[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[{*.json,.*rc,*.yml}]\nindent_style = space\nindent_size = 2\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\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 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 address, without explicit permission\n- Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@preactjs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n---\n\n- [ ] Check if updating to the latest Preact version resolves the issue\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\n\nIf possible, please provide a link to a StackBlitz/CodeSandbox/Codepen project or a GitHub repository that demonstrates the issue. You can use the following template on StackBlitz to get started: https://stackblitz.com/edit/create-preact-starter\n\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. See error\n\n**Expected behavior**\nWhat should have happened when following the steps above?\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: feature request\nassignees: ''\n---\n\n**Describe the feature you'd love to see**\nA clear and concise description of what you'd love to see added to Preact.\n\n**Additional context (optional)**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/workflows/benchmarks.yml",
    "content": "name: Benchmarks\n\non:\n  workflow_dispatch:\n  workflow_call:\n\njobs:\n  prepare:\n    name: Prepare environment\n    runs-on: ubuntu-latest\n    timeout-minutes: 5\n    steps:\n      - name: Download locally built preact package\n        uses: actions/download-artifact@v4\n        with:\n          name: npm-package\n      - run: mv preact.tgz preact-local.tgz\n      - name: Download base package\n        uses: andrewiggins/download-base-artifact@v3\n        with:\n          artifact: npm-package\n          workflow: ci.yml\n          required: true\n      - run: mv preact.tgz preact-main.tgz\n      - name: Upload locally build & base preact package\n        uses: actions/upload-artifact@v4\n        with:\n          name: bench-environment\n          path: |\n            preact-local.tgz\n            preact-main.tgz\n\n  bench_todo:\n    name: Bench todo\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: todo/todo\n      timeout: 10\n\n  bench_text_update:\n    name: Bench text-update\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: text-update/text-update\n      timeout: 10\n\n  bench_many_updates:\n    name: Bench many-updates\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: many-updates/many-updates\n      timeout: 10\n\n  bench_replace1k:\n    name: Bench replace1k\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: table-app/replace1k\n\n  bench_update10th1k:\n    name: Bench 03_update10th1k_x16\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: table-app/update10th1k\n\n  bench_create10k:\n    name: Bench create10k\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: table-app/create10k\n\n  bench_hydrate1k:\n    name: Bench hydrate1k\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: table-app/hydrate1k\n\n  bench_filter_list:\n    name: Bench filter-list\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: filter-list/filter-list\n      timeout: 10"
  },
  {
    "path": ".github/workflows/build-test.yml",
    "content": "name: Build & Test\n\non:\n  workflow_dispatch:\n  workflow_call:\n    inputs:\n      ref:\n        description: 'Branch or tag ref to check out'\n        type: string\n        required: false\n        default: ''\n      artifact_name:\n        description: 'Name of the artifact to upload'\n        type: string\n        required: false\n        default: 'npm-package'\n\njobs:\n  build_test:\n    name: Build & Test\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          ref: ${{ inputs.ref || '' }}\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: 'package.json'\n          cache: 'npm'\n          cache-dependency-path: '**/package-lock.json'\n      - run: npm ci\n      - name: test\n        env:\n          CI: true\n          COVERAGE: true\n          FLAKEY: false\n        # Not using `npm test` since it rebuilds source which npm ci has already done\n        run: npm run lint && npm run test:unit\n      - name: Coveralls GitHub Action\n        uses: coverallsapp/github-action@v2.3.0\n        timeout-minutes: 2\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          fail-on-error: false\n      - name: Package\n        # Use --ignore-scripts here to avoid re-building again before pack\n        run: |\n          npm pack --ignore-scripts\n          mv preact-*.tgz preact.tgz\n      - name: Upload npm package\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ inputs.artifact_name || 'npm-package' }}\n          path: preact.tgz\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - '**'\n  push:\n    branches:\n      - main\n      - restructure\n      - v11\n\njobs:\n  filter_jobs:\n    name: Filter jobs\n    runs-on: ubuntu-latest\n    outputs:\n      jsChanged: ${{ steps.filter.outputs.jsChanged }}\n    steps:\n      - uses: actions/checkout@v4\n      - uses: dorny/paths-filter@v3\n        id: filter\n        with:\n          # Should be kept in sync with the filter in the PR Reporter workflow\n          predicate-quantifier: 'every'\n          filters: |\n            jsChanged:\n              - '**/src/**/*.js'\n              - '!devtools/src/devtools.js'\n\n  compressed_size:\n    name: Compressed Size\n    needs: filter_jobs\n    if: ${{ needs.filter_jobs.outputs.jsChanged == 'true' }}\n    uses: ./.github/workflows/size.yml\n\n  build_test:\n    name: Build & Test\n    needs: filter_jobs\n    uses: ./.github/workflows/build-test.yml\n\n  benchmarks:\n    name: Benchmarks\n    needs: build_test\n    if: ${{ needs.filter_jobs.outputs.jsChanged == 'true' }}\n    uses: ./.github/workflows/benchmarks.yml"
  },
  {
    "path": ".github/workflows/pr-reporter.yml",
    "content": "name: Report Results to PR\n\non:\n  # The pull_request event can't write comments for PRs from forks so using this\n  # workflow_run workflow as a workaround\n  workflow_run:\n    workflows: ['CI']\n    types:\n      - completed\n      - requested\n\njobs:\n  filter_jobs:\n    name: Filter jobs\n    runs-on: ubuntu-latest\n    if: |\n      github.event.workflow_run.event == 'pull_request'\n    outputs:\n      jsChanged: ${{ steps.filter.outputs.jsChanged }}\n    steps:\n      - uses: actions/checkout@v4\n\n      # Warning: This is kinda gnarly and weird! GitHub doesn't expose the `pull_request`\n      # data if the PR is from a fork, nor does it let you access that data via their API\n      # (by querying for PRs associated with the commit or querying the commit itself, both\n      # come up empty for forked commits). As such, to get the base SHA of the PR we need to\n      # query for all PRs on the repo and match the owner+branch to find the right one and\n      # then extract the base SHA from that.\n      #\n      # I see no reason why GitHub shouldn't expose this, it's just an SHA, branch name, and\n      # URL, but they don't so we're doing it this way. Hopefully we can remove this one day.\n      - name: Get PR Base SHA\n        id: get_pr_base_sha\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          FORK_OWNER: ${{ github.event.workflow_run.head_repository.owner.login }}\n          FORK_BRANCH: ${{ github.event.workflow_run.head_branch }}\n        run: |\n          set -euo pipefail\n\n          PR_JSON=$(gh api \"repos/preactjs/preact/pulls?state=all&head=$FORK_OWNER:$FORK_BRANCH\")\n          BASE_SHA=$(jq -r '.[0].base.sha' <<< \"$PR_JSON\")\n\n          echo \"base_sha=$BASE_SHA\" >> \"$GITHUB_OUTPUT\"\n\n      - uses: dorny/paths-filter@v3\n        id: filter\n        with:\n          # As this Workflow is triggered by a `workflow_run` event, the filter action\n          # can't automatically assume we're working with PR data. As such, we need to\n          # wire it up manually with a base (merge target) and ref (source branch).\n          base: ${{ steps.get_pr_base_sha.outputs.base_sha }}\n          ref: ${{ github.event.workflow_run.head_sha }}\n          # Should be kept in sync with the filter in the CI workflow\n          predicate-quantifier: 'every'\n          filters: |\n            jsChanged:\n              - '**/src/**/*.js'\n              - '!devtools/src/devtools.js'\n\n  report_running:\n    name: Report benchmarks are in-progress\n    needs: filter_jobs\n    runs-on: ubuntu-latest\n    # Only add the \"benchmarks are running\" text when a workflow_run is\n    # requested (a.k.a starting)\n    if: |\n      needs.filter_jobs.outputs.jsChanged == 'true' &&\n      github.event.action == 'requested'\n    steps:\n      - name: Report Tachometer Running\n        uses: andrewiggins/tachometer-reporter-action@v2\n        with:\n          # Set initialize to true so this action just creates the comment or\n          # adds the \"benchmarks are running\" text\n          initialize: true\n\n  report_results:\n    name: Report benchmark results\n    needs: filter_jobs\n    runs-on: ubuntu-latest\n    # Only run this job if the event action was \"completed\" and the triggering\n    # workflow_run was successful\n    if: |\n      needs.filter_jobs.outputs.jsChanged == 'true' &&\n      github.event.action == 'completed' &&\n      github.event.workflow_run.conclusion == 'success'\n    steps:\n      # Download the artifact from the triggering workflow that contains the\n      # Tachometer results to report\n      - uses: dawidd6/action-download-artifact@v2\n        with:\n          workflow: ${{ github.event.workflow.id }}\n          run_id: ${{ github.event.workflow_run.id }}\n          name_is_regexp: true\n          name: results-*\n          path: results\n\n      # Create/update the comment with the latest results\n      - name: Report Tachometer Results\n        uses: andrewiggins/tachometer-reporter-action@v2\n        with:\n          path: results/**/*.json\n          base-bench-name: preact-main\n          pr-bench-name: preact-local\n          summarize: 'duration, usedJSHeapSize'"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\non: create\n\njobs:\n  build:\n    if: github.ref_type == 'tag'\n    uses: preactjs/preact/.github/workflows/build-test.yml@main\n\n  release:\n    runs-on: ubuntu-latest\n    needs: build\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/download-artifact@v4\n        with:\n          name: npm-package\n      - name: Create draft release\n        id: create-release\n        uses: actions/github-script@v6\n        with:\n          script: |\n            const script = require('./scripts/release/create-gh-release.js')\n            return script({ github, context })\n      - name: Upload release artifact\n        uses: actions/github-script@v6\n        with:\n          script: |\n            const script = require('./scripts/release/upload-gh-asset.js')\n            return script({ require, github, context, glob, release: ${{ steps.create-release.outputs.result }} })"
  },
  {
    "path": ".github/workflows/run-bench.yml",
    "content": "name: Benchmark Worker\n\n# Expectations:\n#\n# This workflow expects calling workflows to have uploaded an artifact named\n# \"bench-environment\" that contains any built artifacts required to run the\n# benchmark. This typically is the dist/ folder that running `npm run build`\n# produces and/or a tarball of a previous build to bench the local build against\n\non:\n  workflow_call:\n    inputs:\n      benchmark:\n        description: 'The name of the benchmark to run. Should be name of an HTML file without the .html extension'\n        type: string\n        required: true\n      trace:\n        description: 'Whether to capture browser traces for this benchmark run'\n        type: boolean\n        required: false\n        default: false\n      timeout:\n        description: 'How many minutes to give the benchmark to run before timing out and failing'\n        type: number\n        required: false\n        default: 20\n\njobs:\n  run_bench:\n    name: Bench ${{ inputs.benchmark }}\n    runs-on: ubuntu-latest\n    timeout-minutes: ${{ inputs.timeout }}\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          submodules: 'recursive'\n      - uses: actions/setup-node@v4\n        with:\n          node-version-file: 'package.json'\n          cache: 'npm'\n          cache-dependency-path: '**/package-lock.json'\n\n      # Setup pnpm\n      - name: Install pnpm\n        uses: pnpm/action-setup@v3\n        with:\n          version: 8\n          run_install: false\n      - name: Get pnpm store directory\n        id: pnpm-cache\n        run: |\n          echo \"pnpm_cache_dir=$(pnpm store path)\" >> $GITHUB_OUTPUT\n      - uses: actions/cache@v4\n        name: Setup pnpm cache\n        with:\n          path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}\n          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}\n          restore-keys: |\n            ${{ runner.os }}-pnpm-store-\n\n      # Install benchmark dependencies\n      - uses: actions/download-artifact@v4\n        with:\n          name: bench-environment\n      - name: Move tarballs from env to correct location\n        run: |\n          ls -al\n          mv preact-local.tgz benchmarks/dependencies/preact/local-pinned/preact-local-pinned.tgz\n          ls -al benchmarks/dependencies/preact/local-pinned\n          mv preact-main.tgz benchmarks/dependencies/preact/main/preact-main.tgz\n          ls -al benchmarks/dependencies/preact/main\n      - name: Install deps\n        working-directory: benchmarks\n        # Set the CHROMEDRIVER_FILEPATH so the chromedriver npm package uses the\n        # correct binary when its installed\n        run: |\n          export CHROMEDRIVER_FILEPATH=$(which chromedriver)\n          pnpm install\n          # Install local dependencies with --no-frozen-lockfile to ensure local tarballs\n          # are installed regardless of if they match the integrity hash stored in the lockfile\n          pnpm install --no-frozen-lockfile --filter ./dependencies\n\n      # Run benchmark\n      - name: Run benchmark\n        working-directory: benchmarks\n        run: |\n          export CHROMEDRIVER_FILEPATH=$(which chromedriver)\n          pnpm run bench apps/${{ inputs.benchmark }}.html -d preact@local-pinned -d preact@main --trace=${{ inputs.trace }}\n\n      # Prepare output\n      - name: Anaylze logs if present\n        working-directory: benchmarks\n        run: '[ -d out/logs ] && pnpm run analyze ${{ inputs.benchmark }} || echo \"No logs to analyze\"'\n      - name: Tar logs if present\n        working-directory: benchmarks\n        run: |\n          if [ -d out/logs ]; then\n            LOGS_FILE=out/${{ inputs.benchmark }}_logs.tgz\n            mkdir -p $(dirname $LOGS_FILE)\n            tar -zcvf $LOGS_FILE out/logs\n          else\n            echo \"No logs found\"\n          fi\n\n      # Upload results and logs\n      - name: Calculate log artifact name\n        id: log-artifact-name\n        run: |\n          NAME=$(echo \"${{ inputs.benchmark }}\" | sed -r 's/[\\/]+/_/g')\n          echo \"clean_name=$NAME\" >> $GITHUB_OUTPUT\n          echo \"artifact_name=logs_$NAME\" >> $GITHUB_OUTPUT\n      - name: Upload results\n        uses: actions/upload-artifact@v4\n        with:\n          name: results-${{ steps.log-artifact-name.outputs.clean_name }}\n          path: benchmarks/out/results/${{ inputs.benchmark }}.json\n      - name: Upload logs\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ steps.log-artifact-name.outputs.artifact_name }}\n          path: benchmarks/out/${{ inputs.benchmark }}_logs.tgz\n          if-no-files-found: ignore"
  },
  {
    "path": ".github/workflows/single-bench.yml",
    "content": "name: Benchmark Debug\n\non:\n  workflow_dispatch:\n    inputs:\n      benchmark:\n        description: 'Which benchmark to run'\n        type: choice\n        options:\n          - table-app/replace1k\n          - table-app/update10th1k\n          - table-app/create10k\n          - table-app/hydrate1k\n          - filter_list/filter-list\n          - many-updates/many-updates\n          - text-update/text-update\n          - todo/todo\n        required: true\n      base:\n        description: 'The branch name, tag, or commit sha of the version of preact to benchmark against.'\n        type: string\n        default: main\n        required: false\n      trace:\n        description: 'Whether to capture browser traces for this benchmark run'\n        type: boolean\n        default: true\n        required: false\n      # A bug in GitHub actions prevents us from passing numbers (as either\n      # number or string type) to called workflows. So disabling this for now.\n      # See: https://github.com/orgs/community/discussions/67182\n      #\n      # timeout:\n      #   description: 'How many minutes to give the benchmark to run before timing out and failing'\n      #   type: number\n      #   default: 20\n      #   required: false\n\njobs:\n  build_local:\n    name: Build local package\n    uses: ./.github/workflows/ci.yml\n\n  build_base:\n    name: Build base package\n    uses: ./.github/workflows/ci.yml\n    with:\n      ref: ${{ inputs.base }}\n      artifact_name: base-npm-package\n\n  prepare:\n    name: Prepare environment\n    runs-on: ubuntu-latest\n    needs:\n      - build_local\n      - build_base\n    timeout-minutes: 5\n    steps:\n      - name: Download locally built preact package\n        uses: actions/download-artifact@v4\n        with:\n          name: npm-package\n      - run: mv preact.tgz preact-local.tgz\n      - name: Clear working directory\n        run: |\n          ls -al\n          rm -rf *\n          echo \"====================\"\n          ls -al\n      - name: Download base package\n        uses: actions/download-artifact@v4\n        with:\n          name: base-npm-package\n      - run: mv preact.tgz preact-main.tgz\n      - name: Upload locally built & base preact package\n        uses: actions/upload-artifact@v4\n        with:\n          name: bench-environment\n          path: |\n            preact-local.tgz\n            preact-main.tgz\n\n  benchmark:\n    name: Bench ${{ inputs.benchmark }}\n    uses: ./.github/workflows/run-bench.yml\n    needs: prepare\n    with:\n      benchmark: ${{ inputs.benchmark }}\n      trace: ${{ inputs.trace }}\n      # timeout: ${{ inputs.timeout }}"
  },
  {
    "path": ".github/workflows/size.yml",
    "content": "name: Compressed Size\n\non:\n  workflow_call:\n\njobs:\n  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: 'package.json'\n          cache: 'npm'\n          cache-dependency-path: '**/package-lock.json'\n      - uses: preactjs/compressed-size-action@v2\n        with:\n          repo-token: '${{ secrets.GITHUB_TOKEN }}'\n          # Our `prepare` script already builds the app post-install,\n          # building it again would be redundant\n          build-script: 'npm run --if-present noop'"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\nnpm-debug.log\ndist\n*/package-lock.json\nyarn.lock\n.vscode\n.idea\ntest/ts/**/*.js\ncoverage\n*.sw[op]\n*.log\npackage/\npreact-*.tgz\npreact.tgz\n*.local.*\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"benchmarks\"]\n\tpath = benchmarks\n\turl = https://github.com/preactjs/benchmarks\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "npx nano-staged\n"
  },
  {
    "path": ".oxlintrc.json",
    "content": "{\n  \"$schema\": \"./node_modules/oxlint/configuration_schema.json\",\n  \"ignorePatterns\": [\n    \"**/dist/**\",\n    \"benchmarks/**\"\n  ],\n  \"rules\": {\n    \"camelcase\": [\n      1,\n      {\n        \"allow\": [\"__test__*\", \"unstable_*\", \"UNSAFE_*\"]\n      }\n    ],\n    \"no-unused-vars\": [\n      2,\n      {\n        \"args\": \"none\",\n        \"caughtErrors\": \"none\",\n        \"varsIgnorePattern\": \"^h|React|createElement|Fragment$\"\n      }\n    ],\n    \"typescript/no-namespace\": 0,\n    \"no-constant-binary-expression\": 0,\n    \"no-useless-catch\": 0,\n    \"no-empty-pattern\": 0,\n    \"prefer-rest-params\": 0,\n    \"prefer-spread\": 0,\n    \"no-cond-assign\": 0,\n    \"react/jsx-no-bind\": 0,\n    \"react/no-danger\": 0,\n    \"react/no-danger-with-children\": 0,\n    \"react/prefer-stateless-function\": 0,\n    \"react/sort-comp\": 0,\n    \"jest/valid-expect\": 0,\n    \"jest/no-disabled-tests\": 0,\n    \"jest/no-test-callback\": 0,\n    \"jest/expect-expect\": 0,\n    \"jest/no-standalone-expect\": 0,\n    \"jest/no-export\": 0,\n    \"react/no-find-dom-node\": 0,\n    \"react/no-direct-mutation-state\": 0,\n    \"react/no-children-prop\": 0,\n    \"react/jsx-key\": 0,\n    \"react/no-string-refs\": 0,\n    \"react/require-render-return\": 0,\n    \"unicorn/no-new-array\": 0,\n    \"unicorn/prefer-string-starts-ends-with\": 0\n  }\n}\n"
  },
  {
    "path": ".prettierignore",
    "content": ".DS_Store\nnode_modules\nnpm-debug.log\ndist\n*/package-lock.json\nyarn.lock\n.vscode\n.idea\ntest/ts/**/*.js\ncoverage\n*.sw[op]\n*.log\npackage/\npreact-*.tgz\npreact.tgz\n\npackage-lock.json\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nThis document is intended for developers interested in making contributions to Preact and documents our internal processes like releasing a new version.\n\n## Getting Started\n\nThese steps will help you set up your development environment. That includes all dependencies we use to build Preact and developer tooling like git commit hooks.\n\n1. Clone the git repository: `git clone git@github.com:preactjs/preact.git`\n2. Go into the cloned folder: `cd preact/`\n3. Install all dependencies: `npm install`\n\n## The Repo Structure\n\nThis repository contains Preact itself, as well as several addons like the debugging package for example. This is reflected in the directory structure of this repository. Each package has a `src/` folder where the source code can be found, a `test` folder for all sorts of tests that check if the code in `src/` is correct, and a `dist/` folder where you can find the bundled artifacts. Note that the `dist/` folder may not be present initially. It will be created as soon as you run any of the build scripts inside `package.json`. More on that later ;)\n\nA quick overview of our repository:\n\n```bash\n# The repo root (folder where you cloned the repo into)\n/\n  src/  # Source code of our core\n  test/ # Unit tests for core\n  dist/ # Build artifacts for publishing on npm (may not be present)\n\n  # Sub-package, can be imported via `preact/compat` by users.\n  # Compat stands for react-compatibility layer which tries to mirror the\n  # react API as close as possible (mostly legacy APIs)\n  compat/\n  \tsrc/  # Source code of the compat addon\n  \ttest/ # Tests related to the compat addon\n  \tdist/ # Build artifacts for publishing on npm (may not be present)\n\n  # Sub-package, can be imported via `preact/hooks` by users.\n  # The hooks API is an effect based API to deal with component lifecycles.\n  # It's similar to hooks in React\n  hooks/\n  \tsrc/  # Source code of the hooks addon\n  \ttest/ # Tests related to the hooks addon\n  \tdist/ # Build artifacts for publishing on npm (may not be present)\n\n  # Sub-package, can be imported via `preact/debug` by users.\n  # Includes debugging warnings and error messages for common mistakes found\n  # in Preact applications. Also hosts the devtools bridge\n  debug/\n  \tsrc/  # Source code of the debug addon\n  \ttest/ # Tests related to the debug addon\n  \tdist/ # Build artifacts for publishing on npm (may not be present)\n\n  # Sub-package, can be imported via `preact/test-utils` by users.\n  # Provides helpers to make testing Preact applications easier\n  test-utils/\n  \tsrc/  # Source code of the test-utils addon\n  \ttest/ # Tests related to the test-utils addon\n  \tdist/ # Build artifacts for publishing on npm (may not be present)\n\n  # A demo application that we use to debug tricky errors and play with new\n  # features.\n  demo/\n\n  # Contains build scripts and dependencies for development\n  package.json\n```\n\n_Note: The code for rendering Preact on the server lives in another repo and is a completely separate npm package. It can be found here: [https://github.com/preactjs/preact-render-to-string](https://github.com/preactjs/preact-render-to-string)_\n\n### What does `mangle.json` do?\n\nIt's a special file that can be used to specify how `terser` (previously known as `uglify`) will minify variable names. Because each sub-package has its own distribution files we need to ensure that the variable names stay consistent across bundles.\n\n## What does `options.js` do?\n\nUnique to Preact we do support several ways to hook into our renderer. All our addons use that to inject code at different stages of a render process. They are documented in our typings in `internal.d.ts`. The core itself doesn't make use of them, which is why the file only contains an empty `object`.\n\n## Important Branches\n\nWe have a couple of important branches to be aware of:\n\n- `main` - This is the main development branch and represents the upcoming v11 release line.\n- `v10.x` - This branch represents the current stable release line, v10.\n\nAs we have yet to release v11, contributors are welcome to use either branch to build upon. We will try to port changes between the branches when possible, to keep them in sync, but if you're feeling generous, we'd love if you'd submit PRs to both branches!\n\n## Creating your first Pull-Request\n\nWe try to make it as easy as possible to contribute to Preact and make heavy use of GitHub's \"Draft PR\" feature which tags Pull-Requests (short = PR) as work in progress. PRs tend to be published as soon as there is an idea that the developer deems worthwhile to include into Preact and has written some rough code. The PR doesn't have to be perfect or anything really ;)\n\nOnce a PR or a Draft PR has been created our community typically joins the discussion about the proposed change. Sometimes that includes ideas for test cases or even different ways to go about implementing a feature. Often this also includes ideas on how to make the code smaller. We usually refer to the latter as \"code-golfing\" or just \"golfing\".\n\nWhen everything is good to go someone will approve the PR and the changes will be merged into the `main` or `v10.x` branches and we usually cut a release a few days/ a week later.\n\n_The big takeaway for you here is, that we will guide you along the way. We're here to help to make a PR ready for approval!_\n\nThe short summary is:\n\n1. Make changes and submit a PR\n2. Modify change according to feedback (if there is any)\n3. PR will be merged into `main` or `v10.x`\n4. A new release will be cut (every 2-3 weeks).\n\n## Commonly used scripts for contributions\n\nScripts can be executed via `npm run [script]`.\n\n- `build` - compiles all packages ready for publishing to npm\n- `build:core` - builds just Preact itself\n- `build:debug` - builds the debug addon only\n- `build:devtools` - builds the devtools addon only\n- `build:hooks` - builds the hook addon only\n- `build:test-utils` - builds the test-utils addon only\n- `build:compat` - builds the compat addon only\n- `build:jsx` - builds the JSX runtime addon only\n- `test` - Run all tests (linting, TypeScript definitions, unit/integration tests)\n- `test:ts` - Run all tests for TypeScript definitions\n- `test:vitest` - Run all unit/integration tests.\n- `test:vitest:watch` - Same as above, but it will automatically re-run the test suite if a code change was detected.\n\nBut to be fair, the ones we mostly use locally are `build` and `test:vitest:watch`. The other ones are mainly used on our CI pipeline.\n\n_Note: Both `test:vitest` and `test:vitest:watch` listen to the environment variable `COVERAGE=true`. Disabling code coverage can significantly speed up the time it takes to complete the test suite._\n\n_Note2: Individual tests can be executed by appending `.only`:_\n\n```jsx\nit.only('should test something', () => {\n\texpect(1).to.equal(1);\n});\n```\n\n## Common terminology and variable names\n\n- `vnode` -> shorthand for `virtual-node` which is an object that specifies how a Component or DOM-node looks like\n- `commit` -> A commit is the moment in time when you flush all changes to the DOM\n- `c` -> The variable `c` always refers to a `component` instance throughout our code base.\n- `diff/diffing` -> Diffing describes the process of comparing two \"things\". In our case we compare the previous `vnode` tree with the new one and apply the delta to the DOM.\n- `root` -> The topmost node of a `vnode` tree\n\n## Tips for getting to know the code base\n\n- Check the JSDoc block right above the function definition to understand what it does. It contains a short description of each function argument and what it does.\n- Check the callsites of a function to understand how it's used. Modern editors/IDEs allow you to quickly find those, or use the plain old search feature instead.\n\n## Benchmarks\n\nWe have a benchmark suite that we use to measure the performance of Preact. Our benchmark suite lives in our [preactjs/benchmarks repository](https://github.com/preactjs/benchmarks), but is included here as Git submodule. To run the benchmarks, first ensure [PNPM](https://pnpm.io/installation) is installed on your system and initialize and setup the submodule (it uses `pnpm` as a package manager):\n\n```bash\npnpm -v # Make sure pnpm is installed\ngit submodule update --init --recursive\ncd benchmarks\npnpm i\n```\n\nThen you can run the benchmarks:\n\n```bash\n# In the benchmarks folder\npnpm run bench\n```\n\nCheckout the README in the benchmarks folder for more information on running benchmarks.\n\n> **Note:** When switching branches, git submodules are not automatically updated to the commit of the new branch - it stays at the commit of the previous branch. This can be a feature! It allows you to work in different branches with the latest versions of the benchmarks - especially if you have made changes to the benchmarks.\n>\n> However if you want to switch branches and also update the benchmarks to the latest commit of the new branch, you can run `git submodule update --recursive` after switching branches, or run `git checkout --recurse-submodules` when checking out a new branch.\n\n## FAQ\n\n### Why does the JSDoc use TypeScript syntax to specify types?\n\nSeveral members of the team are very fond of TypeScript and we wanted to leverage as many of its advantages, like improved autocompletion, for Preact. We even attempted to port Preact to TypeScript a few times, but we ran into many issues with the DOM typings. Those would force us to fill our codebase with many `any` castings, making our code very noisy.\n\nLuckily TypeScript has a mode where it can somewhat reliably typecheck JavaScript code by reusing the types defined in JSDoc blocks. It's not perfect and it often has trouble inferring the correct types the further one strays away from the function arguments, but it's good enough that it helps us a lot with autocompletion. Another plus is that we can make sure that our TypeScript definitions are correct at the same time.\n\nCheck out the [official TypeScript documentation](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html) for more information.\n\n_Note that we have separate tests for our TypeScript definition files. We only use `ts-check` for local development and don't check it anywhere else like on the CI._\n\n## How to create a good bug report\n\nTo be able to fix issues we need to see them on our machine. This is only possible when we can reproduce the error. The easiest way to do that is narrow down the problem to specific components or combination of them. This can be done by removing as much unrelated code as possible.\n\nThe perfect way to do that is to make a [codesandbox](https://codesandbox.io/). That way you can easily share the problematic code and ensure that others can see the same issue you are seeing.\n\nFor us a [codesandbox](https://codesandbox.io/) says more than a 1000 words :tada:\n\n## I have more questions on how to contribute to Preact. How can I reach you?\n\nWe closely watch our issues and have a pretty active [Slack workspace](https://chat.preactjs.com/). Nearly all our communication happens via these two forms of communication.\n\n## Releasing Preact (Maintainers only)\n\nThis guide is intended for core team members that have the necessary\nrights to publish new releases on npm.\n\n1. Make a PR where **only** the version number is incremented in `package.json` and everywhere else. A simple search and replace works. (note: We follow `SemVer` conventions)\n2. Wait until the PR is approved and merged.\n3. Switch back to the `main` branch and pull the merged PR\n4. Create and push a tag for the new version you want to publish:\n   1. `git tag 10.0.0`\n   2. `git push --tags`\n5. Wait for the Release workflow to complete\n   - It'll create a draft release and upload the built npm package as an asset to the release\n6. [Fill in the release notes](#writing-release-notes) in GitHub and publish them\n7. Run the publish script with the tag you created\n   1. `node ./scripts/release/publish.mjs 10.0.0`\n   2. Make sure you have 2FA enabled in npm, otherwise the above command will fail.\n   3. If you're doing a pre-release add `--npm-tag next` to the `publish.mjs` command to publish it under a different tag (default is `latest`)\n8. Tweet it out\n\n## Legacy Releases (8.x)\n\n> **ATTENTION:** Make sure that you've cleared the project correctly\n> when switching from a 10.x branch.\n\n0. Run `rm -rf dist node_modules && npm i` to make sure to have the correct dependencies.\n1. [Write the release notes](#writing-release-notes) and keep them as a draft in GitHub\n   1. I'd recommend writing them in an offline editor because each edit to a draft will change the URL in GitHub.\n2. Make a PR where **only** the version number is incremented in `package.json` (note: We follow `SemVer` conventions)\n3. Wait until the PR is approved and merged.\n4. Switch back to the `main` branch and pull the merged PR\n5. Run `npm run build && npm publish`\n   1. Make sure you have 2FA enabled in npm, otherwise the above command will fail.\n   2. If you're doing a pre-release add `--tag next` to the `npm publish` command to publish it under a different tag (default is `latest`)\n6. Publish the release notes and create the correct git tag.\n7. Tweet it out\n\n## Writing release notes\n\nThe release notes have become a sort of tiny blog post about what's\nhappening in preact-land. The title usually has this format:\n\n```txt\nVersion Name\n```\n\nExample:\n\n```txt\n10.0.0-beta.1 Los Compresseros\n```\n\nThe name is optional, we just have fun finding creative names :wink:\n\nTo keep them interesting we try to be as\nconcise as possible and to just reflect where we are. There are some\nrules we follow while writing them:\n\n- Be nice, use a positive tone. Avoid negative words\n- Show, don't just tell.\n- Be honest.\n- Don't write too much, keep it simple and short.\n- Avoid making promises and don't overpromise. That leads to unhappy users\n- Avoid framework comparisons if possible\n- Highlight awesome community contributions (or great issue reports)\n- If in doubt, praise the users.\n\nAfter this section we typically follow with a changelog part that's\ndivided into 4 groups in order of importance for the user:\n\n- Features\n- Bug Fixes\n- Typings\n- Maintenance\n\nWe generate it via this handy cli program: [changelogged](https://github.com/marvinhagemeister/changelogged). It will collect and format\nthe descriptions of all PRs that have been merged between two tags.\nThe usual command is `changelogged 10.0.0-rc.2..HEAD` similar to how\nyou'd diff two points in time with git. This will get you 90% there,\nbut you still need to divide it into groups. It's also a good idea\nto unify the formatting of the descriptions, so that they're easier\nto read and don't look like a mess.\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-present Jason Miller\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": "README.md",
    "content": "> [!NOTE]\n> This is the branch for the upcoming release, for patches to v10 you need the [v10.x branch](https://github.com/preactjs/preact/tree/v10.x)\n\n<p align=\"center\">\n<a href=\"https://preactjs.com\" target=\"_blank\">\n\n![Preact](https://raw.githubusercontent.com/preactjs/preact/8b0bcc927995c188eca83cba30fbc83491cc0b2f/logo.svg?sanitize=true 'Preact')\n\n</a>\n</p>\n<p align=\"center\">Fast <b>4kB</b> alternative to React with the same modern API.</p>\n\n**All the power of Virtual DOM components, without the overhead:**\n\n- Familiar React API & patterns: ES6 Class, hooks, and Functional Components\n- Extensive React compatibility via a simple [preact/compat] alias\n- Everything you need: JSX, <abbr title=\"Virtual DOM\">VDOM</abbr>, [DevTools], <abbr title=\"Hot Module Replacement\">HMR</abbr>, <abbr title=\"Server-Side Rendering\">SSR</abbr>.\n- Highly optimized diff algorithm and seamless hydration from Server Side Rendering\n- Supports all modern browsers\n- Transparent asynchronous rendering with a pluggable scheduler\n\n### 💁 More information at the [Preact Website ➞](https://preactjs.com)\n\n<table border=\"0\">\n<tbody>\n<tr>\n<td>\n\n[![npm](https://img.shields.io/npm/v/preact.svg)](https://www.npmjs.com/package/preact)\n[![Preact Slack Community](https://img.shields.io/badge/Slack%20Community-preact.slack.com-blue)](https://chat.preactjs.com)\n[![OpenCollective Backers](https://opencollective.com/preact/backers/badge.svg)](#backers)\n[![OpenCollective Sponsors](https://opencollective.com/preact/sponsors/badge.svg)](#sponsors)\n\n[![coveralls](https://img.shields.io/coveralls/preactjs/preact/main.svg)](https://coveralls.io/github/preactjs/preact)\n[![gzip size](https://img.badgesize.io/https://unpkg.com/preact/dist/preact.min.js?compression=gzip&label=gzip)](https://unpkg.com/preact/dist/preact.min.js)\n[![brotli size](https://img.badgesize.io/https://unpkg.com/preact/dist/preact.min.js?compression=brotli&label=brotli)](https://unpkg.com/preact/dist/preact.min.js)\n\n</td>\n</tr>\n</tbody>\n</table>\n\nYou can find some awesome libraries in the [awesome-preact list](https://github.com/preactjs/awesome-preact) :sunglasses:\n\n---\n\n## Getting Started\n\n> 💁 _**Note:** You [don't need ES2015 to use Preact](https://github.com/developit/preact-in-es3)... but give it a try!_\n\n#### Tutorial: Building UI with Preact\n\nWith Preact, you create user interfaces by assembling trees of components and elements. Components are functions or classes that return a description of what their tree should output. These descriptions are typically written in [JSX](https://react.dev/learn/writing-markup-with-jsx) (shown underneath), or [HTM](https://github.com/developit/htm) which leverages standard JavaScript Tagged Templates. Both syntaxes can express trees of elements with \"props\" (similar to HTML attributes) and children.\n\nTo get started using Preact, first look at the render() function. This function accepts a tree description and creates the structure described. Next, it appends this structure to a parent DOM element provided as the second argument. Future calls to render() will reuse the existing tree and update it in-place in the DOM. Internally, render() will calculate the difference from previous outputted structures in an attempt to perform as few DOM operations as possible.\n\n```js\nimport { h, render } from 'preact';\n// Tells babel to use h for JSX. It's better to configure this globally.\n// See https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#usage\n// In tsconfig you can specify this with the jsxFactory\n/** @jsx h */\n\n// create our tree and append it to document.body:\nrender(\n\t<main>\n\t\t<h1>Hello</h1>\n\t</main>,\n\tdocument.body\n);\n\n// update the tree in-place:\nrender(\n\t<main>\n\t\t<h1>Hello World!</h1>\n\t</main>,\n\tdocument.body\n);\n// ^ this second invocation of render(...) will use a single DOM call to update the text of the <h1>\n```\n\nHooray! render() has taken our structure and output a User Interface! This approach demonstrates a simple case, but would be difficult to use as an application grows in complexity. Each change would be forced to calculate the difference between the current and updated structure for the entire application. Components can help here – by dividing the User Interface into nested Components each can calculate their difference from their mounted point. Here's an example:\n\n```js\nimport { render, h } from 'preact';\nimport { useState } from 'preact/hooks';\n\n/** @jsx h */\n\nconst App = () => {\n\tconst [input, setInput] = useState('');\n\n\treturn (\n\t\t<div>\n\t\t\t<p>Do you agree to the statement: \"Preact is awesome\"?</p>\n\t\t\t<input value={input} onInput={e => setInput(e.target.value)} />\n\t\t</div>\n\t);\n};\n\nrender(<App />, document.body);\n```\n\n---\n\n## Sponsors\n\nBecome a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/preact#sponsor)]\n\n<a href=\"https://opencollective.com/preact/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/4/avatar.svg\"></a>\n<a href=\"https://snyk.co/preact\" target=\"_blank\"><img src=\"https://res.cloudinary.com/snyk/image/upload/snyk-marketingui/brand-logos/wordmark-logo-color.svg\" width=\"192\" height=\"64\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/9/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/10/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/10/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/11/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/11/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/12/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/12/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/13/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/13/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/14/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/14/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/15/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/15/avatar.svg\"></a>\n<a href=\"https://github.com/guardian\" target=\"_blank\"> &nbsp; &nbsp; &nbsp; <img src=\"https://github.com/guardian.png\" width=\"64\" height=\"64\"> &nbsp; &nbsp; &nbsp; </a>\n<a href=\"https://opencollective.com/preact/sponsor/16/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/16/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/17/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/17/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/18/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/18/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/19/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/19/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/20/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/20/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/21/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/21/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/22/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/22/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/23/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/23/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/24/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/24/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/25/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/25/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/26/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/26/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/27/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/27/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/28/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/28/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/sponsor/29/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/sponsor/29/avatar.svg\"></a>\n\n## Backers\n\nSupport us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/preact#backer)]\n\n<a href=\"https://opencollective.com/preact/backer/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/9/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/10/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/10/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/11/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/11/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/12/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/12/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/13/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/13/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/14/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/14/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/15/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/15/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/16/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/16/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/17/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/17/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/18/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/18/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/19/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/19/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/20/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/20/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/21/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/21/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/22/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/22/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/23/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/23/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/24/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/24/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/25/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/25/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/26/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/26/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/27/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/27/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/28/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/28/avatar.svg\"></a>\n<a href=\"https://opencollective.com/preact/backer/29/website\" target=\"_blank\"><img src=\"https://opencollective.com/preact/backer/29/avatar.svg\"></a>\n\n---\n\n## License\n\nMIT\n\n[![Preact](https://i.imgur.com/YqCHvEW.gif)](https://preactjs.com)\n\n[preact/compat]: https://github.com/preactjs/preact/tree/main/compat\n[hyperscript]: https://github.com/dominictarr/hyperscript\n[DevTools]: https://github.com/preactjs/preact-devtools\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = function (api) {\n\tapi.cache(true);\n\n\tconst noModules = String(process.env.BABEL_NO_MODULES) === 'true';\n\n\tconst rename = {};\n\tconst mangle = require('./mangle.json');\n\tfor (let prop in mangle.props.props) {\n\t\tlet name = prop;\n\t\tif (name[0] === '$') {\n\t\t\tname = name.slice(1);\n\t\t}\n\n\t\trename[name] = mangle.props.props[prop];\n\t}\n\n\treturn {\n\t\tpresets: [\n\t\t\t[\n\t\t\t\t'@babel/preset-env',\n\t\t\t\t{\n\t\t\t\t\tloose: true,\n\t\t\t\t\t// Don't transform modules when using esbuild\n\t\t\t\t\tmodules: noModules ? false : 'auto',\n\t\t\t\t\texclude: ['@babel/plugin-transform-typeof-symbol'],\n\t\t\t\t\ttargets: {\n\t\t\t\t\t\tbrowsers: [\n\t\t\t\t\t\t\t'chrome >= 40',\n\t\t\t\t\t\t\t'safari >= 9',\n\t\t\t\t\t\t\t'firefox >= 36',\n\t\t\t\t\t\t\t'edge >= 12',\n\t\t\t\t\t\t\t'not dead'\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t],\n\t\tplugins: [\n\t\t\t'@babel/plugin-transform-react-jsx',\n\t\t\t['babel-plugin-transform-rename-properties', { rename }]\n\t\t],\n\t\tinclude: ['**/src/**/*.js', '**/test/**/*.js'],\n\t\toverrides: [\n\t\t\t{\n\t\t\t\ttest: /(component-stack|debug)\\.test\\.js$/,\n\t\t\t\tplugins: ['@babel/plugin-transform-react-jsx-source']\n\t\t\t}\n\t\t]\n\t};\n};\n"
  },
  {
    "path": "biome.json",
    "content": "{\n  \"formatter\": {\n    \"enabled\": true,\n    \"formatWithErrors\": false,\n    \"indentStyle\": \"tab\",\n    \"indentWidth\": 2,\n    \"lineEnding\": \"lf\",\n    \"lineWidth\": 80,\n    \"attributePosition\": \"auto\",\n    \"includes\": [\n      \"**\",\n      \"!**/.DS_Store\",\n      \"!**/node_modules\",\n      \"!**/npm-debug.log\",\n      \"!**/dist\",\n      \"!**/*/package-lock.json\",\n      \"!**/yarn.lock\",\n      \"!**/.vscode\",\n      \"!**/.idea\",\n      \"!**/test/ts/**/*.js\",\n      \"!**/coverage\",\n      \"!**/*.sw\\\\[op\\\\]\",\n      \"!**/*.log\",\n      \"!**/package/\",\n      \"!**/preact-*.tgz\",\n      \"!**/preact.tgz\",\n      \"!**/package-lock.json\"\n    ]\n  },\n  \"assist\": { \"actions\": { \"source\": { \"organizeImports\": \"on\" } } },\n  \"linter\": { \"enabled\": true, \"rules\": { \"recommended\": true } },\n  \"javascript\": {\n    \"formatter\": {\n      \"jsxQuoteStyle\": \"double\",\n      \"quoteProperties\": \"asNeeded\",\n      \"trailingCommas\": \"none\",\n      \"semicolons\": \"always\",\n      \"arrowParentheses\": \"asNeeded\",\n      \"bracketSpacing\": true,\n      \"bracketSameLine\": false,\n      \"quoteStyle\": \"single\",\n      \"attributePosition\": \"auto\"\n    }\n  },\n  \"overrides\": [\n    {\n      \"includes\": [\"**/*.json\", \"**/.*rc/**\", \"**/*.yml\"],\n      \"formatter\": { \"indentWidth\": 2, \"indentStyle\": \"space\" }\n    }\n  ]\n}\n"
  },
  {
    "path": "compat/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-present Jason Miller\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": "compat/client.d.ts",
    "content": "import * as preact from '../src/index';\n\nexport function createRoot(container: preact.ContainerNode): {\n\trender(children: preact.ComponentChild): void;\n\tunmount(): void;\n};\n\nexport function hydrateRoot(\n\tcontainer: preact.ContainerNode,\n\tchildren: preact.ComponentChild\n): ReturnType<typeof createRoot>;\n"
  },
  {
    "path": "compat/client.js",
    "content": "const { render, hydrate, unmountComponentAtNode } = require('preact/compat');\n\nfunction createRoot(container) {\n\treturn {\n\t\t// eslint-disable-next-line\n\t\trender: function (children) {\n\t\t\trender(children, container);\n\t\t},\n\t\t// eslint-disable-next-line\n\t\tunmount: function () {\n\t\t\tunmountComponentAtNode(container);\n\t\t}\n\t};\n}\n\nexports.createRoot = createRoot;\n\nexports.hydrateRoot = function (container, children) {\n\thydrate(children, container);\n\treturn createRoot(container);\n};\n"
  },
  {
    "path": "compat/client.mjs",
    "content": "import { render, hydrate, unmountComponentAtNode } from 'preact/compat';\n\nexport function createRoot(container) {\n\treturn {\n\t\t// eslint-disable-next-line\n\t\trender: function (children) {\n\t\t\trender(children, container);\n\t\t},\n\t\t// eslint-disable-next-line\n\t\tunmount: function () {\n\t\t\tunmountComponentAtNode(container);\n\t\t}\n\t};\n}\n\nexport function hydrateRoot(container, children) {\n\thydrate(children, container);\n\treturn createRoot(container);\n}\n\nexport default {\n\tcreateRoot,\n\thydrateRoot\n};\n"
  },
  {
    "path": "compat/jsx-dev-runtime.js",
    "content": "require('preact/compat');\n\nmodule.exports = require('preact/jsx-runtime');\n"
  },
  {
    "path": "compat/jsx-dev-runtime.mjs",
    "content": "import 'preact/compat';\n\nexport * from 'preact/jsx-runtime';\n"
  },
  {
    "path": "compat/jsx-runtime.js",
    "content": "require('preact/compat');\n\nmodule.exports = require('preact/jsx-runtime');\n"
  },
  {
    "path": "compat/jsx-runtime.mjs",
    "content": "import 'preact/compat';\n\nexport * from 'preact/jsx-runtime';\n"
  },
  {
    "path": "compat/mangle.json",
    "content": "{\n  \"help\": {\n    \"what is this file?\": \"It controls protected/private property mangling so that minified builds have consistent property names.\",\n    \"why are there duplicate minified properties?\": \"Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size.\"\n  },\n  \"minify\": {\n    \"mangle\": {\n      \"properties\": {\n        \"regex\": \"^_[^_]\",\n        \"reserved\": [\n          \"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\",\n          \"__REACT_DEVTOOLS_GLOBAL_HOOK__\",\n          \"__PREACT_DEVTOOLS__\",\n          \"_renderers\",\n          \"__source\",\n          \"__self\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "compat/package.json",
    "content": "{\n  \"name\": \"preact-compat\",\n  \"amdName\": \"preactCompat\",\n  \"private\": true,\n  \"description\": \"A React compatibility layer for Preact\",\n  \"main\": \"dist/compat.js\",\n  \"module\": \"dist/compat.mjs\",\n  \"umd:main\": \"dist/compat.umd.js\",\n  \"source\": \"src/index.js\",\n  \"types\": \"src/index.d.ts\",\n  \"license\": \"MIT\",\n  \"mangle\": {\n    \"regex\": \"^_\"\n  },\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "compat/scheduler.d.ts",
    "content": "export var unstable_ImmediatePriority: number;\nexport var unstable_UserBlockingPriority: number;\nexport var unstable_NormalPriority: number;\nexport var unstable_LowPriority: number;\nexport var unstable_IdlePriority: number;\n\nexport function unstable_runWithPriority(\n\tpriority: number,\n\tcallback: () => void\n): void;\n\nexport var unstable_now: DOMHighResTimeStamp;\n"
  },
  {
    "path": "compat/scheduler.js",
    "content": "// see scheduler.mjs\n\nfunction unstable_runWithPriority(priority, callback) {\n\treturn callback();\n}\n\nmodule.exports = {\n\tunstable_ImmediatePriority: 1,\n\tunstable_UserBlockingPriority: 2,\n\tunstable_NormalPriority: 3,\n\tunstable_LowPriority: 4,\n\tunstable_IdlePriority: 5,\n\tunstable_runWithPriority,\n\tunstable_now: performance.now.bind(performance)\n};\n"
  },
  {
    "path": "compat/scheduler.mjs",
    "content": "/* eslint-disable */\n\n// This file includes experimental React APIs exported from the \"scheduler\"\n// npm package. Despite being explicitely marked as unstable some libraries\n// already make use of them. This file is not a full replacement for the\n// scheduler package, but includes the necessary shims to make those libraries\n// work with Preact.\n\nexport var unstable_ImmediatePriority = 1;\nexport var unstable_UserBlockingPriority = 2;\nexport var unstable_NormalPriority = 3;\nexport var unstable_LowPriority = 4;\nexport var unstable_IdlePriority = 5;\n\n/**\n * @param {number} priority\n * @param {() => void} callback\n */\nexport function unstable_runWithPriority(priority, callback) {\n\treturn callback();\n}\n\nexport var unstable_now = performance.now.bind(performance);\n"
  },
  {
    "path": "compat/server.browser.js",
    "content": "import { renderToString } from 'preact-render-to-string';\n\nexport {\n\trenderToString,\n\trenderToString as renderToStaticMarkup\n} from 'preact-render-to-string';\n\nexport default {\n\trenderToString,\n\trenderToStaticMarkup: renderToString\n};\n"
  },
  {
    "path": "compat/server.d.ts",
    "content": "// @ts-nocheck TS loses its mind over the mixed module systems here.\n// It's not ideal, but works at runtime and we're not shipping mixed type definitions.\n\nimport { renderToString } from 'preact-render-to-string';\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\nexport {\n\trenderToString,\n\trenderToString as renderToStaticMarkup\n} from 'preact-render-to-string';\n\nexport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\nexport { renderToReadableStream } from 'preact-render-to-string/stream';\nexport = {\n\trenderToString: typeof renderToString,\n\trenderToStaticMarkup: typeof renderToString,\n\trenderToPipeableStream: typeof renderToPipeableStream,\n\trenderToReadableStream: typeof renderToReadableStream\n};\n"
  },
  {
    "path": "compat/server.js",
    "content": "/* eslint-disable */\nvar renderToString;\ntry {\n\tconst mod = require('preact-render-to-string');\n\trenderToString = mod.default || mod.renderToString || mod;\n} catch (e) {\n\tthrow Error(\n\t\t'renderToString() error: missing \"preact-render-to-string\" dependency.'\n\t);\n}\n\nvar renderToReadableStream;\ntry {\n\tconst mod = require('preact-render-to-string/stream');\n\trenderToReadableStream = mod.default || mod.renderToReadableStream || mod;\n} catch (e) {\n\tthrow Error(\n\t\t'renderToReadableStream() error: update \"preact-render-to-string\" dependency to at least 6.5.0.'\n\t);\n}\nvar renderToPipeableStream;\ntry {\n\tconst mod = require('preact-render-to-string/stream-node');\n\trenderToPipeableStream = mod.default || mod.renderToPipeableStream || mod;\n} catch (e) {\n\tthrow Error(\n\t\t'renderToPipeableStream() error: update \"preact-render-to-string\" dependency to at least 6.5.0.'\n\t);\n}\n\nmodule.exports = {\n\trenderToString: renderToString,\n\trenderToStaticMarkup: renderToString,\n\trenderToPipeableStream: renderToPipeableStream,\n\trenderToReadableStream: renderToReadableStream\n};\n"
  },
  {
    "path": "compat/server.mjs",
    "content": "import { renderToString } from 'preact-render-to-string';\nimport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\nimport { renderToReadableStream } from 'preact-render-to-string/stream';\n\nexport {\n\trenderToString,\n\trenderToString as renderToStaticMarkup\n} from 'preact-render-to-string';\n\nexport { renderToPipeableStream } from 'preact-render-to-string/stream-node';\nexport { renderToReadableStream } from 'preact-render-to-string/stream';\nexport default {\n\trenderToString,\n\trenderToStaticMarkup: renderToString,\n\trenderToPipeableStream,\n\trenderToReadableStream\n};\n"
  },
  {
    "path": "compat/src/Children.js",
    "content": "import { toChildArray } from 'preact';\n\nconst mapFn = (children, fn, context) => {\n\tif (children == null) return null;\n\treturn toChildArray(toChildArray(children).map(fn.bind(context)));\n};\n\n// This API is completely unnecessary for Preact, so it's basically passthrough.\nexport const Children = {\n\tmap: mapFn,\n\tforEach: mapFn,\n\tcount(children) {\n\t\treturn children ? toChildArray(children).length : 0;\n\t},\n\tonly(children) {\n\t\tconst normalized = toChildArray(children);\n\t\tif (normalized.length !== 1) throw 'Children.only';\n\t\treturn normalized[0];\n\t},\n\ttoArray: toChildArray\n};\n"
  },
  {
    "path": "compat/src/PureComponent.js",
    "content": "import { Component } from 'preact';\nimport { shallowDiffers } from './util';\n\n/**\n * Component class with a predefined `shouldComponentUpdate` implementation\n */\nexport function PureComponent(p, c) {\n\tthis.props = p;\n\tthis.context = c;\n}\nPureComponent.prototype = new Component();\n// Some third-party libraries check if this property is present\nPureComponent.prototype.isPureReactComponent = true;\nPureComponent.prototype.shouldComponentUpdate = function (props, state) {\n\treturn shallowDiffers(this.props, props) || shallowDiffers(this.state, state);\n};\n"
  },
  {
    "path": "compat/src/forwardRef.js",
    "content": "import { assign } from './util';\n\nexport const REACT_FORWARD_SYMBOL = Symbol.for('react.forward_ref');\n\n/**\n * Pass ref down to a child. This is mainly used in libraries with HOCs that\n * wrap components. Using `forwardRef` there is an easy way to get a reference\n * of the wrapped component instead of one of the wrapper itself.\n * @param {import('./index').ForwardRefRenderFunction} fn\n * @returns {import('./internal').FunctionComponent}\n */\nexport function forwardRef(fn) {\n\tfunction Forwarded(props) {\n\t\tlet clone = assign({}, props);\n\t\tdelete clone.ref;\n\t\treturn fn(clone, props.ref || null);\n\t}\n\n\t// mobx-react checks for this being present\n\tForwarded.$$typeof = REACT_FORWARD_SYMBOL;\n\t// mobx-react heavily relies on implementation details.\n\t// It expects an object here with a `render` property,\n\t// and prototype.render will fail. Without this\n\t// mobx-react throws.\n\tForwarded.render = fn;\n\n\tForwarded.prototype.isReactComponent = true;\n\tForwarded.displayName = 'ForwardRef(' + (fn.displayName || fn.name) + ')';\n\n\treturn Forwarded;\n}\n"
  },
  {
    "path": "compat/src/hooks.js",
    "content": "import { useState, useLayoutEffect, useEffect } from 'preact/hooks';\n\n/**\n * This is taken from https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84\n * on a high level this cuts out the warnings, ... and attempts a smaller implementation\n * @typedef {{ _value: any; _getSnapshot: () => any }} Store\n */\nexport function useSyncExternalStore(subscribe, getSnapshot) {\n\tconst value = getSnapshot();\n\n\t/**\n\t * @typedef {{ _instance: Store }} StoreRef\n\t * @type {[StoreRef, (store: StoreRef) => void]}\n\t */\n\tconst [{ _instance }, forceUpdate] = useState({\n\t\t_instance: { _value: value, _getSnapshot: getSnapshot }\n\t});\n\n\tuseLayoutEffect(() => {\n\t\t_instance._value = value;\n\t\t_instance._getSnapshot = getSnapshot;\n\n\t\tif (didSnapshotChange(_instance)) {\n\t\t\tforceUpdate({ _instance });\n\t\t}\n\t}, [subscribe, value, getSnapshot]);\n\n\tuseEffect(() => {\n\t\tif (didSnapshotChange(_instance)) {\n\t\t\tforceUpdate({ _instance });\n\t\t}\n\n\t\treturn subscribe(() => {\n\t\t\tif (didSnapshotChange(_instance)) {\n\t\t\t\tforceUpdate({ _instance });\n\t\t\t}\n\t\t});\n\t}, [subscribe]);\n\n\treturn value;\n}\n\n/** @type {(inst: Store) => boolean} */\nfunction didSnapshotChange(inst) {\n\ttry {\n\t\treturn !Object.is(inst._value, inst._getSnapshot());\n\t} catch (error) {\n\t\treturn true;\n\t}\n}\n\nexport function startTransition(cb) {\n\tcb();\n}\n\nexport function useDeferredValue(val) {\n\treturn val;\n}\n\nexport function useTransition() {\n\treturn [false, startTransition];\n}\n\n// TODO: in theory this should be done after a VNode is diffed as we want to insert\n// styles/... before it attaches\nexport const useInsertionEffect = useLayoutEffect;\n"
  },
  {
    "path": "compat/src/index.d.ts",
    "content": "import * as _preact from '../../src/index';\nimport { JSXInternal } from '../../src/jsx';\nimport * as _hooks from '../../hooks';\nimport * as _Suspense from './suspense';\n\ndeclare namespace preact {\n\texport interface FunctionComponent<P = {}> {\n\t\t(\n\t\t\tprops: _preact.RenderableProps<P>,\n\t\t\tcontext?: any\n\t\t): _preact.ComponentChildren;\n\t\tdisplayName?: string;\n\t\tdefaultProps?: Partial<P> | undefined;\n\t}\n\n\texport interface ComponentClass<P = {}, S = {}> {\n\t\tnew (props: P, context?: any): _preact.Component<P, S>;\n\t\tdisplayName?: string;\n\t\tdefaultProps?: Partial<P>;\n\t\tcontextType?: _preact.Context<any>;\n\t\tgetDerivedStateFromProps?(\n\t\t\tprops: Readonly<P>,\n\t\t\tstate: Readonly<S>\n\t\t): Partial<S> | null;\n\t\tgetDerivedStateFromError?(error: any): Partial<S> | null;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\n\texport interface Component<P = {}, S = {}> {\n\t\tcomponentWillMount?(): void;\n\t\tcomponentDidMount?(): void;\n\t\tcomponentWillUnmount?(): void;\n\t\tgetChildContext?(): object;\n\t\tcomponentWillReceiveProps?(nextProps: Readonly<P>, nextContext: any): void;\n\t\tshouldComponentUpdate?(\n\t\t\tnextProps: Readonly<P>,\n\t\t\tnextState: Readonly<S>,\n\t\t\tnextContext: any\n\t\t): boolean;\n\t\tcomponentWillUpdate?(\n\t\t\tnextProps: Readonly<P>,\n\t\t\tnextState: Readonly<S>,\n\t\t\tnextContext: any\n\t\t): void;\n\t\tgetSnapshotBeforeUpdate?(oldProps: Readonly<P>, oldState: Readonly<S>): any;\n\t\tcomponentDidUpdate?(\n\t\t\tpreviousProps: Readonly<P>,\n\t\t\tpreviousState: Readonly<S>,\n\t\t\tsnapshot: any\n\t\t): void;\n\t\tcomponentDidCatch?(error: any, errorInfo: _preact.ErrorInfo): void;\n\t}\n\n\texport abstract class Component<P, S> {\n\t\tconstructor(props?: P, context?: any);\n\n\t\tstatic displayName?: string;\n\t\tstatic defaultProps?: any;\n\t\tstatic contextType?: _preact.Context<any>;\n\n\t\t// Static members cannot reference class type parameters. This is not\n\t\t// supported in TypeScript. Reusing the same type arguments from `Component`\n\t\t// will lead to an impossible state where one cannot satisfy the type\n\t\t// constraint under no circumstances, see #1356.In general type arguments\n\t\t// seem to be a bit buggy and not supported well at the time of this\n\t\t// writing with TS 3.3.3333.\n\t\tstatic getDerivedStateFromProps?(\n\t\t\tprops: Readonly<object>,\n\t\t\tstate: Readonly<object>\n\t\t): object | null;\n\t\tstatic getDerivedStateFromError?(error: any): object | null;\n\n\t\tstate: Readonly<S>;\n\t\tprops: _preact.RenderableProps<P>;\n\t\tcontext: any;\n\n\t\t// From https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e836acc75a78cf0655b5dfdbe81d69fdd4d8a252/types/react/index.d.ts#L402\n\t\t// // We MUST keep setState() as a unified signature because it allows proper checking of the method return type.\n\t\t// // See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257\n\t\tsetState<K extends keyof S>(\n\t\t\tstate:\n\t\t\t\t| ((\n\t\t\t\t\t\tprevState: Readonly<S>,\n\t\t\t\t\t\tprops: Readonly<P>\n\t\t\t\t  ) => Pick<S, K> | Partial<S> | null)\n\t\t\t\t| (Pick<S, K> | Partial<S> | null),\n\t\t\tcallback?: () => void\n\t\t): void;\n\n\t\tforceUpdate(callback?: () => void): void;\n\n\t\tabstract render(\n\t\t\tprops?: _preact.RenderableProps<P>,\n\t\t\tstate?: Readonly<S>,\n\t\t\tcontext?: any\n\t\t): _preact.ComponentChildren;\n\t}\n}\n\n// export default React;\nexport = React;\nexport as namespace React;\ndeclare namespace React {\n\t// Export JSX\n\texport import JSX = JSXInternal;\n\n\t// Hooks\n\texport import CreateHandle = _hooks.CreateHandle;\n\texport import EffectCallback = _hooks.EffectCallback;\n\texport import Inputs = _hooks.Inputs;\n\texport import Reducer = _hooks.Reducer;\n\texport import Dispatch = _hooks.Dispatch;\n\texport import SetStateAction = _hooks.StateUpdater;\n\texport import useCallback = _hooks.useCallback;\n\texport import useContext = _hooks.useContext;\n\texport import useDebugValue = _hooks.useDebugValue;\n\texport import useEffect = _hooks.useEffect;\n\texport import useImperativeHandle = _hooks.useImperativeHandle;\n\texport import useId = _hooks.useId;\n\texport import useLayoutEffect = _hooks.useLayoutEffect;\n\texport import useMemo = _hooks.useMemo;\n\texport import useReducer = _hooks.useReducer;\n\texport import useRef = _hooks.useRef;\n\texport import useState = _hooks.useState;\n\t// React 18 hooks\n\texport import useInsertionEffect = _hooks.useLayoutEffect;\n\texport function useTransition(): [false, typeof startTransition];\n\texport function useDeferredValue<T = any>(val: T): T;\n\texport function useSyncExternalStore<T>(\n\t\tsubscribe: (flush: () => void) => () => void,\n\t\tgetSnapshot: () => T\n\t): T;\n\n\t// Preact Defaults\n\texport import Context = _preact.Context;\n\texport import ContextType = _preact.ContextType;\n\texport import RefObject = _preact.RefObject;\n\texport import Component = preact.Component;\n\texport import FunctionComponent = preact.FunctionComponent;\n\texport import ComponentType = _preact.ComponentType;\n\texport import ComponentClass = preact.ComponentClass;\n\texport import FC = _preact.FunctionComponent;\n\texport import createContext = _preact.createContext;\n\texport import Ref = _preact.Ref;\n\texport import createRef = _preact.createRef;\n\texport import Fragment = _preact.Fragment;\n\texport import createElement = _preact.createElement;\n\texport import cloneElement = _preact.cloneElement;\n\texport import ComponentProps = _preact.ComponentProps;\n\texport import ReactNode = _preact.ComponentChild;\n\texport import ReactElement = _preact.VNode;\n\texport import Consumer = _preact.Consumer;\n\texport import ErrorInfo = _preact.ErrorInfo;\n\texport import Key = _preact.Key;\n\n\t// Suspense\n\texport import Suspense = _Suspense.Suspense;\n\texport import lazy = _Suspense.lazy;\n\n\t// Compat\n\texport import StrictMode = _preact.Fragment;\n\texport const version: string;\n\texport function startTransition(cb: () => void): void;\n\n\t// HTML\n\texport interface HTMLAttributes<T extends EventTarget>\n\t\textends _preact.HTMLAttributes<T> {}\n\texport interface HTMLProps<T extends EventTarget>\n\t\textends _preact.AllHTMLAttributes<T>,\n\t\t\t_preact.ClassAttributes<T> {}\n\texport interface AllHTMLAttributes<T extends EventTarget>\n\t\textends _preact.AllHTMLAttributes<T> {}\n\texport import DetailedHTMLProps = _preact.DetailedHTMLProps;\n\texport import CSSProperties = _preact.CSSProperties;\n\n\texport interface SVGProps<T extends EventTarget>\n\t\textends _preact.SVGAttributes<T>,\n\t\t\t_preact.ClassAttributes<T> {}\n\n\tinterface SVGAttributes<T extends EventTarget = SVGElement>\n\t\textends _preact.SVGAttributes<T> {}\n\n\tinterface ReactSVG extends JSXInternal.IntrinsicSVGElements {}\n\n\texport import AriaAttributes = _preact.AriaAttributes;\n\n\texport import HTMLAttributeReferrerPolicy = _preact.HTMLAttributeReferrerPolicy;\n\texport import HTMLAttributeAnchorTarget = _preact.HTMLAttributeAnchorTarget;\n\texport import HTMLInputTypeAttribute = _preact.HTMLInputTypeAttribute;\n\texport import HTMLAttributeCrossOrigin = _preact.HTMLAttributeCrossOrigin;\n\n\texport import AnchorHTMLAttributes = _preact.AnchorHTMLAttributes;\n\texport import AudioHTMLAttributes = _preact.AudioHTMLAttributes;\n\texport import AreaHTMLAttributes = _preact.AreaHTMLAttributes;\n\texport import BaseHTMLAttributes = _preact.BaseHTMLAttributes;\n\texport import BlockquoteHTMLAttributes = _preact.BlockquoteHTMLAttributes;\n\texport import ButtonHTMLAttributes = _preact.ButtonHTMLAttributes;\n\texport import CanvasHTMLAttributes = _preact.CanvasHTMLAttributes;\n\texport import ColHTMLAttributes = _preact.ColHTMLAttributes;\n\texport import ColgroupHTMLAttributes = _preact.ColgroupHTMLAttributes;\n\texport import DataHTMLAttributes = _preact.DataHTMLAttributes;\n\texport import DetailsHTMLAttributes = _preact.DetailsHTMLAttributes;\n\texport import DelHTMLAttributes = _preact.DelHTMLAttributes;\n\texport import DialogHTMLAttributes = _preact.DialogHTMLAttributes;\n\texport import EmbedHTMLAttributes = _preact.EmbedHTMLAttributes;\n\texport import FieldsetHTMLAttributes = _preact.FieldsetHTMLAttributes;\n\texport import FormHTMLAttributes = _preact.FormHTMLAttributes;\n\texport import IframeHTMLAttributes = _preact.IframeHTMLAttributes;\n\texport import ImgHTMLAttributes = _preact.ImgHTMLAttributes;\n\texport import InsHTMLAttributes = _preact.InsHTMLAttributes;\n\texport import InputHTMLAttributes = _preact.InputHTMLAttributes;\n\texport import KeygenHTMLAttributes = _preact.KeygenHTMLAttributes;\n\texport import LabelHTMLAttributes = _preact.LabelHTMLAttributes;\n\texport import LiHTMLAttributes = _preact.LiHTMLAttributes;\n\texport import LinkHTMLAttributes = _preact.LinkHTMLAttributes;\n\texport import MapHTMLAttributes = _preact.MapHTMLAttributes;\n\texport import MenuHTMLAttributes = _preact.MenuHTMLAttributes;\n\texport import MediaHTMLAttributes = _preact.MediaHTMLAttributes;\n\texport import MetaHTMLAttributes = _preact.MetaHTMLAttributes;\n\texport import MeterHTMLAttributes = _preact.MeterHTMLAttributes;\n\texport import QuoteHTMLAttributes = _preact.QuoteHTMLAttributes;\n\texport import ObjectHTMLAttributes = _preact.ObjectHTMLAttributes;\n\texport import OlHTMLAttributes = _preact.OlHTMLAttributes;\n\texport import OptgroupHTMLAttributes = _preact.OptgroupHTMLAttributes;\n\texport import OptionHTMLAttributes = _preact.OptionHTMLAttributes;\n\texport import OutputHTMLAttributes = _preact.OutputHTMLAttributes;\n\texport import ParamHTMLAttributes = _preact.ParamHTMLAttributes;\n\texport import ProgressHTMLAttributes = _preact.ProgressHTMLAttributes;\n\texport import SlotHTMLAttributes = _preact.SlotHTMLAttributes;\n\texport import ScriptHTMLAttributes = _preact.ScriptHTMLAttributes;\n\texport import SelectHTMLAttributes = _preact.SelectHTMLAttributes;\n\texport import SourceHTMLAttributes = _preact.SourceHTMLAttributes;\n\texport import StyleHTMLAttributes = _preact.StyleHTMLAttributes;\n\texport import TableHTMLAttributes = _preact.TableHTMLAttributes;\n\texport import TextareaHTMLAttributes = _preact.TextareaHTMLAttributes;\n\texport import TdHTMLAttributes = _preact.TdHTMLAttributes;\n\texport import ThHTMLAttributes = _preact.ThHTMLAttributes;\n\texport import TimeHTMLAttributes = _preact.TimeHTMLAttributes;\n\texport import TrackHTMLAttributes = _preact.TrackHTMLAttributes;\n\texport import VideoHTMLAttributes = _preact.VideoHTMLAttributes;\n\n\t// Events\n\texport import TargetedEvent = _preact.TargetedEvent;\n\texport import ChangeEvent = _preact.TargetedEvent;\n\texport import ClipboardEvent = _preact.TargetedClipboardEvent;\n\texport import CompositionEvent = _preact.TargetedCompositionEvent;\n\texport import DragEvent = _preact.TargetedDragEvent;\n\texport import PointerEvent = _preact.TargetedPointerEvent;\n\texport import FocusEvent = _preact.TargetedFocusEvent;\n\texport import FormEvent = _preact.TargetedEvent;\n\texport import InvalidEvent = _preact.TargetedEvent;\n\texport import KeyboardEvent = _preact.TargetedKeyboardEvent;\n\texport import MouseEvent = _preact.TargetedMouseEvent;\n\texport import TouchEvent = _preact.TargetedTouchEvent;\n\texport import UIEvent = _preact.TargetedUIEvent;\n\texport import AnimationEvent = _preact.TargetedAnimationEvent;\n\texport import TransitionEvent = _preact.TargetedTransitionEvent;\n\n\t// Event Handler Types\n\texport import EventHandler = _preact.EventHandler;\n\texport import ChangeEventHandler = _preact.GenericEventHandler;\n\texport import ClipboardEventHandler = _preact.ClipboardEventHandler;\n\texport import CompositionEventHandler = _preact.CompositionEventHandler;\n\texport import DragEventHandler = _preact.DragEventHandler;\n\texport import PointerEventHandler = _preact.PointerEventHandler;\n\texport import FocusEventHandler = _preact.FocusEventHandler;\n\texport import FormEventHandler = _preact.GenericEventHandler;\n\texport import InvalidEventHandler = _preact.GenericEventHandler;\n\texport import KeyboardEventHandler = _preact.KeyboardEventHandler;\n\texport import MouseEventHandler = _preact.MouseEventHandler;\n\texport import TouchEventHandler = _preact.TouchEventHandler;\n\texport import UIEventHandler = _preact.UIEventHandler;\n\texport import AnimationEventHandler = _preact.AnimationEventHandler;\n\texport import TransitionEventHandler = _preact.TransitionEventHandler;\n\n\texport function createPortal(\n\t\tvnode: _preact.ComponentChildren,\n\t\tcontainer: _preact.ContainerNode\n\t): _preact.VNode<any>;\n\n\texport function render(\n\t\tvnode: _preact.ComponentChild,\n\t\tparent: _preact.ContainerNode,\n\t\tcallback?: () => void\n\t): Component | null;\n\n\texport function hydrate(\n\t\tvnode: _preact.ComponentChild,\n\t\tparent: _preact.ContainerNode,\n\t\tcallback?: () => void\n\t): Component | null;\n\n\texport function unmountComponentAtNode(\n\t\tcontainer: _preact.ContainerNode\n\t): boolean;\n\n\texport function createFactory(\n\t\ttype: _preact.VNode<any>['type']\n\t): (\n\t\tprops?: any,\n\t\t...children: _preact.ComponentChildren[]\n\t) => _preact.VNode<any>;\n\texport function isValidElement(element: any): boolean;\n\texport function isFragment(element: any): boolean;\n\texport function isMemo(element: any): boolean;\n\texport function findDOMNode(\n\t\tcomponent: _preact.Component | Element\n\t): Element | null;\n\n\texport abstract class PureComponent<\n\t\tP = {},\n\t\tS = {},\n\t\tSS = any\n\t> extends _preact.Component<P, S> {\n\t\tisPureReactComponent: boolean;\n\t}\n\n\texport type MemoExoticComponent<C extends _preact.FunctionalComponent<any>> =\n\t\t_preact.FunctionComponent<ComponentProps<C>> & {\n\t\t\treadonly type: C;\n\t\t};\n\n\texport function memo<P = {}>(\n\t\tcomponent: _preact.FunctionalComponent<P>,\n\t\tcomparer?: (prev: P, next: P) => boolean\n\t): _preact.FunctionComponent<P>;\n\texport function memo<C extends _preact.FunctionalComponent<any>>(\n\t\tcomponent: C,\n\t\tcomparer?: (\n\t\t\tprev: _preact.ComponentProps<C>,\n\t\t\tnext: _preact.ComponentProps<C>\n\t\t) => boolean\n\t): C;\n\n\texport interface RefAttributes<R> extends _preact.Attributes {\n\t\tref?: _preact.Ref<R> | undefined;\n\t}\n\n\texport interface ForwardRefRenderFunction<T = any, P = {}> {\n\t\t(props: P, ref: ForwardedRef<T>): _preact.ComponentChild;\n\t\tdisplayName?: string;\n\t}\n\n\texport interface ForwardRefExoticComponent<P>\n\t\textends _preact.FunctionComponent<P> {\n\t\tdefaultProps?: Partial<P> | undefined;\n\t}\n\n\texport function forwardRef<R, P = {}>(\n\t\tfn: ForwardRefRenderFunction<R, P>\n\t): _preact.FunctionalComponent<PropsWithoutRef<P> & { ref?: _preact.Ref<R> }>;\n\n\texport type PropsWithoutRef<P> = Omit<P, 'ref'>;\n\n\tinterface MutableRefObject<T> {\n\t\tcurrent: T;\n\t}\n\n\texport type ForwardedRef<T> =\n\t\t| ((instance: T | null) => void)\n\t\t| MutableRefObject<T | null>\n\t\t| null;\n\n\texport type ElementType<\n\t\tP = any,\n\t\tTag extends keyof JSX.IntrinsicElements = keyof JSX.IntrinsicElements\n\t> =\n\t\t| { [K in Tag]: P extends JSX.IntrinsicElements[K] ? K : never }[Tag]\n\t\t| ComponentType<P>;\n\n\texport type ComponentPropsWithoutRef<T extends ElementType> = PropsWithoutRef<\n\t\tComponentProps<T>\n\t>;\n\n\texport type ComponentPropsWithRef<C extends ElementType> = C extends new (\n\t\tprops: infer P\n\t) => Component<any, any>\n\t\t? PropsWithoutRef<P> & RefAttributes<InstanceType<C>>\n\t\t: ComponentProps<C>;\n\n\texport type ElementRef<\n\t\tC extends\n\t\t\t| ForwardRefExoticComponent<any>\n\t\t\t| { new (props: any): Component<any, any> }\n\t\t\t| ((props: any) => ReactNode)\n\t\t\t| keyof JSXInternal.IntrinsicElements\n\t> = 'ref' extends keyof ComponentPropsWithRef<C>\n\t\t? NonNullable<ComponentPropsWithRef<C>['ref']> extends RefAttributes<\n\t\t\t\tinfer Instance\n\t\t\t>['ref']\n\t\t\t? Instance\n\t\t\t: never\n\t\t: never;\n\n\texport function flushSync<R>(fn: () => R): R;\n\texport function flushSync<A, R>(fn: (a: A) => R, a: A): R;\n\n\texport function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R;\n\texport function unstable_batchedUpdates<R>(callback: () => R): R;\n\n\texport type PropsWithChildren<P = unknown> = P & {\n\t\tchildren?: _preact.ComponentChildren | undefined;\n\t};\n\n\texport const Children: {\n\t\tmap<T extends _preact.ComponentChild, R>(\n\t\t\tchildren: T | T[],\n\t\t\tfn: (child: T, i: number) => R,\n\t\t\tcontext: any\n\t\t): R[];\n\t\tforEach<T extends _preact.ComponentChild>(\n\t\t\tchildren: T | T[],\n\t\t\tfn: (child: T, i: number) => void,\n\t\t\tcontext: any\n\t\t): void;\n\t\tcount: (children: _preact.ComponentChildren) => number;\n\t\tonly: (children: _preact.ComponentChildren) => _preact.ComponentChild;\n\t\ttoArray: (children: _preact.ComponentChildren) => _preact.VNode<{}>[];\n\t};\n\n\t// scheduler\n\texport const unstable_ImmediatePriority: number;\n\texport const unstable_UserBlockingPriority: number;\n\texport const unstable_NormalPriority: number;\n\texport const unstable_LowPriority: number;\n\texport const unstable_IdlePriority: number;\n\texport function unstable_runWithPriority(\n\t\tpriority: number,\n\t\tcallback: () => void\n\t): void;\n\texport const unstable_now: () => number;\n}\n"
  },
  {
    "path": "compat/src/index.js",
    "content": "import {\n\tComponent,\n\tFragment,\n\tcreateContext,\n\tcreateElement,\n\tcreateRef,\n\toptions,\n\tcloneElement as preactCloneElement,\n\trender as preactRender\n} from 'preact';\nimport {\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue,\n\tuseEffect,\n\tuseId,\n\tuseImperativeHandle,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseReducer,\n\tuseRef,\n\tuseState\n} from 'preact/hooks';\nimport { Children } from './Children';\nimport { PureComponent } from './PureComponent';\nimport { forwardRef } from './forwardRef';\nimport {\n\tstartTransition,\n\tuseDeferredValue,\n\tuseInsertionEffect,\n\tuseSyncExternalStore,\n\tuseTransition\n} from './hooks';\nimport { memo } from './memo';\nimport { createPortal } from './portals';\nimport {\n\tREACT_ELEMENT_TYPE,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,\n\thydrate,\n\trender\n} from './render';\nimport { Suspense, lazy } from './suspense';\n\nconst version = '18.3.1'; // trick libraries to think we are react\n\n/**\n * Legacy version of createElement.\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component constructor\n */\nfunction createFactory(type) {\n\treturn createElement.bind(null, type);\n}\n\n/**\n * Check if the passed element is a valid (p)react node.\n * @param {*} element The element to check\n * @returns {boolean}\n */\nfunction isValidElement(element) {\n\treturn !!element && element.$$typeof === REACT_ELEMENT_TYPE;\n}\n\n/**\n * Check if the passed element is a Fragment node.\n * @param {*} element The element to check\n * @returns {boolean}\n */\nfunction isFragment(element) {\n\treturn isValidElement(element) && element.type === Fragment;\n}\n\n/**\n * Check if the passed element is a Memo node.\n * @param {*} element The element to check\n * @returns {boolean}\n */\nfunction isMemo(element) {\n\treturn (\n\t\t!!element &&\n\t\ttypeof element.displayName == 'string' &&\n\t\telement.displayName.indexOf('Memo(') == 0\n\t);\n}\n\n/**\n * Wrap `cloneElement` to abort if the passed element is not a valid element and apply\n * all vnode normalizations.\n * @param {import('./internal').VNode} element The vnode to clone\n * @param {object} props Props to add when cloning\n * @param {Array<import('./internal').ComponentChildren>} rest Optional component children\n */\nfunction cloneElement(element) {\n\tif (!isValidElement(element)) return element;\n\treturn preactCloneElement.apply(null, arguments);\n}\n\n/**\n * Remove a component tree from the DOM, including state and event handlers.\n * @param {import('./internal').PreactElement} container\n * @returns {boolean}\n */\nfunction unmountComponentAtNode(container) {\n\tif (container._children) {\n\t\tpreactRender(null, container);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Get the matching DOM node for a component\n * @param {import('./internal').Component} component\n * @returns {import('./internal').PreactElement | null}\n */\nfunction findDOMNode(component) {\n\treturn (\n\t\t(component &&\n\t\t\t((component._vnode && component._vnode._dom) ||\n\t\t\t\t(component.nodeType === 1 && component))) ||\n\t\tnull\n\t);\n}\n\n/**\n * In React, `flushSync` flushes the entire tree and forces a rerender.\n * @template Arg\n * @template Result\n * @param {(arg: Arg) => Result} callback function that runs before the flush\n * @param {Arg} [arg] Optional argument that can be passed to the callback\n * @returns\n */\nconst flushSync = (callback, arg) => {\n\tconst prevDebounce = options.debounceRendering;\n\toptions.debounceRendering = cb => cb();\n\tconst res = callback(arg);\n\toptions.debounceRendering = prevDebounce;\n\treturn res;\n};\n\n/**\n * In React, `unstable_batchedUpdates` is a legacy feature that was made a no-op\n * outside of legacy mode in React 18 and a no-op across the board in React 19.\n * @template Arg\n * @template Result\n * @param {(arg: Arg) => Result} callback\n * @param {Arg} [arg]\n * @returns {Result}\n */\nfunction unstable_batchedUpdates(callback, arg) {\n\treturn callback(arg);\n}\n\n// compat to react-is\nexport const isElement = isValidElement;\n\nexport * from 'preact/hooks';\nexport {\n\tversion,\n\tChildren,\n\trender,\n\thydrate,\n\tunmountComponentAtNode,\n\tcreatePortal,\n\tcreateElement,\n\tcreateContext,\n\tcreateFactory,\n\tcloneElement,\n\tcreateRef,\n\tFragment,\n\tisValidElement,\n\tisFragment,\n\tisMemo,\n\tfindDOMNode,\n\tComponent,\n\tPureComponent,\n\tmemo,\n\tforwardRef,\n\tflushSync,\n\tunstable_batchedUpdates,\n\tuseInsertionEffect,\n\tstartTransition,\n\tuseDeferredValue,\n\tuseSyncExternalStore,\n\tuseTransition,\n\tFragment as StrictMode,\n\tSuspense,\n\tlazy,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n};\n\n// React copies the named exports to the default one.\nexport default {\n\tuseState,\n\tuseId,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseInsertionEffect,\n\tuseTransition,\n\tuseDeferredValue,\n\tuseSyncExternalStore,\n\tstartTransition,\n\tuseRef,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue,\n\tversion,\n\tChildren,\n\trender,\n\thydrate,\n\tunmountComponentAtNode,\n\tcreatePortal,\n\tcreateElement,\n\tcreateContext,\n\tcreateFactory,\n\tcloneElement,\n\tcreateRef,\n\tFragment,\n\tisValidElement,\n\tisElement,\n\tisFragment,\n\tisMemo,\n\tfindDOMNode,\n\tComponent,\n\tPureComponent,\n\tmemo,\n\tforwardRef,\n\tflushSync,\n\tunstable_batchedUpdates,\n\tStrictMode: Fragment,\n\tSuspense,\n\tlazy,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n};\n"
  },
  {
    "path": "compat/src/internal.d.ts",
    "content": "import {\n\tComponent as PreactComponent,\n\tVNode as PreactVNode,\n\tFunctionComponent as PreactFunctionComponent,\n\tPreactElement\n} from '../../src/internal';\nimport { SuspenseProps } from './suspense';\n\nexport { ComponentChildren } from '../..';\n\nexport { PreactElement };\n\nexport interface Component<P = {}, S = {}> extends PreactComponent<P, S> {\n\tisReactComponent?: object;\n\tisPureReactComponent?: true;\n\t_patchedLifecycles?: true;\n\n\t// Suspense internal properties\n\t_childDidSuspend?(error: Promise<void>, suspendingVNode: VNode): void;\n\t_suspended: (vnode: VNode) => (unsuspend: () => void) => void;\n\t_onResolve?(): void;\n\n\t// Portal internal properties\n\t_temp: any;\n\t_container: PreactElement;\n}\n\nexport interface FunctionComponent<P = {}> extends PreactFunctionComponent<P> {\n\tshouldComponentUpdate?(nextProps: Readonly<P>): boolean;\n\t_patchedLifecycles?: true;\n}\n\nexport interface VNode<T = any> extends PreactVNode<T> {\n\t$$typeof?: symbol;\n\tpreactCompatNormalized?: boolean;\n}\n\nexport interface SuspenseState {\n\t_suspended?: null | VNode<any>;\n}\n\nexport interface SuspenseComponent\n\textends PreactComponent<SuspenseProps, SuspenseState> {\n\t_pendingSuspensionCount: number;\n\t_suspenders: Component[];\n\t_detachOnNextRender: null | VNode<any>;\n}\n"
  },
  {
    "path": "compat/src/memo.js",
    "content": "import { createElement } from 'preact';\nimport { shallowDiffers } from './util';\n\n/**\n * Memoize a component, so that it only updates when the props actually have\n * changed. This was previously known as `React.pure`.\n * @param {import('./internal').FunctionComponent} c functional component\n * @param {(prev: object, next: object) => boolean} [comparer] Custom equality function\n * @returns {import('./internal').FunctionComponent}\n */\nexport function memo(c, comparer) {\n\tfunction shouldUpdate(nextProps) {\n\t\tconst ref = this.props.ref;\n\t\tif (ref != nextProps.ref && ref) {\n\t\t\ttypeof ref == 'function' ? ref(null) : (ref.current = null);\n\t\t}\n\n\t\treturn comparer\n\t\t\t? !comparer(this.props, nextProps) || ref != nextProps.ref\n\t\t\t: shallowDiffers(this.props, nextProps);\n\t}\n\n\tfunction Memoed(props) {\n\t\tthis.shouldComponentUpdate = shouldUpdate;\n\t\treturn createElement(c, props);\n\t}\n\tMemoed.displayName = 'Memo(' + (c.displayName || c.name) + ')';\n\tMemoed._forwarded = Memoed.prototype.isReactComponent = true;\n\tMemoed.type = c;\n\treturn Memoed;\n}\n"
  },
  {
    "path": "compat/src/portals.js",
    "content": "import { createElement, render } from 'preact';\n\n/**\n * @param {import('../../src/index').RenderableProps<{ context: any }>} props\n */\nfunction ContextProvider(props) {\n\tthis.getChildContext = () => props.context;\n\treturn props.children;\n}\n\n/**\n * Portal component\n * @this {import('./internal').Component}\n * @param {object | null | undefined} props\n *\n * TODO: use createRoot() instead of fake root\n */\nfunction Portal(props) {\n\tconst _this = this;\n\tlet container = props._container;\n\n\t_this.componentWillUnmount = function () {\n\t\trender(null, _this._temp);\n\t\t_this._temp = null;\n\t\t_this._container = null;\n\t};\n\n\t// When we change container we should clear our old container and\n\t// indicate a new mount.\n\tif (_this._container && _this._container !== container) {\n\t\t_this.componentWillUnmount();\n\t}\n\n\tif (!_this._temp) {\n\t\t// Ensure the element has a mask for useId invocations\n\t\tlet root = _this._vnode;\n\t\twhile (root !== null && !root._mask && root._parent !== null) {\n\t\t\troot = root._parent;\n\t\t}\n\n\t\t_this._container = container;\n\n\t\t// Create a fake DOM parent node that manages a subset of `container`'s children:\n\t\t_this._temp = {\n\t\t\tnodeType: 1,\n\t\t\tparentNode: container,\n\t\t\tchildNodes: [],\n\t\t\t_children: { _mask: root._mask },\n\t\t\townerDocument: container.ownerDocument,\n\t\t\tnamespaceURI: container.namespaceURI,\n\t\t\tinsertBefore(child, before) {\n\t\t\t\tthis.childNodes.push(child);\n\t\t\t\t_this._container.insertBefore(child, before);\n\t\t\t}\n\t\t};\n\t}\n\n\t// Render our wrapping element into temp.\n\trender(\n\t\tcreateElement(ContextProvider, { context: _this.context }, props._vnode),\n\t\t_this._temp\n\t);\n}\n\n/**\n * Create a `Portal` to continue rendering the vnode tree at a different DOM node\n * @param {import('./internal').VNode} vnode The vnode to render\n * @param {import('./internal').PreactElement} container The DOM node to continue rendering in to.\n */\nexport function createPortal(vnode, container) {\n\tconst el = createElement(Portal, { _vnode: vnode, _container: container });\n\tel.containerInfo = container;\n\treturn el;\n}\n"
  },
  {
    "path": "compat/src/render.js",
    "content": "import {\n\trender as preactRender,\n\thydrate as preactHydrate,\n\toptions,\n\ttoChildArray,\n\tComponent\n} from 'preact';\nimport {\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue,\n\tuseEffect,\n\tuseId,\n\tuseImperativeHandle,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseReducer,\n\tuseRef,\n\tuseState\n} from 'preact/hooks';\nimport {\n\tuseDeferredValue,\n\tuseInsertionEffect,\n\tuseSyncExternalStore,\n\tuseTransition\n} from './index';\nimport { assign, IS_NON_DIMENSIONAL } from './util';\n\nexport const REACT_ELEMENT_TYPE = Symbol.for('react.element');\n\nconst CAMEL_PROPS =\n\t/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image(!S)|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/;\nconst CAMEL_REPLACE = /[A-Z0-9]/g;\nconst IS_DOM = typeof document !== 'undefined';\n\n// Input types for which onchange should not be converted to oninput.\nconst onChangeInputType = type => /fil|che|rad/.test(type);\n\n// Some libraries like `react-virtualized` explicitly check for this.\nComponent.prototype.isReactComponent = true;\n\n// `UNSAFE_*` lifecycle hooks\n// Preact only ever invokes the unprefixed methods.\n// Here we provide a base \"fallback\" implementation that calls any defined UNSAFE_ prefixed method.\n// - If a component defines its own `componentDidMount()` (including via defineProperty), use that.\n// - If a component defines `UNSAFE_componentDidMount()`, `componentDidMount` is the alias getter/setter.\n// - If anything assigns to an `UNSAFE_*` property, the assignment is forwarded to the unprefixed property.\n// See https://github.com/preactjs/preact/issues/1941\n[\n\t'componentWillMount',\n\t'componentWillReceiveProps',\n\t'componentWillUpdate'\n].forEach(key => {\n\tObject.defineProperty(Component.prototype, key, {\n\t\tconfigurable: true,\n\t\tget() {\n\t\t\treturn this['UNSAFE_' + key];\n\t\t},\n\t\tset(v) {\n\t\t\tObject.defineProperty(this, key, {\n\t\t\t\tconfigurable: true,\n\t\t\t\twritable: true,\n\t\t\t\tvalue: v\n\t\t\t});\n\t\t}\n\t});\n});\n\n/**\n * Proxy render() since React returns a Component reference.\n * @param {import('./internal').VNode} vnode VNode tree to render\n * @param {import('./internal').PreactElement} parent DOM node to render vnode tree into\n * @param {() => void} [callback] Optional callback that will be called after rendering\n * @returns {import('./internal').Component | null} The root component reference or null\n */\nexport function render(vnode, parent, callback) {\n\t// React destroys any existing DOM nodes, see #1727\n\t// ...but only on the first render, see #1828\n\tif (parent._children == null) {\n\t\tparent.textContent = '';\n\t}\n\n\tpreactRender(vnode, parent);\n\tif (typeof callback == 'function') callback();\n\n\treturn vnode ? vnode._component : null;\n}\n\nexport function hydrate(vnode, parent, callback) {\n\tpreactHydrate(vnode, parent);\n\tif (typeof callback == 'function') callback();\n\n\treturn vnode ? vnode._component : null;\n}\n\nlet oldEventHook = options.event;\noptions.event = e => {\n\tif (oldEventHook) e = oldEventHook(e);\n\n\te.persist = () => {};\n\te.isPropagationStopped = function isPropagationStopped() {\n\t\treturn this.cancelBubble;\n\t};\n\te.isDefaultPrevented = function isDefaultPrevented() {\n\t\treturn this.defaultPrevented;\n\t};\n\treturn (e.nativeEvent = e);\n};\n\nconst classNameDescriptorNonEnumberable = {\n\tconfigurable: true,\n\tget() {\n\t\treturn this.class;\n\t}\n};\n\nfunction handleDomVNode(vnode) {\n\tlet props = vnode.props,\n\t\ttype = vnode.type,\n\t\tnormalizedProps = {},\n\t\tisNonDashedType = type.indexOf('-') == -1;\n\n\tfor (let i in props) {\n\t\tlet value = props[i];\n\n\t\tif (\n\t\t\t(i === 'value' && 'defaultValue' in props && value == null) ||\n\t\t\t// Emulate React's behavior of not rendering the contents of noscript tags on the client.\n\t\t\t(IS_DOM && i === 'children' && type === 'noscript') ||\n\t\t\ti === 'class' ||\n\t\t\ti === 'className'\n\t\t) {\n\t\t\t// Skip applying value if it is null/undefined and we already set\n\t\t\t// a default value\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (i === 'style' && typeof value === 'object') {\n\t\t\tfor (let key in value) {\n\t\t\t\tif (typeof value[key] === 'number' && !IS_NON_DIMENSIONAL.test(key)) {\n\t\t\t\t\tvalue[key] += 'px';\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (\n\t\t\ti === 'defaultValue' &&\n\t\t\t'value' in props &&\n\t\t\tprops.value == null\n\t\t) {\n\t\t\t// `defaultValue` is treated as a fallback `value` when a value prop is present but null/undefined.\n\t\t\t// `defaultValue` for Elements with no value prop is the same as the DOM defaultValue property.\n\t\t\ti = 'value';\n\t\t} else if (i === 'download' && value === true) {\n\t\t\t// Calling `setAttribute` with a truthy value will lead to it being\n\t\t\t// passed as a stringified value, e.g. `download=\"true\"`. React\n\t\t\t// converts it to an empty string instead, otherwise the attribute\n\t\t\t// value will be used as the file name and the file will be called\n\t\t\t// \"true\" upon downloading it.\n\t\t\tvalue = '';\n\t\t} else if (i === 'translate' && value === 'no') {\n\t\t\tvalue = false;\n\t\t} else if (i[0] === 'o' && i[1] === 'n') {\n\t\t\tlet lowerCased = i.toLowerCase();\n\t\t\tif (lowerCased === 'ondoubleclick') {\n\t\t\t\ti = 'ondblclick';\n\t\t\t} else if (\n\t\t\t\tlowerCased === 'onchange' &&\n\t\t\t\t(type === 'input' || type === 'textarea') &&\n\t\t\t\t!onChangeInputType(props.type)\n\t\t\t) {\n\t\t\t\tlowerCased = i = 'oninput';\n\t\t\t} else if (lowerCased === 'onfocus') {\n\t\t\t\ti = 'onfocusin';\n\t\t\t} else if (lowerCased === 'onblur') {\n\t\t\t\ti = 'onfocusout';\n\t\t\t}\n\n\t\t\t// Add support for onInput and onChange, see #3561\n\t\t\t// if we have an oninput prop already change it to oninputCapture\n\t\t\tif (lowerCased === 'oninput') {\n\t\t\t\ti = lowerCased;\n\t\t\t\tif (normalizedProps[i]) {\n\t\t\t\t\ti = 'oninputCapture';\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (isNonDashedType && CAMEL_PROPS.test(i)) {\n\t\t\ti = i.replace(CAMEL_REPLACE, '-$&').toLowerCase();\n\t\t} else if (value === null) {\n\t\t\tvalue = undefined;\n\t\t}\n\n\t\tnormalizedProps[i] = value;\n\t}\n\n\tif (type == 'select') {\n\t\t// Add support for array select values: <select multiple value={[]} />\n\t\tif (normalizedProps.multiple && Array.isArray(normalizedProps.value)) {\n\t\t\t// forEach() always returns undefined, which we abuse here to unset the value prop.\n\t\t\tnormalizedProps.value = toChildArray(props.children).forEach(child => {\n\t\t\t\tchild.props.selected =\n\t\t\t\t\tnormalizedProps.value.indexOf(child.props.value) != -1;\n\t\t\t});\n\t\t}\n\n\t\t// Adding support for defaultValue in select tag\n\t\tif (normalizedProps.defaultValue != null) {\n\t\t\tnormalizedProps.value = toChildArray(props.children).forEach(child => {\n\t\t\t\tif (normalizedProps.multiple) {\n\t\t\t\t\tchild.props.selected =\n\t\t\t\t\t\tnormalizedProps.defaultValue.indexOf(child.props.value) != -1;\n\t\t\t\t} else {\n\t\t\t\t\tchild.props.selected =\n\t\t\t\t\t\tnormalizedProps.defaultValue == child.props.value;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tif (props.class && !props.className) {\n\t\tnormalizedProps.class = props.class;\n\t\tObject.defineProperty(\n\t\t\tnormalizedProps,\n\t\t\t'className',\n\t\t\tclassNameDescriptorNonEnumberable\n\t\t);\n\t} else if (props.className) {\n\t\tnormalizedProps.class = normalizedProps.className = props.className;\n\t}\n\n\tvnode.props = normalizedProps;\n}\n\nlet oldVNodeHook = options.vnode;\noptions.vnode = vnode => {\n\t// only normalize props on Element nodes\n\tif (typeof vnode.type === 'string') {\n\t\thandleDomVNode(vnode);\n\t} else if (typeof vnode.type === 'function') {\n\t\tconst shouldApplyRef =\n\t\t\t'prototype' in vnode.type && vnode.type.prototype.render;\n\t\tif ('ref' in vnode.props && shouldApplyRef) {\n\t\t\tvnode.ref = vnode.props.ref;\n\t\t\tdelete vnode.props.ref;\n\t\t}\n\n\t\tif (vnode.type.defaultProps) {\n\t\t\tlet normalizedProps = assign({}, vnode.props);\n\t\t\tfor (let i in vnode.type.defaultProps) {\n\t\t\t\tif (normalizedProps[i] === undefined) {\n\t\t\t\t\tnormalizedProps[i] = vnode.type.defaultProps[i];\n\t\t\t\t}\n\t\t\t}\n\t\t\tvnode.props = normalizedProps;\n\t\t}\n\t}\n\tvnode.$$typeof = REACT_ELEMENT_TYPE;\n\n\tif (oldVNodeHook) oldVNodeHook(vnode);\n};\n\n// Only needed for react-relay\nlet currentComponent;\nconst oldBeforeRender = options._render;\noptions._render = function (vnode) {\n\tif (oldBeforeRender) {\n\t\toldBeforeRender(vnode);\n\t}\n\tcurrentComponent = vnode._component;\n};\n\nconst oldDiffed = options.diffed;\n/** @type {(vnode: import('./internal').VNode) => void} */\noptions.diffed = function (vnode) {\n\tif (oldDiffed) {\n\t\toldDiffed(vnode);\n\t}\n\n\tconst props = vnode.props;\n\tconst dom = vnode._dom;\n\n\tif (\n\t\tdom != null &&\n\t\tvnode.type === 'textarea' &&\n\t\t'value' in props &&\n\t\tprops.value !== dom.value\n\t) {\n\t\tdom.value = props.value == null ? '' : props.value;\n\t}\n\n\tcurrentComponent = null;\n};\n\n// This is a very very private internal function for React it\n// is used to sort-of do runtime dependency injection.\nexport const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {\n\tReactCurrentDispatcher: {\n\t\tcurrent: {\n\t\t\treadContext(context) {\n\t\t\t\treturn currentComponent._globalContext[context._id].props.value;\n\t\t\t},\n\t\t\tuseCallback,\n\t\t\tuseContext,\n\t\t\tuseDebugValue,\n\t\t\tuseDeferredValue,\n\t\t\tuseEffect,\n\t\t\tuseId,\n\t\t\tuseImperativeHandle,\n\t\t\tuseInsertionEffect,\n\t\t\tuseLayoutEffect,\n\t\t\tuseMemo,\n\t\t\t// useMutableSource, // experimental-only and replaced by uSES, likely not worth supporting\n\t\t\tuseReducer,\n\t\t\tuseRef,\n\t\t\tuseState,\n\t\t\tuseSyncExternalStore,\n\t\t\tuseTransition\n\t\t}\n\t}\n};\n"
  },
  {
    "path": "compat/src/suspense.d.ts",
    "content": "import { Component, ComponentChild, ComponentChildren } from '../../src/index';\n\n//\n// Suspense/lazy\n// -----------------------------------\nexport function lazy<T>(\n\tloader: () => Promise<{ default: T } | T>\n): T extends { default: infer U } ? U : T;\n\nexport interface SuspenseProps {\n\tchildren?: ComponentChildren;\n\tfallback: ComponentChildren;\n}\n\nexport class Suspense extends Component<SuspenseProps> {\n\trender(): ComponentChild;\n}\n"
  },
  {
    "path": "compat/src/suspense.js",
    "content": "import { Component, Fragment, createElement, options } from 'preact';\nimport {\n\tCOMPONENT_FORCE,\n\tFORCE_PROPS_REVALIDATE,\n\tMODE_HYDRATE\n} from '../../src/constants';\nimport { assign } from './util';\n\nconst oldCatchError = options._catchError;\noptions._catchError = (error, newVNode, oldVNode, errorInfo) => {\n\tif (error.then) {\n\t\t/** @type {import('./internal').Component} */\n\t\tlet component;\n\t\tlet vnode = newVNode;\n\n\t\twhile ((vnode = vnode._parent)) {\n\t\t\tif ((component = vnode._component) && component._childDidSuspend) {\n\t\t\t\tif (newVNode._dom == null) {\n\t\t\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t\t\t\tnewVNode._children = oldVNode._children;\n\t\t\t\t}\n\t\t\t\t// Don't call oldCatchError if we found a Suspense\n\t\t\t\treturn component._childDidSuspend(error, newVNode);\n\t\t\t}\n\t\t}\n\t}\n\toldCatchError(error, newVNode, oldVNode, errorInfo);\n};\n\nconst oldUnmount = options.unmount;\noptions.unmount = vnode => {\n\t/** @type {import('./internal').Component} */\n\tconst component = vnode._component;\n\tif (component) component._unmounted = true;\n\tif (component && component._onResolve) {\n\t\tcomponent._onResolve();\n\t}\n\n\tif (oldUnmount) oldUnmount(vnode);\n};\n\nfunction detachedClone(vnode, detachedParent, parentDom) {\n\tif (vnode) {\n\t\tif (vnode._component && vnode._component.__hooks) {\n\t\t\tvnode._component.__hooks._list.forEach(effect => {\n\t\t\t\tif (typeof effect._cleanup == 'function') effect._cleanup();\n\t\t\t});\n\n\t\t\tvnode._component.__hooks = null;\n\t\t}\n\n\t\tvnode = assign({}, vnode);\n\t\tif (vnode._component != null) {\n\t\t\tif (vnode._component._parentDom === parentDom) {\n\t\t\t\tvnode._component._parentDom = detachedParent;\n\t\t\t}\n\n\t\t\tvnode._component._bits |= COMPONENT_FORCE;\n\n\t\t\tvnode._component = null;\n\t\t}\n\n\t\tvnode._children =\n\t\t\tvnode._children &&\n\t\t\tvnode._children.map(child =>\n\t\t\t\tdetachedClone(child, detachedParent, parentDom)\n\t\t\t);\n\t}\n\n\treturn vnode;\n}\n\nfunction removeOriginal(vnode, detachedParent, originalParent) {\n\tif (vnode && originalParent) {\n\t\tif (typeof vnode.type == 'string') {\n\t\t\tvnode._flags |= FORCE_PROPS_REVALIDATE;\n\t\t}\n\n\t\tvnode._original = null;\n\t\tvnode._children =\n\t\t\tvnode._children &&\n\t\t\tvnode._children.map(child =>\n\t\t\t\tremoveOriginal(child, detachedParent, originalParent)\n\t\t\t);\n\n\t\tif (vnode._component) {\n\t\t\tif (vnode._component._parentDom === detachedParent) {\n\t\t\t\tif (vnode._dom) {\n\t\t\t\t\toriginalParent.appendChild(vnode._dom);\n\t\t\t\t}\n\t\t\t\tvnode._component._bits |= COMPONENT_FORCE;\n\t\t\t\tvnode._component._parentDom = originalParent;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn vnode;\n}\n\n// having custom inheritance instead of a class here saves a lot of bytes\nexport function Suspense() {\n\t// we do not call super here to golf some bytes...\n\tthis._pendingSuspensionCount = 0;\n\tthis._suspenders = null;\n\tthis._detachOnNextRender = null;\n}\n\n// Things we do here to save some bytes but are not proper JS inheritance:\n// - call `new Component()` as the prototype\n// - do not set `Suspense.prototype.constructor` to `Suspense`\nSuspense.prototype = new Component();\n\n/**\n * @this {import('./internal').SuspenseComponent}\n * @param {Promise} promise The thrown promise\n * @param {import('./internal').VNode<any, any>} suspendingVNode The suspending component\n */\nSuspense.prototype._childDidSuspend = function (promise, suspendingVNode) {\n\tconst suspendingComponent = suspendingVNode._component;\n\n\tif (this._suspenders == null) {\n\t\tthis._suspenders = [];\n\t}\n\tthis._suspenders.push(suspendingComponent);\n\n\tlet resolved = false;\n\tconst onResolved = () => {\n\t\tif (resolved || this._unmounted) return;\n\n\t\tresolved = true;\n\t\tsuspendingComponent._onResolve = null;\n\n\t\tonSuspensionComplete();\n\t};\n\n\tsuspendingComponent._onResolve = onResolved;\n\n\t// Store and null _parentDom to prevent setState/forceUpdate from\n\t// scheduling renders while suspended. Render would be a no-op anyway\n\t// since renderComponent checks _parentDom, but this avoids queue churn.\n\tconst originalParentDom = suspendingComponent._parentDom;\n\tsuspendingComponent._parentDom = null;\n\n\tconst onSuspensionComplete = () => {\n\t\tif (!--this._pendingSuspensionCount) {\n\t\t\t// If the suspension was during hydration we don't need to restore the\n\t\t\t// suspended children into the _children array\n\t\t\tif (this.state._suspended) {\n\t\t\t\tconst suspendedVNode = this.state._suspended;\n\t\t\t\tthis._vnode._children[0] = removeOriginal(\n\t\t\t\t\tsuspendedVNode,\n\t\t\t\t\tsuspendedVNode._component._parentDom,\n\t\t\t\t\tsuspendedVNode._component._originalParentDom\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.setState({ _suspended: (this._detachOnNextRender = null) });\n\n\t\t\tlet suspended;\n\t\t\twhile ((suspended = this._suspenders.pop())) {\n\t\t\t\t// Restore _parentDom before forceUpdate so render can proceed\n\t\t\t\tsuspended._parentDom = originalParentDom;\n\t\t\t\tsuspended.forceUpdate();\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * We do not set `suspended: true` during hydration because we want the actual markup\n\t * to remain on screen and hydrate it when the suspense actually gets resolved.\n\t * While in non-hydration cases the usual fallback -> component flow would occour.\n\t */\n\tif (\n\t\t!this._pendingSuspensionCount++ &&\n\t\t!(suspendingVNode._flags & MODE_HYDRATE)\n\t) {\n\t\tthis.setState({\n\t\t\t_suspended: (this._detachOnNextRender = this._vnode._children[0])\n\t\t});\n\t}\n\tpromise.then(onResolved, onResolved);\n};\n\nSuspense.prototype.componentWillUnmount = function () {\n\tthis._suspenders = [];\n};\n\n/**\n * @this {import('./internal').SuspenseComponent}\n * @param {import('./internal').SuspenseComponent[\"props\"]} props\n * @param {import('./internal').SuspenseState} state\n */\nSuspense.prototype.render = function (props, state) {\n\tif (this._detachOnNextRender) {\n\t\t// When the Suspense's _vnode was created by a call to createVNode\n\t\t// (i.e. due to a setState further up in the tree)\n\t\t// it's _children prop is null, in this case we \"forget\" about the parked vnodes to detach\n\t\tif (this._vnode._children) {\n\t\t\tconst detachedParent = document.createElement('div');\n\t\t\tconst detachedComponent = this._vnode._children[0]._component;\n\t\t\tthis._vnode._children[0] = detachedClone(\n\t\t\t\tthis._detachOnNextRender,\n\t\t\t\tdetachedParent,\n\t\t\t\t(detachedComponent._originalParentDom = detachedComponent._parentDom)\n\t\t\t);\n\t\t}\n\n\t\tthis._detachOnNextRender = null;\n\t}\n\n\treturn [\n\t\tcreateElement(Fragment, null, state._suspended ? null : props.children),\n\t\tstate._suspended && createElement(Fragment, null, props.fallback)\n\t];\n};\n\nexport function lazy(loader) {\n\tlet prom;\n\tlet component = null;\n\tlet error;\n\tlet resolved;\n\n\tfunction Lazy(props) {\n\t\tif (!prom) {\n\t\t\tprom = loader();\n\t\t\tprom.then(\n\t\t\t\texports => {\n\t\t\t\t\tif (exports) {\n\t\t\t\t\t\tcomponent = exports.default || exports;\n\t\t\t\t\t}\n\t\t\t\t\tresolved = true;\n\t\t\t\t},\n\t\t\t\te => {\n\t\t\t\t\terror = e;\n\t\t\t\t\tresolved = true;\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tif (error) {\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (!resolved) {\n\t\t\tthrow prom;\n\t\t}\n\n\t\treturn component ? createElement(component, props) : null;\n\t}\n\n\tLazy.displayName = 'Lazy';\n\treturn Lazy;\n}\n"
  },
  {
    "path": "compat/src/util.js",
    "content": "export const assign = Object.assign;\n\n/**\n * Check if two objects have a different shape\n * @param {object} a\n * @param {object} b\n * @returns {boolean}\n */\nexport function shallowDiffers(a, b) {\n\tfor (let i in a) if (i !== '__source' && !(i in b)) return true;\n\tfor (let i in b) if (i !== '__source' && a[i] !== b[i]) return true;\n\treturn false;\n}\n\nexport const IS_NON_DIMENSIONAL =\n\t/^(-|f[lo].*[^se]$|g.{5,}[^ps]$|z|o[pr]|(W.{5})?[lL]i.*(t|mp)$|an|(bo|s).{4}Im|sca|m.{6}[ds]|ta|c.*[st]$|wido|ini)/;\n"
  },
  {
    "path": "compat/test/browser/Children.test.jsx",
    "content": "import {\n\tsetupScratch,\n\tteardown,\n\tserializeHtml\n} from '../../../test/_util/helpers';\nimport { div, span } from '../../../test/_util/dom';\nimport React, { createElement, Children, render } from 'preact/compat';\nimport { vi } from 'vitest';\n\ndescribe('Children', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('.count', () => {\n\t\tlet count;\n\t\tfunction Foo(props) {\n\t\t\tcount = Children.count(props.children);\n\t\t\treturn <div>{count}</div>;\n\t\t}\n\n\t\tit('should return 0 for no children', () => {\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(count).to.equal(0);\n\t\t});\n\n\t\tit('should return number of children', () => {\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\t<div />\n\t\t\t\t\tfoo\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(count).to.equal(2);\n\t\t});\n\t});\n\n\tdescribe('.only', () => {\n\t\tlet actual;\n\t\tfunction Foo(props) {\n\t\t\tactual = Children.only(props.children);\n\t\t\treturn <div>{actual}</div>;\n\t\t}\n\n\t\tit('should only allow 1 child', () => {\n\t\t\trender(<Foo>foo</Foo>, scratch);\n\t\t\texpect(actual).to.equal('foo');\n\t\t});\n\n\t\tit('should throw if no children are passed', () => {\n\t\t\t// eslint-disable-next-line prefer-arrow-callback\n\t\t\texpect(function () {\n\t\t\t\trender(<Foo />, scratch);\n\t\t\t}).to.throw();\n\t\t});\n\n\t\tit('should throw if more children are passed', () => {\n\t\t\t// eslint-disable-next-line prefer-arrow-callback\n\t\t\texpect(function () {\n\t\t\t\trender(\n\t\t\t\t\t<Foo>\n\t\t\t\t\t\tfoo\n\t\t\t\t\t\t<span />\n\t\t\t\t\t</Foo>,\n\t\t\t\t\tscratch\n\t\t\t\t);\n\t\t\t}).to.throw();\n\t\t});\n\t});\n\n\tdescribe('.map', () => {\n\t\tfunction Foo(props) {\n\t\t\tlet children = Children.map(props.children, child => (\n\t\t\t\t<span>{child}</span>\n\t\t\t));\n\t\t\treturn <div>{children}</div>;\n\t\t}\n\n\t\tit('should iterate over children', () => {\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\tfoo<div>bar</div>\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\tlet expected = div([span('foo'), span(div('bar'))]);\n\t\t\texpect(serializeHtml(scratch)).to.equal(expected);\n\t\t});\n\n\t\tit('should work with no children', () => {\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(serializeHtml(scratch)).to.equal('<div></div>');\n\t\t});\n\n\t\tit('should work with children as zero number', () => {\n\t\t\tconst testNumber = 0;\n\n\t\t\trender(<Foo>{testNumber}</Foo>, scratch);\n\t\t\texpect(serializeHtml(scratch)).to.equal('<div><span>0</span></div>');\n\t\t});\n\n\t\tit('should propagate \"this\" context', () => {\n\t\t\tconst context = {};\n\t\t\tconst spy = vi.fn(child => child); // noop\n\t\t\tconst Foo = ({ children }) => {\n\t\t\t\treturn React.Children.map(children, spy, context);\n\t\t\t};\n\t\t\trender(<Foo>foo</Foo>, scratch);\n\n\t\t\texpect(spy.mock.contexts[0]).to.equal(context);\n\t\t});\n\n\t\tit('should flatten result', () => {\n\t\t\tconst ProblemChild = ({ children }) => {\n\t\t\t\treturn React.Children.map(children, child => {\n\t\t\t\t\treturn React.Children.map(child.props.children, x => x);\n\t\t\t\t}).filter(React.isValidElement);\n\t\t\t};\n\n\t\t\tconst App = () => {\n\t\t\t\treturn (\n\t\t\t\t\t<ProblemChild>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</ProblemChild>\n\t\t\t\t);\n\t\t\t};\n\n\t\t\trender(<App />, scratch);\n\n\t\t\texpect(scratch.textContent).to.equal('12');\n\t\t});\n\n\t\tit('should call with indices', () => {\n\t\t\tconst assertion = [];\n\t\t\tconst ProblemChild = ({ children }) => {\n\t\t\t\treturn React.Children.map(children, (child, i) => {\n\t\t\t\t\tassertion.push(i);\n\t\t\t\t\treturn React.Children.map(child.props.children, (x, j) => {\n\t\t\t\t\t\tassertion.push(j);\n\t\t\t\t\t\treturn x;\n\t\t\t\t\t});\n\t\t\t\t}).filter(React.isValidElement);\n\t\t\t};\n\n\t\t\tconst App = () => {\n\t\t\t\treturn (\n\t\t\t\t\t<ProblemChild>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t\t\t<div>4</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</ProblemChild>\n\t\t\t\t);\n\t\t\t};\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.textContent).to.equal('1234');\n\t\t\texpect(assertion.length).to.equal(6);\n\t\t});\n\t});\n\n\tdescribe('.forEach', () => {\n\t\tfunction Foo(props) {\n\t\t\tlet children = [];\n\t\t\tChildren.forEach(props.children, child =>\n\t\t\t\tchildren.push(<span>{child}</span>)\n\t\t\t);\n\t\t\treturn <div>{children}</div>;\n\t\t}\n\n\t\tit('should iterate over children', () => {\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\tfoo<div>bar</div>\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\tlet expected = div([span('foo'), span(div('bar'))]);\n\t\t\texpect(serializeHtml(scratch)).to.equal(expected);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/PureComponent.test.jsx",
    "content": "import React, { createElement } from 'preact/compat';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('PureComponent', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should be a class', () => {\n\t\texpect(React).to.have.property('PureComponent').that.is.a('function');\n\t});\n\n\tit('should pass props in constructor', () => {\n\t\tlet spy = vi.fn();\n\t\tclass Foo extends React.PureComponent {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tspy(this.props, props);\n\t\t\t}\n\t\t}\n\n\t\tReact.render(<Foo foo=\"bar\" />, scratch);\n\n\t\tlet expected = { foo: 'bar' };\n\t\texpect(spy).toHaveBeenCalledWith(expected, expected);\n\t});\n\n\tit('should pass context in constructor', () => {\n\t\tlet instance;\n\t\t// Not initializing state matches React behavior: https://codesandbox.io/s/rml19v8o2q\n\t\tclass Foo extends React.PureComponent {\n\t\t\tconstructor(props, context) {\n\t\t\t\tsuper(props, context);\n\t\t\t\texpect(this.props).to.equal(props);\n\t\t\t\texpect(this.state).to.deep.equal(undefined);\n\t\t\t\texpect(this.context).to.equal(context);\n\n\t\t\t\tinstance = this;\n\t\t\t}\n\t\t\trender(props) {\n\t\t\t\treturn <div {...props}>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\tconst PROPS = { foo: 'bar' };\n\t\tReact.render(<Foo {...PROPS} />, scratch);\n\n\t\texpect(Foo.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, {}, {});\n\t\texpect(Foo.prototype.render).toHaveReturned({ type: 'div', props: PROPS });\n\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\texpect(instance.state).to.deep.equal({});\n\t\texpect(instance.context).to.deep.equal({});\n\n\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t});\n\n\tit('should ignore the __source variable', () => {\n\t\tconst pureSpy = vi.fn();\n\t\tconst appSpy = vi.fn();\n\t\t/** @type {(v) => void} */\n\t\tlet set;\n\t\tclass Pure extends React.PureComponent {\n\t\t\trender() {\n\t\t\t\tpureSpy();\n\t\t\t\treturn <div>Static</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = () => {\n\t\t\tconst [, setState] = React.useState(0);\n\t\t\tappSpy();\n\t\t\tset = setState;\n\t\t\treturn <Pure __source={{}} />;\n\t\t};\n\n\t\tReact.render(<App />, scratch);\n\t\texpect(appSpy).toHaveBeenCalledOnce();\n\t\texpect(pureSpy).toHaveBeenCalledOnce();\n\n\t\tset(1);\n\t\trerender();\n\t\texpect(appSpy).toHaveBeenCalledTimes(2);\n\t\texpect(pureSpy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should only re-render when props or state change', () => {\n\t\tclass C extends React.PureComponent {\n\t\t\trender() {\n\t\t\t\treturn <div />;\n\t\t\t}\n\t\t}\n\t\tlet spy = vi.spyOn(C.prototype, 'render');\n\n\t\tlet inst = React.render(<C />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\tspy.mockClear();\n\n\t\tinst = React.render(<C />, scratch);\n\t\texpect(spy).not.toHaveBeenCalled();\n\n\t\tlet b = { foo: 'bar' };\n\t\tinst = React.render(<C a=\"a\" b={b} />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\tspy.mockClear();\n\n\t\tinst = React.render(<C a=\"a\" b={b} />, scratch);\n\t\texpect(spy).not.toHaveBeenCalled();\n\n\t\tinst.setState({});\n\t\trerender();\n\t\texpect(spy).not.toHaveBeenCalled();\n\n\t\tinst.setState({ a: 'a', b });\n\t\trerender();\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\tspy.mockClear();\n\n\t\tinst.setState({ a: 'a', b });\n\t\trerender();\n\t\texpect(spy).not.toHaveBeenCalled();\n\t});\n\n\tit('should update when props are removed', () => {\n\t\tlet spy = vi.fn();\n\t\tclass App extends React.PureComponent {\n\t\t\trender() {\n\t\t\t\tspy();\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\tReact.render(<App a=\"foo\" />, scratch);\n\t\tReact.render(<App />, scratch);\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('should have \"isPureReactComponent\" property', () => {\n\t\tlet Pure = new React.PureComponent();\n\t\texpect(Pure.isReactComponent).to.deep.equal(true);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/cloneElement.test.jsx",
    "content": "import { createElement as preactH } from 'preact';\nimport { createElement, render, cloneElement } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('compat cloneElement', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should clone elements', () => {\n\t\tlet element = (\n\t\t\t<foo a=\"b\" c=\"d\">\n\t\t\t\ta<span>b</span>\n\t\t\t</foo>\n\t\t);\n\t\tconst clone = cloneElement(element);\n\t\tdelete clone._original;\n\t\tdelete element._original;\n\t\texpect(clone).to.eql(element);\n\t});\n\n\tit('should support props.children', () => {\n\t\tlet element = <foo children={<span>b</span>} />;\n\t\tlet clone = cloneElement(element);\n\t\tdelete clone._original;\n\t\tdelete element._original;\n\t\texpect(clone).to.eql(element);\n\t\texpect(cloneElement(clone).props.children).to.eql(element.props.children);\n\t});\n\n\tit('children take precedence over props.children', () => {\n\t\tlet element = (\n\t\t\t<foo children={<span>c</span>}>\n\t\t\t\t<div>b</div>\n\t\t\t</foo>\n\t\t);\n\t\tlet clone = cloneElement(element);\n\t\tdelete clone._original;\n\t\tdelete element._original;\n\t\texpect(clone).to.eql(element);\n\t\texpect(clone.props.children.type).to.eql('div');\n\t});\n\n\tit('should support children in prop argument', () => {\n\t\tlet element = <foo />;\n\t\tlet children = [<span>b</span>];\n\t\tlet clone = cloneElement(element, { children });\n\t\texpect(clone.props.children).to.eql(children);\n\t});\n\n\tit('single child argument takes precedence over props.children', () => {\n\t\tlet element = <foo />;\n\t\tlet childrenA = [<span>b</span>];\n\t\tlet childrenB = [<div>c</div>];\n\t\tlet clone = cloneElement(element, { children: childrenA }, ...childrenB);\n\t\texpect(clone.props.children).to.eql(childrenB[0]);\n\t});\n\n\tit('multiple children arguments take precedence over props.children', () => {\n\t\tlet element = <foo />;\n\t\tlet childrenA = [<span>b</span>];\n\t\tlet childrenB = [<div>c</div>, 'd'];\n\t\tlet clone = cloneElement(element, { children: childrenA }, ...childrenB);\n\t\texpect(clone.props.children).to.eql(childrenB);\n\t});\n\n\tit('children argument takes precedence over props.children even if falsey', () => {\n\t\tlet element = <foo />;\n\t\tlet childrenA = [<span>b</span>];\n\t\tlet clone = cloneElement(element, { children: childrenA }, undefined);\n\t\texpect(clone.children).to.eql(undefined);\n\t});\n\n\tit('should skip cloning on invalid element', () => {\n\t\tlet element = { foo: 42 };\n\t\t// @ts-expect-error\n\t\tlet clone = cloneElement(element);\n\t\texpect(clone).to.eql(element);\n\t});\n\n\tit('should work with jsx constructor from core', () => {\n\t\tfunction Foo(props) {\n\t\t\treturn <div>{props.value}</div>;\n\t\t}\n\n\t\tlet clone = cloneElement(preactH(Foo, {}), { value: 'foo' });\n\t\trender(clone, scratch);\n\t\texpect(scratch.textContent).to.equal('foo');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/compat.options.test.jsx",
    "content": "import { vnodeSpy, eventSpy } from '../../../test/_util/optionSpies';\nimport {\n\tcreateElement,\n\trender,\n\tComponent,\n\tcreateRef\n} from 'preact/compat';\nimport { setupRerender } from 'preact/test-utils';\nimport {\n\tsetupScratch,\n\tteardown,\n\tcreateEvent\n} from '../../../test/_util/helpers';\n\ndescribe('compat options', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t/** @type {() => void} */\n\tlet increment;\n\n\t/** @type {import('../../src/index').PropRef<HTMLButtonElement | null>} */\n\tlet buttonRef;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\n\t\tvnodeSpy.mockClear();\n\t\teventSpy.mockClear();\n\n\t\tbuttonRef = createRef();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tclass ClassApp extends Component {\n\t\tconstructor() {\n\t\t\tsuper();\n\t\t\tthis.state = { count: 0 };\n\t\t\tincrement = () =>\n\t\t\t\tthis.setState(({ count }) => ({\n\t\t\t\t\tcount: count + 1\n\t\t\t\t}));\n\t\t}\n\n\t\trender() {\n\t\t\treturn (\n\t\t\t\t<button ref={buttonRef} onClick={increment}>\n\t\t\t\t\t{this.state.count}\n\t\t\t\t</button>\n\t\t\t);\n\t\t}\n\t}\n\n\tit('should call old options on mount', () => {\n\t\trender(<ClassApp />, scratch);\n\n\t\texpect(vnodeSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options on event and update', () => {\n\t\trender(<ClassApp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<button>0</button>');\n\n\t\tbuttonRef.current.dispatchEvent(createEvent('click'));\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<button>1</button>');\n\n\t\texpect(vnodeSpy).toHaveBeenCalled();\n\t\texpect(eventSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options on unmount', () => {\n\t\trender(<ClassApp />, scratch);\n\t\trender(null, scratch);\n\n\t\texpect(vnodeSpy).toHaveBeenCalled();\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/component.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport React, { createElement, Component, createRef } from 'preact/compat';\nimport { vi } from 'vitest';\n\ndescribe('components', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should have \"isReactComponent\" property', () => {\n\t\tlet Comp = new React.Component();\n\t\texpect(Comp.isReactComponent).to.deep.equal(true);\n\t});\n\n\tit('should be sane', () => {\n\t\tlet props;\n\n\t\tclass Demo extends React.Component {\n\t\t\trender() {\n\t\t\t\tprops = this.props;\n\t\t\t\treturn <div id=\"demo\">{this.props.children}</div>;\n\t\t\t}\n\t\t}\n\n\t\tReact.render(\n\t\t\t<Demo a=\"b\" c=\"d\">\n\t\t\t\tinner\n\t\t\t</Demo>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(props).to.exist.and.deep.equal({\n\t\t\ta: 'b',\n\t\t\tc: 'd',\n\t\t\tchildren: 'inner'\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.equal('<div id=\"demo\">inner</div>');\n\t});\n\n\tit('should single out children before componentWillReceiveProps', () => {\n\t\tlet props;\n\n\t\tclass Child extends React.Component {\n\t\t\tcomponentWillReceiveProps(newProps) {\n\t\t\t\tprops = newProps;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tclass Parent extends React.Component {\n\t\t\trender() {\n\t\t\t\treturn <Child>second</Child>;\n\t\t\t}\n\t\t}\n\n\t\tlet a = React.render(<Parent />, scratch);\n\t\ta.forceUpdate();\n\t\trerender();\n\n\t\texpect(props).to.exist.and.deep.equal({\n\t\t\tchildren: 'second'\n\t\t});\n\t});\n\n\tdescribe('UNSAFE_* lifecycle methods', () => {\n\t\tit('should support UNSAFE_componentWillMount', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass Foo extends React.Component {\n\t\t\t\t// eslint-disable-next-line camelcase\n\t\t\t\tUNSAFE_componentWillMount() {\n\t\t\t\t\tspy();\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>foo</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tReact.render(<Foo />, scratch);\n\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should support UNSAFE_componentWillMount #2', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass Foo extends React.Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>foo</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tObject.defineProperty(Foo.prototype, 'UNSAFE_componentWillMount', {\n\t\t\t\tvalue: spy\n\t\t\t});\n\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should support UNSAFE_componentWillReceiveProps', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass Foo extends React.Component {\n\t\t\t\t// eslint-disable-next-line camelcase\n\t\t\t\tUNSAFE_componentWillReceiveProps() {\n\t\t\t\t\tspy();\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>foo</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\t// Trigger an update\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should support UNSAFE_componentWillReceiveProps #2', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass Foo extends React.Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>foo</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tObject.defineProperty(Foo.prototype, 'UNSAFE_componentWillReceiveProps', {\n\t\t\t\tvalue: spy\n\t\t\t});\n\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\t// Trigger an update\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should support UNSAFE_componentWillUpdate', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass Foo extends React.Component {\n\t\t\t\t// eslint-disable-next-line camelcase\n\t\t\t\tUNSAFE_componentWillUpdate() {\n\t\t\t\t\tspy();\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>foo</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\t// Trigger an update\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should support UNSAFE_componentWillUpdate #2', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass Foo extends React.Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>foo</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tObject.defineProperty(Foo.prototype, 'UNSAFE_componentWillUpdate', {\n\t\t\t\tvalue: spy\n\t\t\t});\n\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\t// Trigger an update\n\t\t\tReact.render(<Foo />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should not forward refs on class components', () => {\n\t\t\tconst ref = createRef();\n\t\t\tclass Foo extends React.Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>foo</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t\tReact.render(<Foo ref={ref} />, scratch);\n\t\t\texpect(ref.current).not.to.be.undefined;\n\t\t\texpect(ref.current instanceof Foo).to.equal(true);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>foo</div>');\n\t\t});\n\n\t\tit('should forward refs on functional components', () => {\n\t\t\tconst ref = createRef();\n\t\t\tconst Foo = props => <div ref={props.ref}>foo</div>;\n\t\t\tReact.render(<Foo ref={ref} />, scratch);\n\t\t\texpect(ref.current).not.to.be.undefined;\n\t\t\texpect(ref.current.nodeName).to.equal('DIV');\n\t\t\texpect(scratch.innerHTML).to.equal('<div>foo</div>');\n\t\t});\n\n\t\tit('should alias UNSAFE_* method to non-prefixed variant', () => {\n\t\t\tlet inst;\n\t\t\tclass Foo extends React.Component {\n\t\t\t\t// eslint-disable-next-line camelcase\n\t\t\t\tUNSAFE_componentWillMount() {}\n\t\t\t\t// eslint-disable-next-line camelcase\n\t\t\t\tUNSAFE_componentWillReceiveProps() {}\n\t\t\t\t// eslint-disable-next-line camelcase\n\t\t\t\tUNSAFE_componentWillUpdate() {}\n\t\t\t\trender() {\n\t\t\t\t\tinst = this;\n\t\t\t\t\treturn <div>foo</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tReact.render(<Foo />, scratch);\n\n\t\t\texpect(inst.UNSAFE_componentWillMount).to.equal(inst.componentWillMount);\n\t\t\texpect(inst.UNSAFE_componentWillReceiveProps).to.equal(\n\t\t\t\tinst.UNSAFE_componentWillReceiveProps\n\t\t\t);\n\t\t\texpect(inst.UNSAFE_componentWillUpdate).to.equal(\n\t\t\t\tinst.UNSAFE_componentWillUpdate\n\t\t\t);\n\t\t});\n\n\t\tit('should call UNSAFE_* methods through Suspense with wrapper component #2525', () => {\n\t\t\tclass Page extends React.Component {\n\t\t\t\tUNSAFE_componentWillMount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <h1>Example</h1>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst Wrapper = () => <Page />;\n\n\t\t\tvi.spyOn(Page.prototype, 'UNSAFE_componentWillMount');\n\n\t\t\tReact.render(\n\t\t\t\t<React.Suspense fallback={<div>fallback</div>}>\n\t\t\t\t\t<Wrapper />\n\t\t\t\t</React.Suspense>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<h1>Example</h1>');\n\t\t\texpect(Page.prototype.UNSAFE_componentWillMount).toHaveBeenCalled();\n\t\t});\n\t});\n\n\tdescribe('defaultProps', () => {\n\t\tit('should apply default props on initial render', () => {\n\t\t\tclass WithDefaultProps extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\texpect(props).to.be.deep.equal({\n\t\t\t\t\t\tfieldA: 1,\n\t\t\t\t\t\tfieldB: 2,\n\t\t\t\t\t\tfieldC: 1,\n\t\t\t\t\t\tfieldD: 2\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tWithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };\n\t\t\tReact.render(\n\t\t\t\t<WithDefaultProps fieldA={1} fieldB={2} fieldD={2} />,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\tit('should apply default props on rerender', () => {\n\t\t\tlet doRender;\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { i: 1 };\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tdoRender = () => this.setState({ i: 2 });\n\t\t\t\t}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <WithDefaultProps fieldA={1} fieldB={i} fieldD={i} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass WithDefaultProps extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.ctor(props, context);\n\t\t\t\t}\n\t\t\t\tctor() {}\n\t\t\t\tcomponentWillReceiveProps() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tWithDefaultProps.defaultProps = { fieldC: 1, fieldD: 1 };\n\n\t\t\tlet proto = WithDefaultProps.prototype;\n\t\t\tvi.spyOn(proto, 'ctor');\n\t\t\tvi.spyOn(proto, 'componentWillReceiveProps');\n\t\t\tvi.spyOn(proto, 'render');\n\n\t\t\tReact.render(<Outer />, scratch);\n\t\t\tdoRender();\n\n\t\t\tconst PROPS1 = {\n\t\t\t\tfieldA: 1,\n\t\t\t\tfieldB: 1,\n\t\t\t\tfieldC: 1,\n\t\t\t\tfieldD: 1\n\t\t\t};\n\n\t\t\tconst PROPS2 = {\n\t\t\t\tfieldA: 1,\n\t\t\t\tfieldB: 2,\n\t\t\t\tfieldC: 1,\n\t\t\t\tfieldD: 2\n\t\t\t};\n\n\t\t\texpect(proto.ctor).toHaveBeenCalledWith(PROPS1, {});\n\t\t\texpect(proto.render).toHaveBeenCalledWith(PROPS1, {}, {});\n\n\t\t\trerender();\n\n\t\t\t// expect(proto.ctor).to.have.been.calledWith(PROPS2);\n\t\t\texpect(proto.componentWillReceiveProps).toHaveBeenCalledWith(PROPS2, {});\n\t\t\texpect(proto.render).toHaveBeenCalledWith(PROPS2, {}, {});\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/componentDidCatch.test.jsx",
    "content": "import { createElement, render, Component } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { act } from 'preact/test-utils';\n\ndescribe('componentDidCatch', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should pass errorInfo in compat', () => {\n\t\tlet info;\n\t\tlet update;\n\t\tclass Receiver extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { error: null, i: 0 };\n\t\t\t\tupdate = this.setState.bind(this);\n\t\t\t}\n\t\t\tcomponentDidCatch(error, errorInfo) {\n\t\t\t\tinfo = errorInfo;\n\t\t\t\tthis.setState({ error });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tif (this.state.error) return <div />;\n\t\t\t\t// @ts-expect-error\n\t\t\t\tif (this.state.i === 0) return <ThrowErr />;\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tfunction ThrowErr() {\n\t\t\tthrow new Error('fail');\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<Receiver />, scratch);\n\t\t});\n\n\t\tact(() => {\n\t\t\tupdate({ i: 1 });\n\t\t});\n\n\t\texpect(info).to.deep.equal({});\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/context.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport {\n\trender,\n\tcreateElement,\n\tFragment,\n\tcreateContext,\n\tComponent,\n\tuseState,\n\tuseContext\n} from 'preact/compat';\n\ndescribe('components', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('nested context updates propagate throughout the tree synchronously', () => {\n\t\tconst RouterContext = createContext({ location: '__default_value__' });\n\n\t\tconst route1 = '/page/1';\n\t\tconst route2 = '/page/2';\n\n\t\t/** @type {() => void} */\n\t\tlet toggleLocalState;\n\t\t/** @type {() => void} */\n\t\tlet toggleLocation;\n\n\t\t/** @type {Array<{location: string, localState: boolean}>} */\n\t\tlet pageRenders = [];\n\n\t\tfunction runUpdate() {\n\t\t\ttoggleLocalState();\n\t\t\ttoggleLocation();\n\t\t}\n\n\t\t/**\n\t\t * @extends {Component<{children: any}, {location: string}>}\n\t\t */\n\t\tclass Router extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { location: route1 };\n\t\t\t\ttoggleLocation = () => {\n\t\t\t\t\tconst oldLocation = this.state.location;\n\t\t\t\t\tconst newLocation = oldLocation === route1 ? route2 : route1;\n\t\t\t\t\t// console.log('Toggling  location', oldLocation, '->', newLocation);\n\t\t\t\t\tthis.setState({ location: newLocation });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\t// console.log('Rendering Router', { location: this.state.location });\n\t\t\t\treturn (\n\t\t\t\t\t<RouterContext.Provider value={{ location: this.state.location }}>\n\t\t\t\t\t\t{this.props.children}\n\t\t\t\t\t</RouterContext.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @extends {Component<{children: any}>}\n\t\t */\n\t\tclass Route extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<RouterContext.Consumer>\n\t\t\t\t\t\t{contextValue => {\n\t\t\t\t\t\t\t// console.log('Rendering Route', {\n\t\t\t\t\t\t\t// \tlocation: contextValue.location\n\t\t\t\t\t\t\t// });\n\t\t\t\t\t\t\t// Pretend to do something with the context value\n\t\t\t\t\t\t\tconst newContextValue = { ...contextValue };\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<RouterContext.Provider value={newContextValue}>\n\t\t\t\t\t\t\t\t\t{this.props.children}\n\t\t\t\t\t\t\t\t</RouterContext.Provider>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}}\n\t\t\t\t\t</RouterContext.Consumer>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tfunction Page() {\n\t\t\tconst [localState, setLocalState] = useState(true);\n\t\t\tconst { location } = useContext(RouterContext);\n\n\t\t\tpageRenders.push({ location, localState });\n\t\t\t// console.log('Rendering Page', { location, localState });\n\n\t\t\ttoggleLocalState = () => {\n\t\t\t\tlet newValue = !localState;\n\t\t\t\t// console.log('Toggling  localState', localState, '->', newValue);\n\t\t\t\tsetLocalState(newValue);\n\t\t\t};\n\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t<div>localState: {localState.toString()}</div>\n\t\t\t\t\t<div>location: {location}</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<button type=\"button\" onClick={runUpdate}>\n\t\t\t\t\t\t\tTrigger update\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t);\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<Router>\n\t\t\t\t\t<Route>\n\t\t\t\t\t\t<Page />\n\t\t\t\t\t</Route>\n\t\t\t\t</Router>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(pageRenders).to.deep.equal([{ location: route1, localState: true }]);\n\n\t\tpageRenders = [];\n\t\trunUpdate(); // Simulate button click\n\t\trerender();\n\n\t\t// Page should rerender once with both propagated context and local state updates\n\t\texpect(pageRenders).to.deep.equal([\n\t\t\t{ location: route2, localState: false }\n\t\t]);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/createElement.test.jsx",
    "content": "import { createElement, render } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { getSymbol } from './testUtils';\n\ndescribe('compat createElement()', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should normalize vnodes', () => {\n\t\tlet vnode = (\n\t\t\t<div a=\"b\">\n\t\t\t\t<a>t</a>\n\t\t\t</div>\n\t\t);\n\n\t\tconst $$typeof = getSymbol('react.element', 0xeac7);\n\t\texpect(vnode).to.have.property('$$typeof', $$typeof);\n\t\texpect(vnode).to.have.property('type', 'div');\n\t\texpect(vnode).to.have.property('props').that.is.an('object');\n\t\texpect(vnode.props).to.have.property('children');\n\t\texpect(vnode.props.children).to.have.property('$$typeof', $$typeof);\n\t\texpect(vnode.props.children).to.have.property('type', 'a');\n\t\texpect(vnode.props.children).to.have.property('props').that.is.an('object');\n\t\texpect(vnode.props.children.props).to.eql({ children: 't' });\n\t});\n\n\tit('should not normalize text nodes', () => {\n\t\t// @ts-expect-error\n\t\tString.prototype.capFLetter = function () {\n\t\t\treturn this.charAt(0).toUpperCase() + this.slice(1);\n\t\t};\n\t\tlet vnode = <div>hi buddy</div>;\n\n\t\trender(vnode, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>hi buddy</div>');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/createFactory.test.jsx",
    "content": "import { render, createElement, createFactory } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('createFactory', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should create a DOM element', () => {\n\t\trender(createFactory('span')({ class: 'foo' }, '1'), scratch);\n\t\texpect(scratch.innerHTML).to.equal('<span class=\"foo\">1</span>');\n\t});\n\n\tit('should create a component', () => {\n\t\tconst Foo = ({ id, children }) => <div id={id}>foo {children}</div>;\n\t\trender(createFactory(Foo)({ id: 'value' }, 'bar'), scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div id=\"value\">foo bar</div>');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/events.test.jsx",
    "content": "import { render } from 'preact';\nimport {\n\tsetupScratch,\n\tteardown,\n\tcreateEvent,\n\tsupportsPassiveEvents\n} from '../../../test/_util/helpers';\n\nimport { createElement } from 'preact/compat';\nimport { vi } from 'vitest';\n\ndescribe('preact/compat events', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\tlet proto;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\n\t\tproto = Element.prototype;\n\t\tvi.spyOn(proto, 'addEventListener');\n\t\tvi.spyOn(proto, 'removeEventListener');\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\n\t\tproto.addEventListener.mockRestore();\n\t\tproto.removeEventListener.mockRestore();\n\t});\n\n\tit('should patch events', () => {\n\t\tlet spy = vi.fn(event => {\n\t\t\texpect(event.isDefaultPrevented()).to.be.false;\n\t\t\tevent.preventDefault();\n\t\t\texpect(event.isDefaultPrevented()).to.be.true;\n\n\t\t\texpect(event.isPropagationStopped()).to.be.false;\n\t\t\tevent.stopPropagation();\n\t\t\texpect(event.isPropagationStopped()).to.be.true;\n\t\t});\n\n\t\trender(<div onClick={spy} />, scratch);\n\t\tscratch.firstChild.click();\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\tconst event = spy.mock.calls[0][0];\n\t\texpect(event).to.haveOwnProperty('persist');\n\t\texpect(event).to.haveOwnProperty('nativeEvent');\n\t\texpect(event).to.haveOwnProperty('isDefaultPrevented');\n\t\texpect(event).to.haveOwnProperty('isPropagationStopped');\n\t\texpect(typeof event.persist).to.equal('function');\n\t\texpect(typeof event.isDefaultPrevented).to.equal('function');\n\t\texpect(typeof event.isPropagationStopped).to.equal('function');\n\n\t\texpect(() => event.persist()).to.not.throw();\n\t\texpect(() => event.isDefaultPrevented()).to.not.throw();\n\t\texpect(() => event.isPropagationStopped()).to.not.throw();\n\t});\n\n\tit('should normalize ondoubleclick event', () => {\n\t\tlet vnode = <div onDoubleClick={() => null} />;\n\t\texpect(vnode.props).to.haveOwnProperty('ondblclick');\n\t});\n\n\tit('should normalize onChange for textarea', () => {\n\t\tlet vnode = <textarea onChange={() => null} />;\n\t\texpect(vnode.props).to.haveOwnProperty('oninput');\n\t\texpect(vnode.props).to.not.haveOwnProperty('onchange');\n\n\t\tvnode = <textarea oninput={() => null} onChange={() => null} />;\n\t\texpect(vnode.props).to.haveOwnProperty('oninput');\n\t\texpect(vnode.props).to.not.haveOwnProperty('onchange');\n\t});\n\n\tit('should by pass onInputCapture normalization for custom onInputAction when using it along with onChange', () => {\n\t\tconst onInputAction = () => null;\n\t\tconst onChange = () => null;\n\n\t\tlet vnode = <textarea onChange={onChange} onInputAction={onInputAction} />;\n\n\t\texpect(vnode.props).to.haveOwnProperty('onInputAction');\n\t\texpect(vnode.props.onInputAction).to.equal(onInputAction);\n\t\texpect(vnode.props).to.haveOwnProperty('oninput');\n\t\texpect(vnode.props.oninput).to.equal(onChange);\n\t\texpect(vnode.props).to.not.haveOwnProperty('oninputCapture');\n\t});\n\n\tit('should normalize onChange for range', () => {\n\t\trender(<input type=\"range\" onChange={() => null} />, scratch);\n\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'input',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t});\n\n\tit('should support onAnimationEnd', () => {\n\t\tconst func = vi.fn(() => {});\n\t\trender(<div onAnimationEnd={func} />, scratch);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'animationend',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('animationend'));\n\t\texpect(func).toHaveBeenCalledOnce();\n\n\t\trender(<div />, scratch);\n\t\texpect(proto.removeEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.removeEventListener).toHaveBeenCalledWith(\n\t\t\t'animationend',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t});\n\n\tit('should support onTouch* events', () => {\n\t\tconst onTouchStart = vi.fn();\n\t\tconst onTouchEnd = vi.fn();\n\t\tconst onTouchMove = vi.fn();\n\t\tconst onTouchCancel = vi.fn();\n\n\t\trender(\n\t\t\t<div\n\t\t\t\tonTouchStart={onTouchStart}\n\t\t\t\tonTouchEnd={onTouchEnd}\n\t\t\t\tonTouchMove={onTouchMove}\n\t\t\t\tonTouchCancel={onTouchCancel}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(proto.addEventListener.mock.calls.length).to.eql(4);\n\t\texpect(proto.addEventListener.mock.calls[0].length).to.eql(3);\n\t\texpect(proto.addEventListener.mock.calls[0][0]).to.eql('touchstart');\n\t\texpect(proto.addEventListener.mock.calls[0][2]).to.eql(false);\n\t\texpect(proto.addEventListener.mock.calls[1].length).to.eql(3);\n\t\texpect(proto.addEventListener.mock.calls[1][0]).to.eql('touchend');\n\t\texpect(proto.addEventListener.mock.calls[1][2]).to.eql(false);\n\t\texpect(proto.addEventListener.mock.calls[2].length).to.eql(3);\n\t\texpect(proto.addEventListener.mock.calls[2][0]).to.eql('touchmove');\n\t\texpect(proto.addEventListener.mock.calls[2][2]).to.eql(false);\n\t\texpect(proto.addEventListener.mock.calls[3].length).to.eql(3);\n\t\texpect(proto.addEventListener.mock.calls[3][0]).to.eql('touchcancel');\n\t\texpect(proto.addEventListener.mock.calls[3][2]).to.eql(false);\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('touchstart'));\n\t\texpect(onTouchStart).toHaveBeenCalledOnce();\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('touchmove'));\n\t\texpect(onTouchMove).toHaveBeenCalledOnce();\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('touchend'));\n\t\texpect(onTouchEnd).toHaveBeenCalledOnce();\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('touchcancel'));\n\t\texpect(onTouchCancel).toHaveBeenCalledOnce();\n\n\t\trender(<div />, scratch);\n\n\t\texpect(proto.removeEventListener.mock.calls.length).to.eql(4);\n\t\texpect(proto.removeEventListener.mock.calls[0].length).to.eql(3);\n\t\texpect(proto.removeEventListener.mock.calls[0][0]).to.eql('touchstart');\n\t\texpect(proto.removeEventListener.mock.calls[0][2]).to.eql(false);\n\t\texpect(proto.removeEventListener.mock.calls[1].length).to.eql(3);\n\t\texpect(proto.removeEventListener.mock.calls[1][0]).to.eql('touchend');\n\t\texpect(proto.removeEventListener.mock.calls[1][2]).to.eql(false);\n\t\texpect(proto.removeEventListener.mock.calls[2].length).to.eql(3);\n\t\texpect(proto.removeEventListener.mock.calls[2][0]).to.eql('touchmove');\n\t\texpect(proto.removeEventListener.mock.calls[2][2]).to.eql(false);\n\t\texpect(proto.removeEventListener.mock.calls[3].length).to.eql(3);\n\t\texpect(proto.removeEventListener.mock.calls[3][0]).to.eql('touchcancel');\n\t\texpect(proto.removeEventListener.mock.calls[3][2]).to.eql(false);\n\t});\n\n\tit('should support onTransitionEnd', () => {\n\t\tconst func = vi.fn(() => {});\n\t\trender(<div onTransitionEnd={func} />, scratch);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'transitionend',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('transitionend'));\n\t\texpect(func).toHaveBeenCalledOnce();\n\n\t\trender(<div />, scratch);\n\t\texpect(proto.removeEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.removeEventListener).toHaveBeenCalledWith(\n\t\t\t'transitionend',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t});\n\n\tit('should normalize onChange', () => {\n\t\tlet props = { onChange() {} };\n\n\t\tfunction expectToBeNormalized(vnode, desc) {\n\t\t\texpect(vnode, desc)\n\t\t\t\t.to.have.property('props')\n\t\t\t\t.with.all.keys(['oninput'].concat(vnode.props.type ? 'type' : []))\n\t\t\t\t.and.property('oninput')\n\t\t\t\t.that.is.a('function');\n\t\t}\n\n\t\tfunction expectToBeUnmodified(vnode, desc) {\n\t\t\texpect(vnode, desc)\n\t\t\t\t.to.have.property('props')\n\t\t\t\t.eql({\n\t\t\t\t\t...props,\n\t\t\t\t\t...(vnode.props.type ? { type: vnode.props.type } : {})\n\t\t\t\t});\n\t\t}\n\n\t\texpectToBeUnmodified(<div {...props} />, '<div>');\n\t\texpectToBeUnmodified(\n\t\t\t<input {...props} type=\"radio\" />,\n\t\t\t'<input type=\"radio\">'\n\t\t);\n\t\texpectToBeUnmodified(\n\t\t\t<input {...props} type=\"checkbox\" />,\n\t\t\t'<input type=\"checkbox\">'\n\t\t);\n\t\texpectToBeUnmodified(\n\t\t\t<input {...props} type=\"file\" />,\n\t\t\t'<input type=\"file\">'\n\t\t);\n\n\t\texpectToBeNormalized(<textarea {...props} />, '<textarea>');\n\t\texpectToBeNormalized(<input {...props} />, '<input>');\n\t\texpectToBeNormalized(\n\t\t\t<input {...props} type=\"text\" />,\n\t\t\t'<input type=\"text\">'\n\t\t);\n\t});\n\n\tit('should normalize beforeinput event listener', () => {\n\t\tlet spy = vi.fn();\n\t\trender(<input onBeforeInput={spy} />, scratch);\n\t\tscratch.firstChild.dispatchEvent(createEvent('beforeinput'));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should normalize compositionstart event listener', () => {\n\t\tlet spy = vi.fn();\n\t\trender(<input onCompositionStart={spy} />, scratch);\n\t\tscratch.firstChild.dispatchEvent(createEvent('compositionstart'));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should normalize onFocus to onfocusin', () => {\n\t\tlet spy = vi.fn();\n\t\trender(<input onFocus={spy} />, scratch);\n\t\tscratch.firstChild.dispatchEvent(createEvent('focusin'));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should normalize onBlur to onfocusout', () => {\n\t\tlet spy = vi.fn();\n\t\trender(<input onBlur={spy} />, scratch);\n\t\tscratch.firstChild.dispatchEvent(createEvent('focusout'));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tif (supportsPassiveEvents()) {\n\t\tit('should use capturing for event props ending with *Capture', () => {\n\t\t\tlet click = vi.fn();\n\n\t\t\trender(\n\t\t\t\t<div onTouchMoveCapture={click}>\n\t\t\t\t\t<button type=\"button\">Click me</button>\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t\t'touchmove',\n\t\t\t\texpect.any(Function),\n\t\t\t\ttrue\n\t\t\t);\n\t\t});\n\t}\n});\n"
  },
  {
    "path": "compat/test/browser/exports.test.js",
    "content": "import Compat from 'preact/compat';\nimport CompatClient from 'preact/compat/client';\n// eslint-disable-next-line no-duplicate-imports\nimport * as Named from 'preact/compat';\n// eslint-disable-next-line no-duplicate-imports\nimport * as NamedClient from 'preact/compat/client';\n\ndescribe('compat exports', () => {\n\tdescribe('client', () => {\n\t\tit('should have a default export', () => {\n\t\t\texpect(CompatClient.createRoot).to.be.a('function');\n\t\t\texpect(CompatClient.hydrateRoot).to.be.a('function');\n\t\t});\n\n\t\tit('should have named exports', () => {\n\t\t\texpect(NamedClient.createRoot).to.be.a('function');\n\t\t\texpect(NamedClient.hydrateRoot).to.be.a('function');\n\t\t});\n\t});\n\n\tit('should have a default export', () => {\n\t\texpect(Compat.createElement).to.be.a('function');\n\t\texpect(Compat.Component).to.be.a('function');\n\t\texpect(Compat.Fragment).to.exist;\n\t\texpect(Compat.render).to.be.a('function');\n\t\texpect(Compat.hydrate).to.be.a('function');\n\t\texpect(Compat.cloneElement).to.be.a('function');\n\t\texpect(Compat.createContext).to.be.a('function');\n\t\texpect(Compat.createRef).to.be.a('function');\n\n\t\t// Hooks\n\t\texpect(Compat.useState).to.be.a('function');\n\t\texpect(Compat.useReducer).to.be.a('function');\n\t\texpect(Compat.useEffect).to.be.a('function');\n\t\texpect(Compat.useLayoutEffect).to.be.a('function');\n\t\texpect(Compat.useRef).to.be.a('function');\n\t\texpect(Compat.useMemo).to.be.a('function');\n\t\texpect(Compat.useCallback).to.be.a('function');\n\t\texpect(Compat.useContext).to.be.a('function');\n\t\texpect(Compat.useSyncExternalStore).to.be.a('function');\n\t\texpect(Compat.useInsertionEffect).to.be.a('function');\n\t\texpect(Compat.useTransition).to.be.a('function');\n\t\texpect(Compat.useDeferredValue).to.be.a('function');\n\n\t\t// Suspense\n\t\texpect(Compat.Suspense).to.be.a('function');\n\t\texpect(Compat.lazy).to.be.a('function');\n\n\t\t// Compat specific\n\t\texpect(Compat.PureComponent).to.exist.and.be.a('function');\n\t\texpect(Compat.createPortal).to.exist.and.be.a('function');\n\t\texpect(Compat.createFactory).to.exist.and.be.a('function');\n\t\texpect(Compat.isValidElement).to.exist.and.be.a('function');\n\t\texpect(Compat.findDOMNode).to.exist.and.be.a('function');\n\t\texpect(Compat.Children.map).to.exist.and.be.a('function');\n\t\texpect(Compat.Children.forEach).to.exist.and.be.a('function');\n\t\texpect(Compat.Children.count).to.exist.and.be.a('function');\n\t\texpect(Compat.Children.toArray).to.exist.and.be.a('function');\n\t\texpect(Compat.Children.only).to.exist.and.be.a('function');\n\t\texpect(Compat.unmountComponentAtNode).to.exist.and.be.a('function');\n\t\texpect(Compat.version).to.exist.and.be.a('string');\n\t\texpect(Compat.startTransition).to.be.a('function');\n\t\texpect(Compat.unstable_batchedUpdates).to.be.a('function');\n\t});\n\n\tit('should have named exports', () => {\n\t\texpect(Named.createElement).to.be.a('function');\n\t\texpect(Named.Component).to.be.a('function');\n\t\texpect(Named.Fragment).to.exist;\n\t\texpect(Named.render).to.be.a('function');\n\t\texpect(Named.hydrate).to.be.a('function');\n\t\texpect(Named.cloneElement).to.be.a('function');\n\t\texpect(Named.createContext).to.be.a('function');\n\t\texpect(Named.createRef).to.be.a('function');\n\n\t\t// Hooks\n\t\texpect(Named.useState).to.be.a('function');\n\t\texpect(Named.useReducer).to.be.a('function');\n\t\texpect(Named.useEffect).to.be.a('function');\n\t\texpect(Named.useLayoutEffect).to.be.a('function');\n\t\texpect(Named.useRef).to.be.a('function');\n\t\texpect(Named.useMemo).to.be.a('function');\n\t\texpect(Named.useCallback).to.be.a('function');\n\t\texpect(Named.useContext).to.be.a('function');\n\n\t\t// Suspense\n\t\texpect(Named.Suspense).to.be.a('function');\n\t\texpect(Named.lazy).to.be.a('function');\n\n\t\t// Compat specific\n\t\texpect(Named.PureComponent).to.exist.and.be.a('function');\n\t\texpect(Named.createPortal).to.exist.and.be.a('function');\n\t\texpect(Named.createFactory).to.exist.and.be.a('function');\n\t\texpect(Named.isValidElement).to.exist.and.be.a('function');\n\t\texpect(Named.findDOMNode).to.exist.and.be.a('function');\n\t\texpect(Named.Children.map).to.exist.and.be.a('function');\n\t\texpect(Named.Children.forEach).to.exist.and.be.a('function');\n\t\texpect(Named.Children.count).to.exist.and.be.a('function');\n\t\texpect(Named.Children.toArray).to.exist.and.be.a('function');\n\t\texpect(Named.Children.only).to.exist.and.be.a('function');\n\t\texpect(Named.unmountComponentAtNode).to.exist.and.be.a('function');\n\t\texpect(Named.version).to.exist.and.be.a('string');\n\t\texpect(Named.unstable_batchedUpdates).to.be.a('function');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/findDOMNode.test.jsx",
    "content": "import React, { createElement, findDOMNode } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('findDOMNode()', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tclass Helper extends React.Component {\n\t\trender({ something }) {\n\t\t\tif (something == null) return null;\n\t\t\tif (something === false) return null;\n\t\t\treturn <div />;\n\t\t}\n\t}\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit.skip('should return DOM Node if render is not false nor null', () => {\n\t\tconst helper = React.render(<Helper />, scratch);\n\t\texpect(findDOMNode(helper)).to.be.instanceof(Node);\n\t});\n\n\tit('should return null if given null', () => {\n\t\texpect(findDOMNode(null)).to.be.null;\n\t});\n\n\tit('should return a regular DOM Element if given a regular DOM Element', () => {\n\t\tlet scratch = document.createElement('div');\n\t\texpect(findDOMNode(scratch)).to.equalNode(scratch);\n\t});\n\n\t// NOTE: React.render() returning false or null has the component pointing\n\t// \t\t\tto no DOM Node, in contrast, Preact always render an empty Text DOM Node.\n\tit('should return null if render returns false', () => {\n\t\tconst helper = React.render(<Helper something={false} />, scratch);\n\t\texpect(findDOMNode(helper)).to.be.null;\n\t});\n\n\t// NOTE: React.render() returning false or null has the component pointing\n\t// \t\t\tto no DOM Node, in contrast, Preact always render an empty Text DOM Node.\n\tit('should return null if render returns null', () => {\n\t\tconst helper = React.render(<Helper something={null} />, scratch);\n\t\texpect(findDOMNode(helper)).to.be.null;\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/forwardRef.test.jsx",
    "content": "import {\n\tcreateElement,\n\trender,\n\tcreateRef,\n\tforwardRef,\n\thydrate,\n\tmemo,\n\tuseState,\n\tuseRef,\n\tuseImperativeHandle,\n\tcreatePortal,\n\tComponent\n} from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { setupRerender, act } from 'preact/test-utils';\nimport { getSymbol } from './testUtils';\nimport { vi } from 'vitest';\n\n/* eslint-disable react/jsx-boolean-value, react/display-name, prefer-arrow-callback */\n\ndescribe('forwardRef', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch, rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should have isReactComponent flag', () => {\n\t\tlet App = forwardRef((_, ref) => <div ref={ref}>foo</div>);\n\t\texpect(App.prototype.isReactComponent).to.equal(true);\n\t});\n\n\tit.skip('should have $$typeof property', () => {\n\t\tlet App = forwardRef((_, ref) => <div ref={ref}>foo</div>);\n\t\tconst expected = getSymbol('react.forward_ref', 0xf47);\n\t\texpect(App.$$typeof).to.equal(expected);\n\t});\n\n\tit('should pass ref with createRef', () => {\n\t\tlet App = forwardRef((_, ref) => <div ref={ref}>foo</div>);\n\t\tlet ref = createRef();\n\t\trender(<App ref={ref} />, scratch);\n\n\t\texpect(ref.current).to.equalNode(scratch.firstChild);\n\t});\n\n\tit('should share the same ref reference', () => {\n\t\tlet passedRef;\n\t\tlet App = forwardRef((_, ref) => {\n\t\t\tpassedRef = ref;\n\t\t\treturn <div ref={ref}>foo</div>;\n\t\t});\n\n\t\tlet ref = createRef();\n\t\trender(<App ref={ref} />, scratch);\n\n\t\texpect(ref).to.equal(passedRef);\n\t});\n\n\tit('should pass ref with a callback', () => {\n\t\tlet App = forwardRef((_, ref) => (\n\t\t\t<div>\n\t\t\t\t<span ref={ref}>foo</span>\n\t\t\t</div>\n\t\t));\n\t\tlet ref;\n\t\trender(<App ref={x => (ref = x)} />, scratch);\n\n\t\texpect(ref).to.equalNode(scratch.firstChild.firstChild);\n\t});\n\n\tit('should forward props', () => {\n\t\tlet spy = vi.fn();\n\t\tlet App = forwardRef(spy);\n\t\trender(<App foo=\"bar\" />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledWith({ foo: 'bar' }, null);\n\t});\n\n\tit('should support nesting', () => {\n\t\tlet passedRef;\n\t\tlet Inner = forwardRef((_, ref) => {\n\t\t\tpassedRef = ref;\n\t\t\treturn <div ref={ref}>inner</div>;\n\t\t});\n\t\tlet App = forwardRef((_, ref) => <Inner ref={ref} />);\n\n\t\tlet ref = createRef();\n\t\trender(<App ref={ref} />, scratch);\n\n\t\texpect(ref).to.equal(passedRef);\n\t});\n\n\tit('should forward null on unmount', () => {\n\t\tlet passedRef;\n\t\tlet App = forwardRef((_, ref) => {\n\t\t\tpassedRef = ref;\n\t\t\treturn <div ref={ref}>foo</div>;\n\t\t});\n\n\t\tlet ref = createRef();\n\t\trender(<App ref={ref} />, scratch);\n\t\trender(null, scratch);\n\n\t\texpect(passedRef.current).to.equal(null);\n\t});\n\n\tit('should be able to render and hydrate forwardRef components', () => {\n\t\tconst Foo = ({ label, forwardedRef }) => (\n\t\t\t<div ref={forwardedRef}>{label}</div>\n\t\t);\n\t\tconst App = forwardRef((props, ref) => (\n\t\t\t<Foo {...props} forwardedRef={ref} />\n\t\t));\n\n\t\tconst ref = createRef();\n\t\tconst markup = <App ref={ref} label=\"Hi\" />;\n\n\t\tconst element = document.createElement('div');\n\t\telement.innerHTML = '<div>Hi</div>';\n\t\texpect(element.textContent).to.equal('Hi');\n\t\texpect(ref.current == null).to.equal(true);\n\n\t\thydrate(markup, element);\n\t\texpect(element.textContent).to.equal('Hi');\n\t\texpect(ref.current.tagName).to.equal('DIV');\n\t});\n\n\tit('should update refs when switching between children', () => {\n\t\tfunction Foo({ forwardedRef, setRefOnDiv }) {\n\t\t\treturn (\n\t\t\t\t<section>\n\t\t\t\t\t<div ref={setRefOnDiv ? forwardedRef : null}>First</div>\n\t\t\t\t\t<span ref={setRefOnDiv ? null : forwardedRef}>Second</span>\n\t\t\t\t</section>\n\t\t\t);\n\t\t}\n\n\t\tconst App = forwardRef((props, ref) => (\n\t\t\t<Foo {...props} forwardedRef={ref} />\n\t\t));\n\n\t\tconst ref = createRef();\n\n\t\trender(<App ref={ref} setRefOnDiv={true} />, scratch);\n\t\texpect(ref.current.nodeName).to.equal('DIV');\n\n\t\trender(<App ref={ref} setRefOnDiv={false} />, scratch);\n\t\texpect(ref.current.nodeName).to.equal('SPAN');\n\t});\n\n\tit('should support rendering null', () => {\n\t\tconst App = forwardRef(() => null);\n\t\tconst ref = createRef();\n\n\t\trender(<App ref={ref} />, scratch);\n\t\texpect(ref.current == null).to.equal(true);\n\t});\n\n\tit('should support rendering null for multiple children', () => {\n\t\tconst Foo = forwardRef(() => null);\n\t\tconst ref = createRef();\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div />\n\t\t\t\t<Foo ref={ref} />\n\t\t\t\t<div />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\texpect(ref.current == null).to.equal(true);\n\t});\n\n\tit('should support useImperativeHandle', () => {\n\t\t/** @type {(v) => void} */\n\t\tlet setValue;\n\t\tconst Foo = forwardRef((props, ref) => {\n\t\t\tconst result = useState('');\n\t\t\tsetValue = result[1];\n\n\t\t\tuseImperativeHandle(\n\t\t\t\tref,\n\t\t\t\t() => ({\n\t\t\t\t\tgetValue: () => result[0]\n\t\t\t\t}),\n\t\t\t\t[result[0]]\n\t\t\t);\n\n\t\t\treturn <input ref={ref} value={result[0]} />;\n\t\t});\n\n\t\tconst ref = createRef();\n\t\trender(<Foo ref={ref} />, scratch);\n\n\t\texpect(typeof ref.current.getValue).to.equal('function');\n\t\texpect(ref.current.getValue()).to.equal('');\n\n\t\tsetValue('x');\n\t\trerender();\n\t\texpect(typeof ref.current.getValue).to.equal('function');\n\t\texpect(ref.current.getValue()).to.equal('x');\n\t});\n\n\tit('should not bailout if forwardRef is not wrapped in memo', () => {\n\t\tconst Component = props => <div {...props} />;\n\n\t\tlet renderCount = 0;\n\n\t\tconst App = forwardRef((props, ref) => {\n\t\t\trenderCount++;\n\t\t\treturn <Component {...props} forwardedRef={ref} />;\n\t\t});\n\n\t\tconst ref = createRef();\n\n\t\trender(<App ref={ref} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(1);\n\n\t\trender(<App ref={ref} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(2);\n\t});\n\n\tit('should bailout if forwardRef is wrapped in memo', () => {\n\t\tconst Component = props => <div ref={props.forwardedRef} />;\n\n\t\tlet renderCount = 0;\n\n\t\tconst App = memo(\n\t\t\tforwardRef((props, ref) => {\n\t\t\t\trenderCount++;\n\t\t\t\treturn <Component {...props} forwardedRef={ref} />;\n\t\t\t})\n\t\t);\n\n\t\tconst ref = createRef();\n\n\t\trender(<App ref={ref} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(1);\n\n\t\texpect(ref.current.nodeName).to.equal('DIV');\n\n\t\trender(<App ref={ref} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(1);\n\n\t\tconst differentRef = createRef();\n\n\t\trender(<App ref={differentRef} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(2);\n\n\t\texpect(ref.current == null).to.equal(true);\n\t\texpect(differentRef.current.nodeName).to.equal('DIV');\n\n\t\trender(<App ref={ref} optional=\"bar\" />, scratch);\n\t\texpect(renderCount).to.equal(3);\n\t});\n\n\tit('should bailout if forwardRef is wrapped in memo using function refs', () => {\n\t\tconst Component = props => <div ref={props.forwardedRef} />;\n\n\t\tlet renderCount = 0;\n\n\t\tconst App = memo(\n\t\t\tforwardRef((props, ref) => {\n\t\t\t\trenderCount++;\n\t\t\t\treturn <Component {...props} forwardedRef={ref} />;\n\t\t\t})\n\t\t);\n\n\t\tconst ref = vi.fn();\n\n\t\trender(<App ref={ref} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(1);\n\n\t\texpect(ref).toHaveBeenCalled();\n\n\t\tref.mockClear();\n\t\trender(<App ref={ref} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(1);\n\n\t\tconst differentRef = vi.fn();\n\n\t\trender(<App ref={differentRef} optional=\"foo\" />, scratch);\n\t\texpect(renderCount).to.equal(2);\n\n\t\texpect(ref).toHaveBeenCalledWith(null);\n\t\texpect(differentRef).toHaveBeenCalled();\n\n\t\tdifferentRef.mockClear();\n\t\trender(<App ref={ref} optional=\"bar\" />, scratch);\n\t\texpect(renderCount).to.equal(3);\n\t});\n\n\tit('should pass ref through memo() with custom comparer function', () => {\n\t\tconst Foo = props => <div ref={props.forwardedRef} />;\n\n\t\tlet renderCount = 0;\n\n\t\tconst App = memo(\n\t\t\tforwardRef((props, ref) => {\n\t\t\t\trenderCount++;\n\t\t\t\treturn <Foo {...props} forwardedRef={ref} />;\n\t\t\t}),\n\t\t\t(o, p) => o.a === p.a && o.b === p.b\n\t\t);\n\n\t\tconst ref = createRef();\n\n\t\trender(<App ref={ref} a=\"0\" b=\"0\" c=\"1\" />, scratch);\n\t\texpect(renderCount).to.equal(1);\n\n\t\texpect(ref.current.nodeName).to.equal('DIV');\n\n\t\t// Changing either a or b rerenders\n\t\trender(<App ref={ref} a=\"0\" b=\"1\" c=\"1\" />, scratch);\n\t\texpect(renderCount).to.equal(2);\n\n\t\t// Changing c doesn't rerender\n\t\trender(<App ref={ref} a=\"0\" b=\"1\" c=\"2\" />, scratch);\n\t\texpect(renderCount).to.equal(2);\n\n\t\tconst App2 = memo(App, (o, p) => o.a === p.a && o.c === p.c);\n\n\t\trender(<App2 ref={ref} a=\"0\" b=\"0\" c=\"0\" />, scratch);\n\t\texpect(renderCount).to.equal(3);\n\n\t\t// Changing just b no longer updates\n\t\trender(<App2 ref={ref} a=\"0\" b=\"1\" c=\"0\" />, scratch);\n\t\texpect(renderCount).to.equal(3);\n\n\t\t// Changing just a and c updates\n\t\trender(<App2 ref={ref} a=\"2\" b=\"2\" c=\"2\" />, scratch);\n\t\texpect(renderCount).to.equal(4);\n\n\t\t// Changing just c does not update\n\t\trender(<App2 ref={ref} a=\"2\" b=\"2\" c=\"3\" />, scratch);\n\t\texpect(renderCount).to.equal(4);\n\n\t\t// Changing ref still rerenders\n\t\tconst differentRef = createRef();\n\n\t\trender(<App2 ref={differentRef} a=\"2\" b=\"2\" c=\"3\" />, scratch);\n\t\texpect(renderCount).to.equal(5);\n\n\t\texpect(ref.current == null).to.equal(true);\n\t\texpect(differentRef.current.nodeName).to.equal('DIV');\n\t});\n\n\tit('calls ref when this is a function.', () => {\n\t\tconst spy = vi.fn();\n\t\tconst Bar = forwardRef((props, ref) => {\n\t\t\tuseImperativeHandle(ref, () => ({ foo: 100 }));\n\t\t\treturn null;\n\t\t});\n\n\t\trender(<Bar ref={spy} />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith({ foo: 100 });\n\t});\n\n\tit('stale ref missing with passed useRef', () => {\n\t\tlet _ref = null;\n\t\tlet _set = null;\n\t\tconst Inner = forwardRef((props, ref) => {\n\t\t\tconst _hook = useState(null);\n\t\t\t_ref = ref;\n\t\t\t_set = _hook[1];\n\t\t\treturn <div ref={ref} />;\n\t\t});\n\n\t\tconst Parent = () => {\n\t\t\tconst parentRef = useRef(null);\n\t\t\treturn <Inner ref={parentRef}>child</Inner>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<Parent />, scratch);\n\t\t});\n\n\t\texpect(_ref.current).to.equal(scratch.firstChild);\n\n\t\tact(() => {\n\t\t\t_set(1);\n\t\t\trerender();\n\t\t});\n\n\t\texpect(_ref.current).to.equal(scratch.firstChild);\n\t});\n\n\tit('should forward at diff time instead vnode-creation.', () => {\n\t\tlet ref, forceTransition, forceOpen;\n\n\t\tconst Portal = ({ children, open }) =>\n\t\t\topen ? createPortal(children, scratch) : null;\n\n\t\tconst Wrapper = forwardRef((_props, ref) => <div ref={ref}>Wrapper</div>);\n\t\tconst Transition = ({ children }) => {\n\t\t\tconst state = useState(0);\n\t\t\tforceTransition = state[1];\n\t\t\texpect(children.props.ref).to.not.be.undefined;\n\t\t\treturn children;\n\t\t};\n\n\t\tconst App = () => {\n\t\t\tconst openState = useState(false);\n\t\t\tforceOpen = openState[1];\n\t\t\tref = useRef();\n\t\t\treturn (\n\t\t\t\t<Portal open={openState[0]}>\n\t\t\t\t\t<Transition>\n\t\t\t\t\t\t<Wrapper ref={ref} />\n\t\t\t\t\t</Transition>\n\t\t\t\t</Portal>\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\n\t\tact(() => {\n\t\t\tforceOpen(true);\n\t\t});\n\n\t\texpect(ref.current.innerHTML).to.equal('Wrapper');\n\n\t\tact(() => {\n\t\t\tforceTransition(1);\n\t\t});\n\n\t\texpect(ref.current.innerHTML).to.equal('Wrapper');\n\t});\n\n\t// Issue #2566\n\tit('should pass null as ref when no ref is present', () => {\n\t\tlet actual;\n\t\tconst App = forwardRef((_, ref) => {\n\t\t\tactual = ref;\n\t\t\treturn <div />;\n\t\t});\n\n\t\trender(<App />, scratch);\n\t\texpect(actual).to.equal(null);\n\t});\n\n\t// Issue #2599\n\tit('should not crash when explicitly passing null', () => {\n\t\tlet actual;\n\t\tconst App = forwardRef((_, ref) => {\n\t\t\tactual = ref;\n\t\t\treturn <div />;\n\t\t});\n\n\t\t// eslint-disable-next-line new-cap\n\t\trender(App({}, null), scratch);\n\t\texpect(actual).to.equal(null);\n\t});\n\n\t// Issue #3483\n\tit('should allow for multiple refs', () => {\n\t\tlet actual;\n\t\tconst App = forwardRef((_, ref) => {\n\t\t\tactual = ref;\n\t\t\treturn <div />;\n\t\t});\n\n\t\tconst ref = { a: createRef(), b: createRef() };\n\t\t// eslint-disable-next-line new-cap\n\t\trender(<App ref={ref} />, scratch);\n\t\texpect(actual).to.equal(ref);\n\t});\n\n\tit('should not leak context into refs', () => {\n\t\tclass Provider extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn { foo: 2 };\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tlet actual;\n\t\tconst Forwarded = forwardRef((_, ref) => {\n\t\t\tactual = ref;\n\t\t\treturn <div />;\n\t\t});\n\n\t\trender(\n\t\t\t<Provider>\n\t\t\t\t<Forwarded />\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(actual).to.equal(null);\n\t});\n\n\t// Issue #4769\n\tit('should attach .render pointing to the original render function', () => {\n\t\tfunction Foo(props, ref) {\n\t\t\treturn <div ref={ref} />;\n\t\t}\n\n\t\tconst Forwarded = forwardRef(Foo);\n\n\t\texpect(Forwarded.render).to.equal(Foo);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/hooks.test.jsx",
    "content": "import { createContext } from 'preact';\nimport {\n\tcreateElement,\n\tuseDeferredValue,\n\tuseInsertionEffect,\n\tuseTransition,\n\trender,\n\tuseState,\n\tuseContext,\n\tuseEffect\n} from 'preact/compat';\nimport { setupRerender, act } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('React-18-hooks', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('useDeferredValue', () => {\n\t\tit('returns the value', () => {\n\t\t\tconst App = props => {\n\t\t\t\tconst val = useDeferredValue(props.text);\n\t\t\t\treturn <p>{val}</p>;\n\t\t\t};\n\n\t\t\trender(<App text=\"hello world\" />, scratch);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<p>hello world</p>');\n\t\t});\n\t});\n\n\tdescribe('useInsertionEffect', () => {\n\t\tit('runs the effect', () => {\n\t\t\tconst spy = vi.fn();\n\t\t\tconst App = () => {\n\t\t\t\tuseInsertionEffect(spy, []);\n\t\t\t\treturn <p>hello world</p>;\n\t\t\t};\n\n\t\t\tact(() => {\n\t\t\t\trender(<App />, scratch);\n\t\t\t});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<p>hello world</p>');\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\t});\n\n\tdescribe('useTransition', () => {\n\t\tit('runs transitions', () => {\n\t\t\tconst spy = vi.fn();\n\n\t\t\t/** @type {(v) => void} */\n\t\t\tlet go;\n\t\t\tconst App = () => {\n\t\t\t\tconst [isPending, start] = useTransition();\n\t\t\t\tgo = start;\n\t\t\t\treturn <p>Pending: {isPending ? 'yes' : 'no'}</p>;\n\t\t\t};\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<p>Pending: no</p>');\n\n\t\t\tgo(spy);\n\t\t\trerender();\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(scratch.innerHTML).to.equal('<p>Pending: no</p>');\n\t\t});\n\t});\n\n\tit('should release the force-flag on context-consumers', () => {\n\t\tlet sequence, setSubmitting;\n\t\tconst Ctx = createContext({\n\t\t\tisSubmitting: false,\n\t\t\tsetIsSubmitting: () => {}\n\t\t});\n\t\tconst FormWrapper = props => {\n\t\t\tconst [isSubmitting, setIsSubmitting] = useState(false);\n\t\t\tsetSubmitting = setIsSubmitting;\n\t\t\treturn (\n\t\t\t\t<Ctx.Provider value={{ isSubmitting, setIsSubmitting }}>\n\t\t\t\t\t{props.children}\n\t\t\t\t</Ctx.Provider>\n\t\t\t);\n\t\t};\n\n\t\tconst Form = () => {\n\t\t\tconst { isSubmitting, setIsSubmitting } = useContext(Ctx);\n\t\t\tconst [shouldSubmit, setShouldSubmit] = useState(false);\n\n\t\t\tsequence = () => {\n\t\t\t\tsetShouldSubmit(true);\n\t\t\t};\n\n\t\t\tconst submit = () => {\n\t\t\t\tsetIsSubmitting(true);\n\t\t\t\tsetShouldSubmit(false);\n\t\t\t};\n\n\t\t\tuseEffect(() => {\n\t\t\t\tif (shouldSubmit) {\n\t\t\t\t\tsubmit();\n\t\t\t\t}\n\t\t\t}, [shouldSubmit]);\n\n\t\t\treturn (\n\t\t\t\t<p>\n\t\t\t\t\tisSubmitting: {'' + isSubmitting} | shouldSubmit: {'' + shouldSubmit}\n\t\t\t\t</p>\n\t\t\t);\n\t\t};\n\n\t\tconst App = () => {\n\t\t\treturn (\n\t\t\t\t<FormWrapper>\n\t\t\t\t\t<Form />\n\t\t\t\t</FormWrapper>\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\n\t\tact(() => {\n\t\t\tsequence();\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<p>isSubmitting: true | shouldSubmit: false</p>'\n\t\t);\n\n\t\tact(() => {\n\t\t\tsetSubmitting(false);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<p>isSubmitting: false | shouldSubmit: false</p>'\n\t\t);\n\n\t\tact(() => {\n\t\t\tsequence();\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<p>isSubmitting: true | shouldSubmit: false</p>'\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/hydrate.test.jsx",
    "content": "import { createElement, hydrate } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('compat hydrate', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should render react-style jsx', () => {\n\t\tconst input = document.createElement('input');\n\t\tscratch.appendChild(input);\n\t\tinput.focus();\n\t\texpect(document.activeElement).to.equalNode(input);\n\n\t\thydrate(<input />, scratch);\n\t\texpect(document.activeElement).to.equalNode(input);\n\t});\n\n\tit('should call the callback', () => {\n\t\tscratch.innerHTML = '<div></div>';\n\n\t\tlet spy = vi.fn();\n\t\thydrate(<div />, scratch, spy);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith();\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/isFragment.test.js",
    "content": "import { createElement as preactCreateElement, Fragment } from 'preact';\nimport React, { isFragment } from 'preact/compat';\n\ndescribe('isFragment', () => {\n\tit('should check return false for invalid arguments', () => {\n\t\texpect(isFragment(null)).to.equal(false);\n\t\texpect(isFragment(false)).to.equal(false);\n\t\texpect(isFragment(true)).to.equal(false);\n\t\texpect(isFragment('foo')).to.equal(false);\n\t\texpect(isFragment(123)).to.equal(false);\n\t\texpect(isFragment([])).to.equal(false);\n\t\texpect(isFragment({})).to.equal(false);\n\t});\n\n\tit('should detect a preact vnode', () => {\n\t\texpect(isFragment(preactCreateElement(Fragment, {}))).to.equal(true);\n\t});\n\n\tit('should detect a compat vnode', () => {\n\t\texpect(isFragment(React.createElement(Fragment, {}))).to.equal(true);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/isMemo.test.jsx",
    "content": "import { createElement as preactCreateElement, Fragment } from 'preact';\nimport React, { createElement, isMemo, memo } from 'preact/compat';\n\ndescribe('isMemo', () => {\n\tit('should check return false for invalid arguments', () => {\n\t\texpect(isMemo(null)).to.equal(false);\n\t\texpect(isMemo(false)).to.equal(false);\n\t\texpect(isMemo(true)).to.equal(false);\n\t\texpect(isMemo('foo')).to.equal(false);\n\t\texpect(isMemo(123)).to.equal(false);\n\t\texpect(isMemo([])).to.equal(false);\n\t\texpect(isMemo({})).to.equal(false);\n\t});\n\n\tit('should detect a preact memo', () => {\n\t\tfunction Foo() {\n\t\t\treturn <h1>Hello World</h1>;\n\t\t}\n\t\tlet App = memo(Foo);\n\t\texpect(isMemo(App)).to.equal(true);\n\t});\n\n\tit('should not detect a normal element', () => {\n\t\tfunction Foo() {\n\t\t\treturn <h1>Hello World</h1>;\n\t\t}\n\t\texpect(isMemo(Foo)).to.equal(false);\n\t});\n\n\tit('should detect a preact vnode as false', () => {\n\t\texpect(isMemo(preactCreateElement(Fragment, {}))).to.equal(false);\n\t});\n\n\tit('should detect a compat vnode as false', () => {\n\t\texpect(isMemo(React.createElement(Fragment, {}))).to.equal(false);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/isValidElement.test.js",
    "content": "import { createElement as preactCreateElement } from 'preact';\nimport React, { isValidElement } from 'preact/compat';\n\ndescribe('isValidElement', () => {\n\tit('should check return false for invalid arguments', () => {\n\t\texpect(isValidElement(null)).to.equal(false);\n\t\texpect(isValidElement(false)).to.equal(false);\n\t\texpect(isValidElement(true)).to.equal(false);\n\t\texpect(isValidElement('foo')).to.equal(false);\n\t\texpect(isValidElement(123)).to.equal(false);\n\t\texpect(isValidElement([])).to.equal(false);\n\t\texpect(isValidElement({})).to.equal(false);\n\t});\n\n\tit('should detect a preact vnode', () => {\n\t\texpect(isValidElement(preactCreateElement('div', {}))).to.equal(true);\n\t});\n\n\tit('should detect a compat vnode', () => {\n\t\texpect(isValidElement(React.createElement('div', {}))).to.equal(true);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/memo.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport {\n\tcreateEvent,\n\tsetupScratch,\n\tteardown\n} from '../../../test/_util/helpers';\nimport React, {\n\tcreateElement,\n\tComponent,\n\trender,\n\tmemo,\n\tuseState\n} from 'preact/compat';\nimport { vi, expect } from 'vitest';\n\nconst h = React.createElement;\n\ndescribe('memo()', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should have isReactComponent flag', () => {\n\t\t// eslint-disable-next-line react/display-name\n\t\tlet App = memo(() => <div>foo</div>);\n\t\texpect(App.prototype.isReactComponent).to.equal(true);\n\t});\n\n\tit('should work with function components', () => {\n\t\tlet spy = vi.fn();\n\n\t\tfunction Foo() {\n\t\t\tspy();\n\t\t\treturn <h1>Hello World</h1>;\n\t\t}\n\n\t\tlet Memoized = memo(Foo);\n\n\t\t/** @type {() => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tupdate = () => this.setState({});\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <Memoized />;\n\t\t\t}\n\t\t}\n\t\trender(<App />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should support adding refs', () => {\n\t\tlet spy = vi.fn();\n\n\t\tlet ref = null;\n\n\t\tfunction Foo(props) {\n\t\t\tspy();\n\t\t\treturn <h1 ref={props.ref}>Hello World</h1>;\n\t\t}\n\n\t\tlet Memoized = memo(Foo);\n\n\t\t/** @type {(v) => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tupdate = () => this.setState({});\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <Memoized ref={ref} />;\n\t\t\t}\n\t\t}\n\t\trender(<App />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\n\t\tref = {};\n\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(ref.current).to.equal(scratch.firstChild);\n\t\t// TODO: not sure whether this is in-line with react...\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('should support custom comparer functions', () => {\n\t\tfunction Foo() {\n\t\t\treturn <h1>Hello World</h1>;\n\t\t}\n\n\t\tlet spy = vi.fn(() => true);\n\t\tlet Memoized = memo(Foo, spy);\n\n\t\t/** @type {(v) => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tupdate = () => this.setState({});\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <Memoized />;\n\t\t\t}\n\t\t}\n\t\trender(<App />, scratch);\n\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith({}, {});\n\t});\n\n\tit('should rerender when custom comparer returns false', () => {\n\t\tconst spy = vi.fn();\n\t\tfunction Foo() {\n\t\t\tspy();\n\t\t\treturn <h1>Hello World</h1>;\n\t\t}\n\n\t\tconst App = memo(Foo, () => false);\n\t\trender(<App />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\n\t\trender(<App foo=\"bar\" />, scratch);\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('should pass props and nextProps to comparer fn', () => {\n\t\tconst spy = vi.fn(() => false);\n\t\tfunction Foo() {\n\t\t\treturn <div>foo</div>;\n\t\t}\n\n\t\tconst props = { foo: true };\n\t\tconst nextProps = { foo: false };\n\t\tconst App = memo(Foo, spy);\n\t\trender(h(App, props), scratch);\n\t\trender(h(App, nextProps), scratch);\n\n\t\texpect(spy).toHaveBeenCalledWith(props, nextProps);\n\t});\n\n\tit('should nest without errors', () => {\n\t\tconst Foo = () => <div>foo</div>;\n\t\tconst App = memo(memo(Foo));\n\n\t\t// eslint-disable-next-line prefer-arrow-callback\n\t\texpect(function () {\n\t\t\trender(<App />, scratch);\n\t\t}).to.not.throw();\n\t});\n\n\tit('should pass ref through nested memos', () => {\n\t\tconst Foo = props => <h1 ref={props.ref}>Hello World</h1>;\n\n\t\tconst App = memo(memo(Foo));\n\n\t\tconst ref = {};\n\n\t\trender(<App ref={ref} />, scratch);\n\n\t\texpect(ref.current).not.to.be.undefined;\n\t\texpect(ref.current).to.equal(scratch.firstChild);\n\t});\n\n\tit('should not unnecessarily reorder children #2895', () => {\n\t\tconst array = [{ name: 'A' }, { name: 'B' }, { name: 'C' }, { name: 'D' }];\n\n\t\tconst List = () => {\n\t\t\tconst [selected, setSelected] = useState('');\n\t\t\treturn (\n\t\t\t\t<ol>\n\t\t\t\t\t{array.map(item => (\n\t\t\t\t\t\t<ListItem\n\t\t\t\t\t\t\t{...{\n\t\t\t\t\t\t\t\tisSelected: item.name === selected,\n\t\t\t\t\t\t\t\tsetSelected,\n\t\t\t\t\t\t\t\t...item\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tkey={item.name}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ol>\n\t\t\t);\n\t\t};\n\n\t\tconst ListItem = memo(({ name, isSelected, setSelected }) => {\n\t\t\tconst handleClick = () => setSelected(name);\n\t\t\treturn (\n\t\t\t\t<li class={isSelected ? 'selected' : null} onClick={handleClick}>\n\t\t\t\t\t{name}\n\t\t\t\t</li>\n\t\t\t);\n\t\t});\n\n\t\trender(<List />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<ol><li>A</li><li>B</li><li>C</li><li>D</li></ol>`\n\t\t);\n\n\t\tlet listItem = scratch.querySelector('li:nth-child(3)');\n\t\tlistItem.dispatchEvent(createEvent('click'));\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<ol><li>A</li><li>B</li><li class=\"selected\">C</li><li>D</li></ol>`\n\t\t);\n\t});\n\n\tit('should attach .type pointing to the original component', () => {\n\t\tfunction Foo() {\n\t\t\treturn <div />;\n\t\t}\n\t\tconst Memoized = memo(Foo);\n\n\t\texpect(Memoized.type).to.equal(Foo);\n\t});\n\n\tit('should recover and render siblings when memo child throws once', () => {\n\t\tlet causeError = true;\n\n\t\tconst TestWithMemo = /** @type {any} */ (memo(\n\t\t\t/** @type {(props: { n: number }) => any} */ (props => {\n\t\t\t\tconst { n } = props;\n\t\t\t\tif (n === 2 && causeError) {\n\t\t\t\t\tthrow new Error('test error');\n\t\t\t\t}\n\t\t\t\treturn <p>test {n}</p>;\n\t\t\t})\n\t\t));\n\n\t\tclass App extends Component {\n\t\t\tstatic getDerivedStateFromError() {\n\t\t\t\tcauseError = false;\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h1>Example</h1>\n\t\t\t\t\t\t<TestWithMemo n={1} />\n\t\t\t\t\t\t<TestWithMemo n={2} />\n\t\t\t\t\t\t<TestWithMemo n={3} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\trerender();\n\n\t\texpect(scratch.textContent).to.equal('Exampletest 1test 2test 3');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/portals.test.jsx",
    "content": "import React, {\n\tcreateElement,\n\trender,\n\tcreatePortal,\n\tuseState,\n\tComponent,\n\tuseEffect,\n\tFragment,\n\tuseId\n} from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { setupRerender, act } from 'preact/test-utils';\nimport { expect } from 'chai';\nimport { vi } from 'vitest';\n\n/* eslint-disable react/jsx-boolean-value, react/display-name, prefer-arrow-callback */\n\ndescribe('Portal', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\t/** @type {HTMLDivElement} */\n\tlet scratch2;\n\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\tscratch2 = setupScratch('scratch-2');\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tteardown(scratch2);\n\t});\n\n\tit('should render into a different root node', () => {\n\t\tlet root = document.createElement('div');\n\t\tdocument.body.appendChild(root);\n\n\t\tfunction Foo(props) {\n\t\t\treturn <div>{createPortal(props.children, root)}</div>;\n\t\t}\n\t\trender(<Foo>foobar</Foo>, scratch);\n\n\t\texpect(root.innerHTML).to.equal('foobar');\n\n\t\troot.parentNode.removeChild(root);\n\t});\n\n\tit('should insert the portal', () => {\n\t\t/** @type {() => void} */\n\t\tlet setFalse;\n\t\tfunction Foo(props) {\n\t\t\tconst [mounted, setMounted] = useState(true);\n\t\t\tsetFalse = () => setMounted(() => false);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{mounted && createPortal(props.children, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t\trender(<Foo>foobar</Foo>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('foobar<div><p>Hello</p></div>');\n\n\t\tsetFalse();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\t});\n\n\tit('should order portal children well', () => {\n\t\t/** @type {() => void} */\n\t\tlet bump;\n\n\t\tfunction Modal() {\n\t\t\tconst [state, setState] = useState(0);\n\t\t\tbump = () => setState(() => 1);\n\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t{state === 1 && <div>top</div>}\n\t\t\t\t\t<div>middle</div>\n\t\t\t\t\t<div>bottom</div>\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tfunction Foo(props) {\n\t\t\treturn createPortal(<Modal />, scratch);\n\t\t}\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>middle</div><div>bottom</div>');\n\n\t\tbump();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>top</div><div>middle</div><div>bottom</div>'\n\t\t);\n\t});\n\n\tit('should toggle the portal', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [mounted, setMounted] = useState(true);\n\t\t\ttoggle = () => setMounted(s => !s);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{mounted && createPortal(props.children, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<div>foobar</div>\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>foobar</div><div><p>Hello</p></div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\t});\n\n\tit('should notice prop changes on the portal', () => {\n\t\t/** @type {(c) => void} */\n\t\tlet set;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [additionalProps, setProps] = useState({\n\t\t\t\tstyle: { backgroundColor: 'red' }\n\t\t\t});\n\t\t\tset = c => setProps(c);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{createPortal(<p {...additionalProps}>Foo</p>, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.firstChild.style.backgroundColor).to.equal('red');\n\n\t\tset({});\n\t\trerender();\n\t\texpect(scratch.firstChild.style.backgroundColor).to.equal('');\n\t});\n\n\tit('should not unmount the portal component', () => {\n\t\tlet spy = vi.fn();\n\t\t/** @type {(c) => void} */\n\t\tlet set;\n\t\tclass Child extends Component {\n\t\t\tcomponentWillUnmount() {\n\t\t\t\tspy();\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn props.children;\n\t\t\t}\n\t\t}\n\n\t\tfunction Foo(props) {\n\t\t\tconst [additionalProps, setProps] = useState({\n\t\t\t\tstyle: { background: 'red' }\n\t\t\t});\n\t\t\tset = c => setProps(c);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{createPortal(<Child {...additionalProps}>Foo</Child>, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(spy).not.toHaveBeenCalled();\n\n\t\tset({});\n\t\trerender();\n\t\texpect(spy).not.toHaveBeenCalled();\n\t});\n\n\tit('should not render <undefined> for Portal nodes', () => {\n\t\tlet root = document.createElement('div');\n\t\tlet dialog = document.createElement('div');\n\t\tdialog.id = 'container';\n\n\t\tscratch.appendChild(root);\n\t\tscratch.appendChild(dialog);\n\n\t\tfunction Dialog() {\n\t\t\treturn <div>Dialog content</div>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn <div>{createPortal(<Dialog />, dialog)}</div>;\n\t\t}\n\n\t\trender(<App />, root);\n\t\texpect(scratch.firstChild.firstChild.childNodes.length).to.equal(0);\n\t});\n\n\tit('should have unique ids for each portal', () => {\n\t\tlet root = document.createElement('div');\n\t\tlet dialog = document.createElement('div');\n\t\tdialog.id = 'container';\n\n\t\tscratch.appendChild(root);\n\t\tscratch.appendChild(dialog);\n\n\t\tfunction Id() {\n\t\t\tconst id = useId();\n\t\t\treturn id;\n\t\t}\n\n\t\tfunction Dialog() {\n\t\t\treturn <Id />;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Id />\n\t\t\t\t\t{createPortal(<Dialog />, dialog)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, root);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>P0-0</div></div><div id=\"container\">P0-1</div>'\n\t\t);\n\t});\n\n\tit('should have unique ids for each portal, even when a new one shows up', () => {\n\t\tlet root = document.createElement('div');\n\t\tlet dialog = document.createElement('div');\n\t\tdialog.id = 'container';\n\n\t\tscratch.appendChild(root);\n\t\tscratch.appendChild(dialog);\n\n\t\tfunction Id() {\n\t\t\tconst id = useId();\n\t\t\treturn id;\n\t\t}\n\n\t\tfunction Dialog(props) {\n\t\t\treturn <Id />;\n\t\t}\n\n\t\tfunction App(props) {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Id />\n\t\t\t\t\t{createPortal(<Dialog />, dialog)}\n\t\t\t\t\t{props.renderPortal && createPortal(<Dialog />, dialog)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, root);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>P0-0</div></div><div id=\"container\">P0-1</div>'\n\t\t);\n\n\t\trender(<App renderPortal={true} />, root);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>P0-0</div></div><div id=\"container\">P0-1P0-2</div>'\n\t\t);\n\t});\n\n\tit('should unmount Portal', () => {\n\t\tlet root = document.createElement('div');\n\t\tlet dialog = document.createElement('div');\n\t\tdialog.id = 'container';\n\n\t\tscratch.appendChild(root);\n\t\tscratch.appendChild(dialog);\n\n\t\tfunction Dialog() {\n\t\t\treturn <div>Dialog content</div>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn <div>{createPortal(<Dialog />, dialog)}</div>;\n\t\t}\n\n\t\trender(<App />, root);\n\t\texpect(dialog.childNodes.length).to.equal(1);\n\t\trender(null, root);\n\t\texpect(dialog.childNodes.length).to.equal(0);\n\t});\n\n\tit('should leave a working root after the portal', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle,\n\t\t\t/** @type {() => void} */\n\t\t\ttoggle2;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [mounted, setMounted] = useState(false);\n\t\t\tconst [mounted2, setMounted2] = useState(true);\n\t\t\ttoggle = () => setMounted(s => !s);\n\t\t\ttoggle2 = () => setMounted2(s => !s);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t{mounted && createPortal(props.children, scratch)}\n\t\t\t\t\t{mounted2 && <p>Hello</p>}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<div>foobar</div>\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div></div><div>foobar</div>');\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('should work with stacking portals', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle,\n\t\t\t/** @type {() => void} */\n\t\t\ttoggle2;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [mounted, setMounted] = useState(false);\n\t\t\tconst [mounted2, setMounted2] = useState(false);\n\t\t\ttoggle = () => setMounted(s => !s);\n\t\t\ttoggle2 = () => setMounted2(s => !s);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{mounted && createPortal(props.children, scratch)}\n\t\t\t\t\t{mounted2 && createPortal(props.children2, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(\n\t\t\t<Foo children2={<div>foobar2</div>}>\n\t\t\t\t<div>foobar</div>\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div><div>foobar2</div>'\n\t\t);\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\t});\n\n\tit('should work with changing the container', () => {\n\t\t/** @type {(c) => void} */\n\t\tlet set, ref;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [container, setContainer] = useState(scratch);\n\t\t\tset = setContainer;\n\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tref={r => {\n\t\t\t\t\t\tref = r;\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{createPortal(props.children, container)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<div>foobar</div>\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>foobar</div><div><p>Hello</p></div>'\n\t\t);\n\n\t\tset(() => ref);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p><div>foobar</div></div>'\n\t\t);\n\t});\n\n\tit('should work with replacing placeholder portals', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle,\n\t\t\t/** @type {() => void} */\n\t\t\ttoggle2;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [mounted, setMounted] = useState(false);\n\t\t\tconst [mounted2, setMounted2] = useState(false);\n\t\t\ttoggle = () => setMounted(s => !s);\n\t\t\ttoggle2 = () => setMounted2(s => !s);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{createPortal(mounted && props.children, scratch)}\n\t\t\t\t\t{createPortal(mounted2 && props.children, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<div>foobar</div>\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div>foobar</div>'\n\t\t);\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\t});\n\n\tit('should work with removing an element from stacked container to new one', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle, root2;\n\n\t\tfunction Foo(props) {\n\t\t\tconst [root, setRoot] = useState(scratch);\n\t\t\ttoggle = () => setRoot(() => root2);\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tref={r => {\n\t\t\t\t\t\troot2 = r;\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{createPortal(props.children, scratch)}\n\t\t\t\t\t{createPortal(props.children, root)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<div>foobar</div>\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>foobar</div><div>foobar</div><div><p>Hello</p></div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>foobar</div><div><p>Hello</p><div>foobar</div></div>'\n\t\t);\n\t});\n\n\tit('should support nested portals', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle,\n\t\t\t/** @type {() => void} */\n\t\t\ttoggle2,\n\t\t\tinner;\n\n\t\tfunction Bar() {\n\t\t\tconst [mounted, setMounted] = useState(false);\n\t\t\ttoggle2 = () => setMounted(s => !s);\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tref={r => {\n\t\t\t\t\t\tinner = r;\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<p>Inner</p>\n\t\t\t\t\t{mounted && createPortal(<p>hiFromBar</p>, scratch)}\n\t\t\t\t\t{mounted && createPortal(<p>innerPortal</p>, inner)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction Foo(props) {\n\t\t\tconst [mounted, setMounted] = useState(false);\n\t\t\ttoggle = () => setMounted(s => !s);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t{mounted && createPortal(<Bar />, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div><p>Inner</p></div>'\n\t\t);\n\n\t\ttoggle2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><p>Hello</p></div><div><p>Inner</p><p>innerPortal</p></div><p>hiFromBar</p>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><p>Hello</p></div>');\n\t});\n\n\tit('should support nested portals remounting #2669', () => {\n\t\tlet setVisible;\n\t\tlet i = 0;\n\n\t\tfunction PortalComponent(props) {\n\t\t\tconst innerVnode = <div id=\"inner\">{i}</div>;\n\t\t\tinnerVnode.___id = 'inner_' + i++;\n\t\t\tconst outerVnode = (\n\t\t\t\t<div id=\"outer\">\n\t\t\t\t\t{i}\n\t\t\t\t\t{props.show && createPortal(innerVnode, scratch)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t\touterVnode.___id = 'outer_' + i++;\n\t\t\treturn createPortal(outerVnode, scratch);\n\t\t}\n\n\t\tfunction App() {\n\t\t\tconst [visible, _setVisible] = useState(true);\n\t\t\tsetVisible = _setVisible;\n\n\t\t\treturn (\n\t\t\t\t<div id=\"app\">\n\t\t\t\t\ttest\n\t\t\t\t\t<PortalComponent show={visible} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"inner\">0</div><div id=\"outer\">1</div><div id=\"app\">test</div>'\n\t\t);\n\n\t\tact(() => {\n\t\t\tsetVisible(false);\n\t\t});\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"outer\">3</div><div id=\"app\">test</div>'\n\t\t);\n\n\t\tact(() => {\n\t\t\tsetVisible(true);\n\t\t});\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"outer\">5</div><div id=\"app\">test</div><div id=\"inner\">4</div>'\n\t\t);\n\n\t\tact(() => {\n\t\t\tsetVisible(false);\n\t\t});\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"outer\">7</div><div id=\"app\">test</div>'\n\t\t);\n\t});\n\n\tit('should not unmount when parent renders', () => {\n\t\tlet root = document.createElement('div');\n\t\tlet dialog = document.createElement('div');\n\t\tdialog.id = 'container';\n\n\t\tscratch.appendChild(root);\n\t\tscratch.appendChild(dialog);\n\n\t\tlet spy = vi.fn();\n\t\tclass Child extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tspy();\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <div id=\"child\">child</div>;\n\t\t\t}\n\t\t}\n\n\t\tlet spyParent = vi.fn();\n\t\tclass App extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tspyParent();\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>{createPortal(<Child />, dialog)}</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, root);\n\t\tlet dom = document.getElementById('child');\n\t\texpect(spyParent).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledOnce();\n\n\t\t// Render twice to trigger update scenario\n\t\trender(<App />, root);\n\t\trender(<App />, root);\n\n\t\tlet domNew = document.getElementById('child');\n\t\texpect(dom).to.equal(domNew);\n\t\texpect(spyParent).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should switch between non portal and portal node (Modal as lastChild)', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\t\tconst Modal = ({ children, open }) =>\n\t\t\topen ? createPortal(<div>{children}</div>, scratch) : <div>Closed</div>;\n\n\t\tconst App = () => {\n\t\t\tconst [open, setOpen] = useState(false);\n\t\t\ttoggle = setOpen.bind(this, x => !x);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<button onClick={() => setOpen(!open)}>Show</button>\n\t\t\t\t\t{open ? 'Open' : 'Closed'}\n\t\t\t\t\t<Modal open={open}>Hello</Modal>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><button>Show</button>Closed<div>Closed</div></div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><button>Show</button>Open</div><div>Hello</div>'\n\t\t);\n\t});\n\n\tit('should switch between non portal and portal node (Modal as firstChild)', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\t\tconst Modal = ({ children, open }) =>\n\t\t\topen ? createPortal(<div>{children}</div>, scratch) : <div>Closed</div>;\n\n\t\tconst App = () => {\n\t\t\tconst [open, setOpen] = useState(false);\n\t\t\ttoggle = setOpen.bind(this, x => !x);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Modal open={open}>Hello</Modal>\n\t\t\t\t\t<button onClick={() => setOpen(!open)}>Show</button>\n\t\t\t\t\t{open ? 'Open' : 'Closed'}\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Closed</div><button>Show</button>Closed</div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><button>Show</button>Open</div><div>Hello</div>'\n\t\t);\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Closed</div><button>Show</button>Closed</div>'\n\t\t);\n\t});\n\n\tit('should order effects well', () => {\n\t\tconst calls = [];\n\t\tconst Modal = ({ children }) => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('Modal');\n\t\t\t}, []);\n\t\t\treturn createPortal(<div className=\"modal\">{children}</div>, scratch);\n\t\t};\n\n\t\tconst ModalButton = ({ i }) => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push(`Button ${i}`);\n\t\t\t}, []);\n\n\t\t\treturn <button>Action</button>;\n\t\t};\n\n\t\tconst App = () => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('App');\n\t\t\t}, []);\n\n\t\t\treturn (\n\t\t\t\t<Modal>\n\t\t\t\t\t<ModalButton i=\"1\" />\n\t\t\t\t\t<ModalButton i=\"2\" />\n\t\t\t\t</Modal>\n\t\t\t);\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(calls).to.deep.equal(['Button 1', 'Button 2', 'Modal', 'App']);\n\t});\n\n\tit('should include containerInfo', () => {\n\t\tlet root = document.createElement('div');\n\t\tdocument.body.appendChild(root);\n\n\t\tconst A = () => <span>A</span>;\n\n\t\tlet portal;\n\t\tfunction Foo(props) {\n\t\t\tportal = createPortal(props.children, root);\n\t\t\treturn <div>{portal}</div>;\n\t\t}\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<A />\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(portal.containerInfo).to.equal(root);\n\n\t\troot.parentNode.removeChild(root);\n\t});\n\n\tit('should order complex effects well', () => {\n\t\tconst calls = [];\n\t\tconst Parent = ({ children, isPortal }) => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push(`${isPortal ? 'Portal ' : ''}Parent`);\n\t\t\t}, [isPortal]);\n\n\t\t\treturn <div>{children}</div>;\n\t\t};\n\n\t\tconst Child = ({ index, isPortal }) => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push(`${isPortal ? 'Portal ' : ''}Child ${index}`);\n\t\t\t}, [index, isPortal]);\n\n\t\t\treturn <div>{index}</div>;\n\t\t};\n\n\t\tconst Portal = () => {\n\t\t\tconst content = [1, 2, 3].map(index => (\n\t\t\t\t<Child key={index} index={index} isPortal />\n\t\t\t));\n\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('Portal');\n\t\t\t}, []);\n\n\t\t\treturn createPortal(<Parent isPortal>{content}</Parent>, scratch2);\n\t\t};\n\n\t\tconst App = () => {\n\t\t\tconst content = [1, 2, 3].map(index => (\n\t\t\t\t<Child key={index} index={index} />\n\t\t\t));\n\n\t\t\treturn (\n\t\t\t\t<React.Fragment>\n\t\t\t\t\t<Parent>{content}</Parent>\n\t\t\t\t\t<Portal />\n\t\t\t\t</React.Fragment>\n\t\t\t);\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(calls).to.deep.equal([\n\t\t\t'Child 1',\n\t\t\t'Child 2',\n\t\t\t'Child 3',\n\t\t\t'Parent',\n\t\t\t'Portal Child 1',\n\t\t\t'Portal Child 2',\n\t\t\t'Portal Child 3',\n\t\t\t'Portal Parent',\n\t\t\t'Portal'\n\t\t]);\n\t});\n\n\t// #4992\n\tit('should maintain SVG namespace when rendering through a portal', () => {\n\t\tconst svgRoot = document.createElementNS(\n\t\t\t'http://www.w3.org/2000/svg',\n\t\t\t'svg'\n\t\t);\n\t\tdocument.body.appendChild(svgRoot);\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<svg>\n\t\t\t\t\t<g>\n\t\t\t\t\t\t<rect width=\"100\" height=\"100\" fill=\"red\" />\n\t\t\t\t\t\t{createPortal(\n\t\t\t\t\t\t\t<g id=\"test-portal\">\n\t\t\t\t\t\t\t\t<rect width=\"50\" height=\"50\" fill=\"blue\" />\n\t\t\t\t\t\t\t</g>,\n\t\t\t\t\t\t\tsvgRoot\n\t\t\t\t\t\t)}\n\t\t\t\t\t</g>\n\t\t\t\t</svg>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tconst portalG = svgRoot.querySelector('g#test-portal');\n\t\texpect(portalG.namespaceURI).to.equal('http://www.w3.org/2000/svg');\n\t\texpect(portalG.constructor.name).to.equal('SVGGElement');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/render.test.jsx",
    "content": "import React, {\n\tcreateElement,\n\trender,\n\tComponent,\n\thydrate,\n\tcreateContext\n} from 'preact/compat';\nimport { setupRerender, act } from 'preact/test-utils';\nimport {\n\tsetupScratch,\n\tteardown,\n\tserializeHtml,\n\tcreateEvent,\n\tsortAttributes\n} from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('compat render', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tconst ce = type => document.createElement(type);\n\tconst text = text => document.createTextNode(text);\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should render react-style jsx', () => {\n\t\tlet jsx = (\n\t\t\t<div className=\"foo bar\" data-foo=\"bar\">\n\t\t\t\t<span id=\"some_id\">inner!</span>\n\t\t\t\t{['a', 'b']}\n\t\t\t</div>\n\t\t);\n\n\t\texpect(jsx.props).to.have.property('className', 'foo bar');\n\n\t\tReact.render(jsx, scratch);\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\t'<div class=\"foo bar\" data-foo=\"bar\"><span id=\"some_id\">inner!</span>ab</div>'\n\t\t);\n\t});\n\n\tit('should replace isomorphic content', () => {\n\t\tlet root = ce('div');\n\t\tlet initialChild = ce('div');\n\t\tinitialChild.appendChild(text('initial content'));\n\t\troot.appendChild(initialChild);\n\n\t\trender(<div>dynamic content</div>, root);\n\t\texpect(root)\n\t\t\t.to.have.property('textContent')\n\t\t\t.that.is.a('string')\n\t\t\t.that.equals('dynamic content');\n\t});\n\n\tit('should remove extra elements', () => {\n\t\tlet root = ce('div');\n\t\tlet inner = ce('div');\n\n\t\troot.appendChild(inner);\n\n\t\tlet c1 = ce('div');\n\t\tc1.appendChild(text('isomorphic content'));\n\t\tinner.appendChild(c1);\n\n\t\tlet c2 = ce('div');\n\t\tc2.appendChild(text('extra content'));\n\t\tinner.appendChild(c2);\n\n\t\trender(<div>dynamic content</div>, root);\n\t\texpect(root)\n\t\t\t.to.have.property('textContent')\n\t\t\t.that.is.a('string')\n\t\t\t.that.equals('dynamic content');\n\t});\n\n\t// Note: Replacing text nodes inside the root itself is currently unsupported.\n\t// We do replace them everywhere else, though.\n\tit('should remove text nodes', () => {\n\t\tlet root = ce('div');\n\n\t\tlet div = ce('div');\n\t\troot.appendChild(div);\n\t\tdiv.appendChild(text('Text Content'));\n\t\tdiv.appendChild(text('More Text Content'));\n\n\t\trender(<div>dynamic content</div>, root);\n\t\texpect(root)\n\t\t\t.to.have.property('textContent')\n\t\t\t.that.is.a('string')\n\t\t\t.that.equals('dynamic content');\n\t});\n\n\tit('should ignore maxLength / minLength when is null', () => {\n\t\trender(<input maxLength={null} minLength={null} />, scratch);\n\t\texpect(scratch.firstElementChild.getAttribute('maxlength')).to.equal(null);\n\t\texpect(scratch.firstElementChild.getAttribute('minlength')).to.equal(null);\n\t});\n\n\tit('should support defaultValue', () => {\n\t\trender(<input defaultValue=\"foo\" />, scratch);\n\t\texpect(scratch.firstElementChild).to.have.property('value', 'foo');\n\t});\n\n\tit('should add defaultValue when value is null/undefined', () => {\n\t\trender(<input defaultValue=\"foo\" value={null} />, scratch);\n\t\texpect(scratch.firstElementChild).to.have.property('value', 'foo');\n\n\t\trender(<input defaultValue=\"foo\" value={undefined} />, scratch);\n\t\texpect(scratch.firstElementChild).to.have.property('value', 'foo');\n\t});\n\n\tit('should support defaultValue for select tag', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<select defaultValue=\"2\">\n\t\t\t\t\t<option value=\"1\">Picked 1</option>\n\t\t\t\t\t<option value=\"2\">Picked 2</option>\n\t\t\t\t\t<option value=\"3\">Picked 3</option>\n\t\t\t\t</select>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tconst options = scratch.firstChild.children;\n\t\texpect(options[0]).to.have.property('selected', false);\n\t\texpect(options[1]).to.have.property('selected', true);\n\t});\n\n\tit('should support defaultValue for select tag when using multi selection', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<select multiple defaultValue={['1', '3']}>\n\t\t\t\t\t<option value=\"1\">Picked 1</option>\n\t\t\t\t\t<option value=\"2\">Picked 2</option>\n\t\t\t\t\t<option value=\"3\">Picked 3</option>\n\t\t\t\t</select>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tconst options = scratch.firstChild.children;\n\t\texpect(options[0]).to.have.property('selected', true);\n\t\texpect(options[1]).to.have.property('selected', false);\n\t\texpect(options[2]).to.have.property('selected', true);\n\t});\n\n\tit('should ignore defaultValue when value is 0', () => {\n\t\trender(<input defaultValue={2} value={0} />, scratch);\n\t\texpect(scratch.firstElementChild.value).to.equal('0');\n\t});\n\n\tit('should use defaultProps when prop is undefined', () => {\n\t\tfunction TestComponent({ message }) {\n\t\t\treturn <div>{message}</div>;\n\t\t}\n\t\tTestComponent.defaultProps = {\n\t\t\tmessage: 'default message'\n\t\t};\n\n\t\trender(<TestComponent message={undefined} />, scratch);\n\t\texpect(scratch.textContent).to.equal('default message');\n\t});\n\n\tit('should not use defaultProps when prop is null', () => {\n\t\tfunction TestComponent({ message }) {\n\t\t\treturn <div>{message === null ? 'null value' : message}</div>;\n\t\t}\n\t\tTestComponent.defaultProps = {\n\t\t\tmessage: 'default message'\n\t\t};\n\n\t\trender(<TestComponent message={null} />, scratch);\n\t\texpect(scratch.textContent).to.equal('null value');\n\t});\n\n\tit('should not use defaultProps when prop has a value', () => {\n\t\tfunction TestComponent({ message }) {\n\t\t\treturn <div>{message}</div>;\n\t\t}\n\t\tTestComponent.defaultProps = {\n\t\t\tmessage: 'default message'\n\t\t};\n\n\t\trender(<TestComponent message=\"actual message\" />, scratch);\n\t\texpect(scratch.textContent).to.equal('actual message');\n\t});\n\n\tit('should use defaultProps when prop is missing entirely', () => {\n\t\tfunction TestComponent({ message }) {\n\t\t\treturn <div>{message}</div>;\n\t\t}\n\t\tTestComponent.defaultProps = {\n\t\t\tmessage: 'default message'\n\t\t};\n\n\t\trender(<TestComponent />, scratch);\n\t\texpect(scratch.textContent).to.equal('default message');\n\t});\n\n\tit('should handle multiple defaultProps with mixed prop states', () => {\n\t\tfunction TestComponent({ title, message, count }) {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<h1>{title}</h1>\n\t\t\t\t\t<p>{message}</p>\n\t\t\t\t\t<span>{count}</span>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t\tTestComponent.defaultProps = {\n\t\t\ttitle: 'Default Title',\n\t\t\tmessage: 'Default Message',\n\t\t\tcount: 42\n\t\t};\n\n\t\t// title is undefined (should use default), message is null (should not use default), count has value (should not use default)\n\t\trender(\n\t\t\t<TestComponent title={undefined} message={null} count={0} />,\n\t\t\tscratch\n\t\t);\n\n\t\tconst title = scratch.querySelector('h1');\n\t\tconst message = scratch.querySelector('p');\n\t\tconst count = scratch.querySelector('span');\n\n\t\texpect(title.textContent).to.equal('Default Title');\n\t\texpect(message.textContent).to.equal(''); // null renders as empty\n\t\texpect(count.textContent).to.equal('0'); // 0 is a valid value\n\t});\n\n\tit('should call onChange and onInput when input event is dispatched', () => {\n\t\tconst onChange = vi.fn();\n\t\tconst onInput = vi.fn();\n\n\t\trender(<input onChange={onChange} onInput={onInput} />, scratch);\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('input'));\n\n\t\texpect(onChange).toHaveBeenCalledOnce();\n\t\texpect(onInput).toHaveBeenCalledOnce();\n\n\t\tonChange.mockClear();\n\t\tonInput.mockClear();\n\n\t\t// change props order\n\t\trender(<input onInput={onInput} onChange={onChange} />, scratch);\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('input'));\n\n\t\texpect(onChange).toHaveBeenCalledOnce();\n\t\texpect(onInput).toHaveBeenCalledOnce();\n\t});\n\n\tit('should keep value of uncontrolled inputs using defaultValue', () => {\n\t\t// See https://github.com/preactjs/preact/issues/2391\n\n\t\tconst spy = vi.fn();\n\n\t\tclass Input extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tdefaultValue=\"bar\"\n\t\t\t\t\t\tonChange={() => {\n\t\t\t\t\t\t\tspy();\n\t\t\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Input />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('bar');\n\t\tscratch.firstChild.focus();\n\t\tscratch.firstChild.value = 'foo';\n\n\t\tscratch.firstChild.dispatchEvent(createEvent('input'));\n\t\trerender();\n\t\texpect(scratch.firstChild.value).to.equal('foo');\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should call the callback', () => {\n\t\tlet spy = vi.fn();\n\t\trender(<div />, scratch, spy);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith();\n\t});\n\n\t// Issue #1727\n\tit('should destroy the any existing DOM nodes inside the container', () => {\n\t\tscratch.appendChild(document.createElement('div'));\n\t\tscratch.appendChild(document.createElement('div'));\n\n\t\trender(<span>foo</span>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<span>foo</span>');\n\t});\n\n\tit('should only destroy existing DOM nodes on first render', () => {\n\t\tscratch.appendChild(document.createElement('div'));\n\t\tscratch.appendChild(document.createElement('div'));\n\n\t\trender(<input />, scratch);\n\n\t\tlet child = scratch.firstChild;\n\t\tchild.focus();\n\t\trender(<input />, scratch);\n\t\texpect(document.activeElement.nodeName).to.equal('INPUT');\n\t});\n\n\tit('should transform react-style camel cased attributes', () => {\n\t\trender(\n\t\t\t<text dominantBaseline=\"middle\" fontWeight=\"30px\">\n\t\t\t\tfoo\n\t\t\t</text>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<text dominant-baseline=\"middle\" font-weight=\"30px\">foo</text>'\n\t\t);\n\t});\n\n\tit('should not transform imageSrcSet', () => {\n\t\trender(\n\t\t\t<link\n\t\t\t\trel=\"preload\"\n\t\t\t\tas=\"image\"\n\t\t\t\thref=\"preact.jpg\"\n\t\t\t\timageSrcSet=\"preact_400px.jpg 400w\"\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(sortAttributes(scratch.innerHTML)).to.equal(\n\t\t\t'<link as=\"image\" href=\"preact.jpg\" imagesrcset=\"preact_400px.jpg 400w\" rel=\"preload\">'\n\t\t);\n\t});\n\n\tit('should correctly allow for \"className\"', () => {\n\t\tconst Foo = props => {\n\t\t\tconst { className, ...rest } = props;\n\t\t\treturn (\n\t\t\t\t<div class={className}>\n\t\t\t\t\t<p {...rest}>Foo</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<Foo className=\"foo\" />, scratch);\n\t\texpect(scratch.firstChild.className).to.equal('foo');\n\t\texpect(scratch.firstChild.firstChild.className).to.equal('');\n\t});\n\n\tit('should normalize class+className even on components', () => {\n\t\tfunction Foo(props) {\n\t\t\treturn (\n\t\t\t\t<div class={props.class} className={props.className}>\n\t\t\t\t\tfoo\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t\trender(<Foo class=\"foo\" />, scratch);\n\t\texpect(scratch.firstChild.className).to.equal('foo');\n\t\trender(null, scratch);\n\n\t\trender(<Foo className=\"foo\" />, scratch);\n\t\texpect(scratch.firstChild.className).to.equal('foo');\n\t});\n\n\tit('should normalize className when it has an empty string', () => {\n\t\tfunction Foo(props) {\n\t\t\texpect(props.className).to.equal('');\n\t\t\treturn <div className=\"\">foo</div>;\n\t\t}\n\n\t\trender(<Foo className=\"\" />, scratch);\n\t});\n\n\t// Issue #2275\n\tit('should normalize class+className + DOM properties', () => {\n\t\tfunction Foo(props) {\n\t\t\treturn <ul class=\"old\" {...props} />;\n\t\t}\n\n\t\trender(<Foo fontSize=\"xlarge\" className=\"new\" />, scratch);\n\t\texpect(scratch.firstChild.className).to.equal('new');\n\t});\n\n\tit('should give precedence to last-applied class/className prop', () => {\n\t\trender(<ul className=\"from className\" class=\"from class\" />, scratch);\n\t\texpect(scratch.firstChild.className).to.equal('from className');\n\n\t\trender(<ul class=\"from class\" className=\"from className\" />, scratch);\n\t\texpect(scratch.firstChild.className).to.equal('from className');\n\t});\n\n\tdescribe('className normalization', () => {\n\t\tit('should give precedence to className over class', () => {\n\t\t\tconst { props } = <ul className=\"from className\" class=\"from class\" />;\n\t\t\texpect(props).to.have.property('className', 'from className');\n\t\t\texpect(props).to.have.property('class', 'from className');\n\t\t});\n\n\t\tit('should preserve className, add class alias', () => {\n\t\t\tconst { props } = <ul className=\"from className\" />;\n\t\t\texpect(props).to.have.property('className', 'from className');\n\t\t\t// TODO: why would we do this, assuming that folks add className themselves\n\t\t\texpect(props).to.have.property('class', 'from className');\n\t\t});\n\n\t\tit('should preserve class, and add className alias', () => {\n\t\t\tconst { props } = <ul class=\"from class\" />;\n\t\t\texpect(props).to.have.property('class', 'from class');\n\t\t\texpect(props.propertyIsEnumerable('className')).to.equal(false);\n\t\t\texpect(props).to.have.property('className', 'from class');\n\t\t});\n\n\t\tit('should preserve class when spreading', () => {\n\t\t\tconst { props } = <ul class=\"from class\" />;\n\t\t\tconst spreaded = (<li a {...props} />).props;\n\t\t\texpect(spreaded).to.have.property('class', 'from class');\n\t\t\texpect(spreaded.propertyIsEnumerable('className')).to.equal(false);\n\t\t\texpect(spreaded).to.have.property('className', 'from class');\n\t\t});\n\n\t\tit('should preserve className when spreading', () => {\n\t\t\tconst { props } = <ul className=\"from className\" />;\n\t\t\tconst spreaded = (<li a {...props} />).props;\n\t\t\texpect(spreaded).to.have.property('className', 'from className');\n\t\t\t// TODO: why would we do this, assuming that folks add className themselves\n\t\t\texpect(spreaded).to.have.property('class', 'from className');\n\t\t\texpect(spreaded.propertyIsEnumerable('class')).to.equal(true);\n\t\t});\n\n\t\t// Issue #2772\n\t\tit('should give precedence to className from spread props', () => {\n\t\t\tconst Foo = ({ className, ...props }) => {\n\t\t\t\treturn <div className={`${className} foo`} {...props} />;\n\t\t\t};\n\t\t\trender(<Foo className=\"bar\" />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('bar foo');\n\t\t});\n\n\t\tit('should give precedence to class from spread props', () => {\n\t\t\tconst Foo = ({ class: c, ...props }) => {\n\t\t\t\treturn <div class={`${c} foo`} {...props} />;\n\t\t\t};\n\t\t\trender(<Foo class=\"bar\" />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('bar foo');\n\t\t});\n\n\t\t// Issue #2224\n\t\tit('should not mark both class and className as enumerable', () => {\n\t\t\tfunction ClassNameCheck(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>{props.propertyIsEnumerable('className') ? 'Failed' : ''}</div>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet update;\n\t\t\tclass OtherThing extends Component {\n\t\t\t\trender({ children }) {\n\t\t\t\t\tupdate = () => this.forceUpdate();\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t<ClassNameCheck class=\"test\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction App() {\n\t\t\t\treturn (\n\t\t\t\t\t<OtherThing>\n\t\t\t\t\t\t<ClassNameCheck class=\"test\" />\n\t\t\t\t\t</OtherThing>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\n\t\t\tupdate();\n\t\t\trerender();\n\n\t\t\texpect(/Failed/g.test(scratch.textContent)).to.equal(\n\t\t\t\tfalse,\n\t\t\t\t'not enumerable'\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should cast boolean \"download\" values', () => {\n\t\trender(<a download />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('download')).to.equal('');\n\n\t\trender(<a download={false} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('download')).to.equal(null);\n\t});\n\n\tit('should support static content', () => {\n\t\tconst updateSpy = vi.fn();\n\t\tconst mountSpy = vi.fn();\n\t\tconst renderSpy = vi.fn();\n\n\t\tfunction StaticContent({ children, element = 'div', staticMode }) {\n\t\t\t// if we're in the server or a spa navigation, just render it\n\t\t\tif (!staticMode) {\n\t\t\t\treturn createElement(element, {\n\t\t\t\t\tchildren\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// avoid re-render on the client\n\t\t\treturn createElement(element, {\n\t\t\t\tdangerouslySetInnerHTML: { __html: '' }\n\t\t\t});\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tmountSpy();\n\t\t\t}\n\n\t\t\tcomponentDidUpdate() {\n\t\t\t\tupdateSpy();\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\trenderSpy();\n\t\t\t\treturn <div>Staticness</div>;\n\t\t\t}\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<StaticContent staticMode={false}>\n\t\t\t\t\t<App />\n\t\t\t\t</StaticContent>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.eq('<div><div>Staticness</div></div>');\n\t\texpect(renderSpy).toHaveBeenCalledOnce();\n\t\texpect(mountSpy).toHaveBeenCalledOnce();\n\t\texpect(updateSpy).not.toHaveBeenCalled();\n\n\t\tact(() => {\n\t\t\thydrate(\n\t\t\t\t<StaticContent staticMode>\n\t\t\t\t\t<App />\n\t\t\t\t</StaticContent>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.eq('<div><div>Staticness</div></div>');\n\t\texpect(renderSpy).toHaveBeenCalledOnce();\n\t\texpect(mountSpy).toHaveBeenCalledOnce();\n\t\texpect(updateSpy).not.toHaveBeenCalled();\n\t});\n\n\tit('should support the translate attribute w/ yes as a string', () => {\n\t\trender(<b translate=\"yes\">Bold</b>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<b translate=\"yes\">Bold</b>');\n\t});\n\n\tit('should support the translate attribute w/ no as a string', () => {\n\t\trender(<b translate=\"no\">Bold</b>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<b translate=\"no\">Bold</b>');\n\t});\n\n\tit('should support false aria-* attributes', () => {\n\t\trender(<div aria-checked={false} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('aria-checked')).to.equal('false');\n\t});\n\n\tit('should support false data-* attributes', () => {\n\t\trender(<div data-checked={false} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('data-checked')).to.equal('false');\n\t});\n\n\tit(\"should support react-relay's usage of __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\", () => {\n\t\tconst Ctx = createContext('foo');\n\n\t\t// Simplified version of: https://github.com/facebook/relay/blob/fba79309977bf6b356ee77a5421ca5e6f306223b/packages/react-relay/readContext.js#L17-L28\n\t\tfunction readContext(Context) {\n\t\t\tconst { ReactCurrentDispatcher } =\n\t\t\t\tReact.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\t\t\tconst dispatcher = ReactCurrentDispatcher.current;\n\t\t\treturn dispatcher.readContext(Context);\n\t\t}\n\n\t\tfunction Foo() {\n\t\t\tconst value = readContext(Ctx);\n\t\t\treturn <div>{value}</div>;\n\t\t}\n\n\t\tReact.render(\n\t\t\t<Ctx.Provider value=\"foo\">\n\t\t\t\t<Foo />\n\t\t\t</Ctx.Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.textContent).to.equal('foo');\n\t});\n\n\tit('should allow context as a component', () => {\n\t\tconst Context = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\n\t\tlet receivedContext;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.a}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<Context value={CONTEXT}>\n\t\t\t\t<div>\n\t\t\t\t\t<Context.Consumer>\n\t\t\t\t\t\t{data => {\n\t\t\t\t\t\t\treceivedContext = data;\n\t\t\t\t\t\t\treturn <Inner {...data} />;\n\t\t\t\t\t\t}}\n\t\t\t\t\t</Context.Consumer>\n\t\t\t\t</div>\n\t\t\t</Context>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\tCONTEXT,\n\t\t\t{},\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedContext).to.equal(CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>a</div></div>');\n\t});\n\n\tit(\"should support recoils's usage of __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\", () => {\n\t\t// Simplified version of: https://github.com/facebookexperimental/Recoil/blob/c1b97f3a0117cad76cbc6ab3cb06d89a9ce717af/packages/recoil/core/Recoil_ReactMode.js#L36-L44\n\t\tfunction useStateWrapper(init) {\n\t\t\tconst { ReactCurrentDispatcher } =\n\t\t\t\tReact.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\t\t\tconst dispatcher = ReactCurrentDispatcher.current;\n\t\t\treturn dispatcher.useState(init);\n\t\t}\n\n\t\tfunction Foo() {\n\t\t\tconst [value] = useStateWrapper('foo');\n\t\t\treturn <div>{value}</div>;\n\t\t}\n\n\t\tReact.render(<Foo />, scratch);\n\n\t\texpect(scratch.textContent).to.equal('foo');\n\t});\n\n\tit('should append \"px\" to unitless inline css values', () => {\n\t\t// These are all CSS Properties that support a single <length> value\n\t\t// that must have a unit. If we encounter a number we append \"px\" to it.\n\t\t// The list is taken from: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference\n\t\tconst unitless = {\n\t\t\t'border-block': 2,\n\t\t\t'border-block-end-width': 3,\n\t\t\t'border-block-start-width': 4,\n\t\t\t'border-block-width': 5,\n\t\t\t'border-bottom-left-radius': 6,\n\t\t\t'border-bottom-right-radius': 7,\n\t\t\t'border-bottom-width': 8,\n\t\t\t'border-end-end-radius': 9,\n\t\t\t'border-end-start-radius': 10,\n\t\t\t'border-image-outset': 11,\n\t\t\t'border-image-width': 12,\n\t\t\t'border-inline': 2,\n\t\t\t'border-inline-end': 3,\n\t\t\t'border-inline-end-width': 4,\n\t\t\t'border-inline-start': 1,\n\t\t\t'border-inline-start-width': 123,\n\t\t\t'border-inline-width': 123,\n\t\t\t'border-left': 123,\n\t\t\t'border-left-width': 123,\n\t\t\t'border-radius': 123,\n\t\t\t'border-right': 123,\n\t\t\t'border-right-width': 123,\n\t\t\t'border-spacing': 123,\n\t\t\t'border-start-end-radius': 123,\n\t\t\t'border-start-start-radius': 123,\n\t\t\t'border-top': 123,\n\t\t\t'border-top-left-radius': 123,\n\t\t\t'border-top-right-radius': 123,\n\t\t\t'border-top-width': 123,\n\t\t\t'border-width': 123,\n\t\t\tbottom: 123,\n\t\t\t'column-gap': 123,\n\t\t\t'column-rule-width': 23,\n\t\t\t'column-width': 23,\n\t\t\t'flex-basis': 23,\n\t\t\t'font-size': 123,\n\t\t\t'grid-gap': 23,\n\t\t\t'grid-auto-columns': 123,\n\t\t\t'grid-auto-rows': 123,\n\t\t\t'grid-template-columns': 23,\n\t\t\t'grid-template-rows': 23,\n\t\t\theight: 123,\n\t\t\t'inline-size': 23,\n\t\t\tinset: 23,\n\t\t\t'inset-block-end': 12,\n\t\t\t'inset-block-start': 12,\n\t\t\t'inset-inline-end': 213,\n\t\t\t'inset-inline-start': 213,\n\t\t\tleft: 213,\n\t\t\t'letter-spacing': 213,\n\t\t\tmargin: 213,\n\t\t\t'margin-block': 213,\n\t\t\t'margin-block-end': 213,\n\t\t\t'margin-block-start': 213,\n\t\t\t'margin-bottom': 213,\n\t\t\t'margin-inline': 213,\n\t\t\t'margin-inline-end': 213,\n\t\t\t'margin-inline-start': 213,\n\t\t\t'margin-left': 213,\n\t\t\t'margin-right': 213,\n\t\t\t'margin-top': 213,\n\t\t\t'mask-position': 23,\n\t\t\t'mask-size': 23,\n\t\t\t'max-block-size': 23,\n\t\t\t'max-height': 23,\n\t\t\t'max-inline-size': 23,\n\t\t\t'max-width': 23,\n\t\t\t'min-block-size': 23,\n\t\t\t'min-height': 23,\n\t\t\t'min-inline-size': 23,\n\t\t\t'min-width': 23,\n\t\t\t'object-position': 23,\n\t\t\t'outline-offset': 23,\n\t\t\t'outline-width': 123,\n\t\t\tpadding: 123,\n\t\t\t'padding-block': 123,\n\t\t\t'padding-block-end': 123,\n\t\t\t'padding-block-start': 123,\n\t\t\t'padding-bottom': 123,\n\t\t\t'padding-inline': 123,\n\t\t\t'padding-inline-end': 123,\n\t\t\t'padding-inline-start': 123,\n\t\t\t'padding-left': 123,\n\t\t\t'padding-right': 123,\n\t\t\t'padding-top': 123,\n\t\t\tperspective: 123,\n\t\t\tright: 123,\n\t\t\t'scroll-margin': 123,\n\t\t\t'scroll-margin-block': 123,\n\t\t\t'scroll-margin-block-start': 123,\n\t\t\t'scroll-margin-bottom': 123,\n\t\t\t'scroll-margin-inline': 123,\n\t\t\t'scroll-margin-inline-end': 123,\n\t\t\t'scroll-margin-inline-start': 123,\n\t\t\t'scroll-margin-inline-left': 123,\n\t\t\t'scroll-margin-inline-right': 123,\n\t\t\t'scroll-margin-inline-top': 123,\n\t\t\t'scroll-padding': 123,\n\t\t\t'scroll-padding-block': 123,\n\t\t\t'scroll-padding-block-end': 123,\n\t\t\t'scroll-padding-block-start': 123,\n\t\t\t'scroll-padding-bottom': 123,\n\t\t\t'scroll-padding-inline': 123,\n\t\t\t'scroll-padding-inline-end': 123,\n\t\t\t'scroll-padding-inline-start': 123,\n\t\t\t'scroll-padding-left': 123,\n\t\t\t'scroll-padding-right': 123,\n\t\t\t'scroll-padding-top': 123,\n\t\t\t'shape-margin': 123,\n\t\t\t'text-decoration-thickness': 123,\n\t\t\t'text-indent': 123,\n\t\t\t'text-underline-offset': 123,\n\t\t\ttop: 123,\n\t\t\t'transform-origin': 123,\n\t\t\ttranslate: 123,\n\t\t\twidth: 123,\n\t\t\t'word-spacing': 123\n\t\t};\n\n\t\t// These are all CSS properties that have valid numeric values.\n\t\t// Our appending logic must not be applied here\n\t\tconst untouched = {\n\t\t\t'-webkit-line-clamp': 2,\n\t\t\tanimation: 2,\n\t\t\t'animation-iteration-count': 3,\n\t\t\t'border-image': 2,\n\t\t\t'border-image-slice': 2,\n\t\t\t'column-count': 2,\n\t\t\tcolumns: 2,\n\t\t\tflex: 1,\n\t\t\t'flex-grow': 1,\n\t\t\t'flex-shrink': 1,\n\t\t\t'font-size-adjust': 123,\n\t\t\t'font-weight': 12,\n\t\t\t'grid-column': 2,\n\t\t\t'grid-column-end': 2,\n\t\t\t'grid-column-start': 2,\n\t\t\t'grid-row': 2,\n\t\t\t'grid-row-end': 2,\n\t\t\t'grid-row-gap': 23,\n\t\t\t'grid-row-start': 2,\n\t\t\t'inital-letter': 2,\n\t\t\t'line-height': 2,\n\t\t\t'line-clamp': 2,\n\t\t\t'mask-border': 2,\n\t\t\t'mask-border-outset': 2,\n\t\t\t'mask-border-slice': 2,\n\t\t\t'mask-border-width': 2,\n\t\t\t'max-lines': 2,\n\t\t\t'max-zoom': 2,\n\t\t\t'min-zoom': 2,\n\t\t\topacity: 123,\n\t\t\torder: 123,\n\t\t\torphans: 2,\n\t\t\tscale: 23,\n\t\t\t'shape-image-threshold': 23,\n\t\t\t'tab-size': 23,\n\t\t\twidows: 123,\n\t\t\t'z-index': 123,\n\t\t\tzoom: 123\n\t\t};\n\n\t\trender(\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\t...unitless,\n\t\t\t\t\t...untouched\n\t\t\t\t}}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet style = scratch.firstChild.style;\n\n\t\t// Check properties that MUST not be changed\n\t\tfor (const key in unitless) {\n\t\t\t// Check if css property is supported\n\t\t\tif (\n\t\t\t\twindow.CSS &&\n\t\t\t\ttypeof window.CSS.supports === 'function' &&\n\t\t\t\twindow.CSS.supports(key, unitless[key])\n\t\t\t) {\n\t\t\t\texpect(\n\t\t\t\t\tString(style[key]).endsWith('px'),\n\t\t\t\t\t`Should append px \"${key}: ${unitless[key]}\" === \"${key}: ${style[key]}\"`\n\t\t\t\t).to.equal(true);\n\t\t\t}\n\t\t}\n\n\t\t// Check properties that MUST not be changed\n\t\tfor (const key in untouched) {\n\t\t\t// Check if css property is supported\n\t\t\tif (\n\t\t\t\twindow.CSS &&\n\t\t\t\ttypeof window.CSS.supports === 'function' &&\n\t\t\t\twindow.CSS.supports(key, untouched[key])\n\t\t\t) {\n\t\t\t\texpect(\n\t\t\t\t\t!String(style[key]).endsWith('px'),\n\t\t\t\t\t`Should be left as is: \"${key}: ${untouched[key]}\" === \"${key}: ${style[key]}\"`\n\t\t\t\t).to.equal(true);\n\t\t\t}\n\t\t}\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/scheduler.test.js",
    "content": "import {\n\tunstable_runWithPriority,\n\tunstable_NormalPriority,\n\tunstable_LowPriority,\n\tunstable_IdlePriority,\n\tunstable_UserBlockingPriority,\n\tunstable_ImmediatePriority,\n\tunstable_now\n} from 'preact/compat/scheduler';\nimport { vi } from 'vitest';\n\ndescribe('scheduler', () => {\n\tdescribe('runWithPriority', () => {\n\t\tit('should call callback ', () => {\n\t\t\tconst spy = vi.fn();\n\t\t\tunstable_runWithPriority(unstable_IdlePriority, spy);\n\t\t\texpect(spy).toHaveBeenCalledTimes(1);\n\n\t\t\tunstable_runWithPriority(unstable_LowPriority, spy);\n\t\t\texpect(spy).toHaveBeenCalledTimes(2);\n\n\t\t\tunstable_runWithPriority(unstable_NormalPriority, spy);\n\t\t\texpect(spy).toHaveBeenCalledTimes(3);\n\n\t\t\tunstable_runWithPriority(unstable_UserBlockingPriority, spy);\n\t\t\texpect(spy).toHaveBeenCalledTimes(4);\n\n\t\t\tunstable_runWithPriority(unstable_ImmediatePriority, spy);\n\t\t\texpect(spy).toHaveBeenCalledTimes(5);\n\t\t});\n\t});\n\n\tdescribe('unstable_now', () => {\n\t\tit('should return number', () => {\n\t\t\tconst res = unstable_now();\n\t\t\texpect(res).is.a('number');\n\t\t\texpect(res > 0).to.equal(true);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/select.test.jsx",
    "content": "import { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { createElement, render } from 'preact/compat';\n\ndescribe('Select', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should work with multiple selected (array of values)', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<select multiple value={['B', 'C']}>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tconst options = scratch.firstChild.children;\n\t\texpect(options[0]).to.have.property('selected', false);\n\t\texpect(options[1]).to.have.property('selected', true);\n\t\texpect(options[2]).to.have.property('selected', true);\n\t\texpect(scratch.firstChild.value).to.equal('B');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/suspense-hydration.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport React, {\n\tcreateElement,\n\thydrate,\n\tFragment,\n\tSuspense,\n\tmemo,\n\tuseState\n} from 'preact/compat';\nimport { logCall, getLog, clearLog } from '../../../test/_util/logCall';\nimport {\n\tcreateEvent,\n\tsetupScratch,\n\tteardown\n} from '../../../test/_util/helpers';\nimport { ul, li, div } from '../../../test/_util/dom';\nimport { createLazy, createSuspenseLoader } from './suspense-utils';\nimport { vi } from 'vitest';\n\n/* eslint-env browser */\ndescribe('suspense hydration', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch,\n\t\trerender,\n\t\tunhandledEvents = [];\n\n\tconst List = ({ children }) => <ul>{children}</ul>;\n\tconst ListItem = ({ children, onClick = null }) => (\n\t\t<li onClick={onClick}>{children}</li>\n\t);\n\n\tfunction onUnhandledRejection(event) {\n\t\tunhandledEvents.push(event);\n\t}\n\n\tlet resetAppendChild;\n\tlet resetInsertBefore;\n\tlet resetRemoveChild;\n\tlet resetRemove;\n\n\tbeforeAll(() => {\n\t\tresetAppendChild = logCall(Element.prototype, 'appendChild');\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetRemoveChild = logCall(Element.prototype, 'removeChild');\n\t\tresetRemove = logCall(Element.prototype, 'remove');\n\t});\n\n\tafterAll(() => {\n\t\tresetAppendChild();\n\t\tresetInsertBefore();\n\t\tresetRemoveChild();\n\t\tresetRemove();\n\t});\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\n\t\tunhandledEvents = [];\n\t\tif ('onunhandledrejection' in window) {\n\t\t\twindow.addEventListener('unhandledrejection', onUnhandledRejection);\n\t\t}\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\n\t\tif ('onunhandledrejection' in window) {\n\t\t\twindow.removeEventListener('unhandledrejection', onUnhandledRejection);\n\n\t\t\tif (unhandledEvents.length) {\n\t\t\t\tthrow unhandledEvents[0].reason;\n\t\t\t}\n\t\t}\n\t});\n\n\tit('should leave DOM untouched when suspending while hydrating', () => {\n\t\tscratch.innerHTML = '<div>Hello</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<Lazy />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(() => <div>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('should leave DOM untouched when suspending while hydrating', () => {\n\t\tscratch.innerHTML = '<!-- test --><div>Hello</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<Lazy />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<!-- test --><div>Hello</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(() => <div>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<!-- test --><div>Hello</div>');\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('should properly attach event listeners when suspending while hydrating', () => {\n\t\tscratch.innerHTML = '<div>Hello</div><div>World</div>';\n\t\tclearLog();\n\n\t\tconst helloListener = vi.fn();\n\t\tconst worldListener = vi.fn();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<Lazy />\n\t\t\t\t<div onClick={worldListener}>World!</div>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div><div>World!</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\tscratch.querySelector('div:last-child').dispatchEvent(createEvent('click'));\n\t\texpect(worldListener, 'worldListener 1').toHaveBeenCalledOnce();\n\n\t\treturn resolve(() => <div onClick={helloListener}>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div><div>World!</div>');\n\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\tscratch\n\t\t\t\t.querySelector('div:first-child')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(helloListener, 'helloListener').toHaveBeenCalledOnce();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('div:last-child')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(worldListener, 'worldListener 2').toHaveBeenCalledTimes(2);\n\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('should allow siblings to update around suspense boundary', () => {\n\t\tscratch.innerHTML = '<div>Count: 0</div><div>Hello</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\t\tfunction Counter() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tincrement = () => setCount(c => c + 1);\n\t\t\treturn <div>Count: {count}</div>;\n\t\t}\n\n\t\thydrate(\n\t\t\t<Fragment>\n\t\t\t\t<Counter />\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 0</div><div>Hello</div>');\n\t\t// Re: DOM OP below - Known issue with hydrating merged text nodes\n\t\texpect(getLog()).to.deep.equal(['<div>Count: .appendChild(#text)']);\n\t\tclearLog();\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 1</div><div>Hello</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(() => <div>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Count: 1</div><div>Hello</div>');\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('should allow parents to update around suspense boundary and unmount', async () => {\n\t\tscratch.innerHTML = '<div>Count: 0</div><div>Hello</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\t\tfunction Counter() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tincrement = () => setCount(c => c + 1);\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<div>Count: {count}</div>\n\t\t\t\t\t<Suspense>\n\t\t\t\t\t\t<Lazy />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tlet hide;\n\t\tfunction Component() {\n\t\t\tconst [show, setShow] = useState(true);\n\t\t\thide = () => setShow(false);\n\n\t\t\treturn show ? <Counter /> : null;\n\t\t}\n\n\t\thydrate(<Component />, scratch);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 0</div><div>Hello</div>');\n\t\t// Re: DOM OP below - Known issue with hydrating merged text nodes\n\t\texpect(getLog()).to.deep.equal(['<div>Count: .appendChild(#text)']);\n\t\tclearLog();\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 1</div><div>Hello</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\tawait resolve(() => <div>Hello</div>);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 1</div><div>Hello</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\thide();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should allow parents to update around suspense boundary and unmount before resolves', async () => {\n\t\tscratch.innerHTML = '<div>Count: 0</div><div>Hello</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy] = createLazy();\n\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\t\tfunction Counter() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tincrement = () => setCount(c => c + 1);\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<div>Count: {count}</div>\n\t\t\t\t\t<Suspense>\n\t\t\t\t\t\t<Lazy />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tlet hide;\n\t\tfunction Component() {\n\t\t\tconst [show, setShow] = useState(true);\n\t\t\thide = () => setShow(false);\n\n\t\t\treturn show ? <Counter /> : null;\n\t\t}\n\n\t\thydrate(<Component />, scratch);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 0</div><div>Hello</div>');\n\t\t// Re: DOM OP below - Known issue with hydrating merged text nodes\n\t\texpect(getLog()).to.deep.equal(['<div>Count: .appendChild(#text)']);\n\t\tclearLog();\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 1</div><div>Hello</div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\thide();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should allow parents to unmount before resolves', async () => {\n\t\tscratch.innerHTML = '<div>Count: 0</div><div>Hello</div>';\n\n\t\tconst [Lazy] = createLazy();\n\n\t\tfunction Counter() {\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<div>Count: 0</div>\n\t\t\t\t\t<Suspense>\n\t\t\t\t\t\t<Lazy />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tlet hide;\n\t\tfunction Component() {\n\t\t\tconst [show, setShow] = useState(true);\n\t\t\thide = () => setShow(false);\n\n\t\t\treturn show ? <Counter /> : null;\n\t\t}\n\n\t\thydrate(<Component />, scratch);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\n\t\thide();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should properly hydrate when there is DOM and Components between Suspense and suspender', () => {\n\t\tscratch.innerHTML = '<div><div>Hello</div></div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<div>\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<Lazy />\n\t\t\t\t\t</Fragment>\n\t\t\t\t</div>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('<div><div>Hello</div></div>');\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(() => <div>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div><div>Hello</div></div>');\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('should properly hydrate suspense with Fragment siblings', () => {\n\t\tconst originalHtml = ul([li(0), li(1), li(2), li(3), li(4)]);\n\n\t\tconst listeners = [vi.fn(), vi.fn(), vi.fn(), vi.fn(), vi.fn()];\n\n\t\tscratch.innerHTML = originalHtml;\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<ul>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<li onClick={listeners[0]}>0</li>\n\t\t\t\t\t<li onClick={listeners[1]}>1</li>\n\t\t\t\t</Fragment>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<li onClick={listeners[3]}>3</li>\n\t\t\t\t\t<li onClick={listeners[4]}>4</li>\n\t\t\t\t</Fragment>\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(listeners[4]).not.toHaveBeenCalled();\n\n\t\tclearLog();\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\t\texpect(listeners[4]).toHaveBeenCalledOnce();\n\n\t\treturn resolve(() => (\n\t\t\t<Fragment>\n\t\t\t\t<li onClick={listeners[2]}>2</li>\n\t\t\t</Fragment>\n\t\t)).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:nth-child(3)')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[2]).toHaveBeenCalledOnce();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:last-child')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[4]).toHaveBeenCalledTimes(2);\n\t\t});\n\t});\n\n\tit('should properly hydrate suspense with Component & Fragment siblings', () => {\n\t\tconst originalHtml = ul([li(0), li(1), li(2), li(3), li(4)]);\n\n\t\tconst listeners = [vi.fn(), vi.fn(), vi.fn(), vi.fn(), vi.fn()];\n\n\t\tscratch.innerHTML = originalHtml;\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={listeners[0]}>0</ListItem>\n\t\t\t\t\t<ListItem onClick={listeners[1]}>1</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={listeners[3]}>3</ListItem>\n\t\t\t\t\t<ListItem onClick={listeners[4]}>4</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(listeners[4]).not.toHaveBeenCalled();\n\n\t\tclearLog();\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\t\texpect(listeners[4]).toHaveBeenCalledOnce();\n\n\t\treturn resolve(() => (\n\t\t\t<Fragment>\n\t\t\t\t<ListItem onClick={listeners[2]}>2</ListItem>\n\t\t\t</Fragment>\n\t\t)).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:nth-child(3)')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[2]).toHaveBeenCalledOnce();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:last-child')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[4]).toHaveBeenCalledTimes(2);\n\t\t});\n\t});\n\n\tit('should suspend hydration with components with state and event listeners between suspender and Suspense', () => {\n\t\tlet html = div([div('Count: 0'), div('Hello')]);\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\tfunction Counter({ children }) {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\treturn (\n\t\t\t\t<div onClick={() => setCount(count + 1)}>\n\t\t\t\t\t<div>Count: {count}</div>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<Counter>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Counter>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal(['<div>Count: .appendChild(#text)']);\n\t\tclearLog();\n\n\t\tscratch.firstElementChild.dispatchEvent(createEvent('click'));\n\t\trerender();\n\n\t\thtml = div([div('Count: 1'), div('Hello')]);\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\tconst lazySpy = vi.fn();\n\t\treturn resolve(() => <div onClick={lazySpy}>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(html);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\n\t\t\tconst lazyDiv = scratch.firstChild.firstChild.nextSibling;\n\t\t\texpect(lazyDiv.textContent).to.equal('Hello');\n\t\t\texpect(lazySpy).not.toHaveBeenCalled();\n\n\t\t\tlazyDiv.dispatchEvent(createEvent('click'));\n\t\t\trerender();\n\n\t\t\texpect(lazySpy).toHaveBeenCalledOnce();\n\t\t});\n\t});\n\n\tit('should maintain state of sibling components around suspender', () => {\n\t\tlet html = [div('Count: 0'), div('Hello'), div('Count: 0')].join('');\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\tfunction Counter() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\treturn <div onClick={() => setCount(count + 1)}>Count: {count}</div>;\n\t\t}\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<Counter />\n\t\t\t\t<Lazy />\n\t\t\t\t<Counter />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>Count: .appendChild(#text)',\n\t\t\t'<div>Count: .appendChild(#text)'\n\t\t]);\n\t\tclearLog();\n\n\t\t// Update state of first Counter\n\t\tscratch.firstElementChild.dispatchEvent(createEvent('click'));\n\t\trerender();\n\n\t\thtml = [div('Count: 1'), div('Hello'), div('Count: 0')].join('');\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\t// Update state of second Counter\n\t\tscratch.lastElementChild.dispatchEvent(createEvent('click'));\n\t\trerender();\n\n\t\thtml = [div('Count: 1'), div('Hello'), div('Count: 1')].join('');\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\tconst lazySpy = vi.fn();\n\t\treturn resolve(() => <div onClick={lazySpy}>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(html);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\n\t\t\tconst lazyDiv = scratch.firstChild.nextSibling;\n\t\t\texpect(lazyDiv.textContent).to.equal('Hello');\n\t\t\texpect(lazySpy).not.toHaveBeenCalled();\n\n\t\t\tlazyDiv.dispatchEvent(createEvent('click'));\n\t\t\trerender();\n\n\t\t\texpect(lazySpy).toHaveBeenCalledOnce();\n\t\t});\n\t});\n\n\tit('should allow component to re-suspend using normal suspension mechanics after initial suspended hydration resumes', () => {\n\t\tconst originalHtml = [div('a'), div('b1'), div('c')].join('');\n\t\tscratch.innerHTML = originalHtml;\n\t\tclearLog();\n\n\t\tconst bOnClickSpy = vi.fn();\n\t\tconst cOnClickSpy = vi.fn();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\n\t\t/** @type {(c: React.JSX.Element) => void} */\n\t\tlet setChild;\n\t\tfunction App() {\n\t\t\t// Mimic some state that may cause a suspend\n\t\t\tconst [child, setChildInternal] = useState(<Lazy />);\n\t\t\tsetChild = setChildInternal;\n\n\t\t\treturn (\n\t\t\t\t<Suspense fallback={<div>fallback</div>}>\n\t\t\t\t\t<div>a</div>\n\t\t\t\t\t{child}\n\t\t\t\t\t<div onClick={cOnClickSpy}>c</div>\n\t\t\t\t</Suspense>\n\t\t\t);\n\t\t}\n\n\t\t// Validate initial hydration suspend resumes (initial markup stays the same\n\t\t// and event listeners attached)\n\t\thydrate(<App />, scratch);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML, 'initial HTML').to.equal(originalHtml);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\tscratch.lastChild.dispatchEvent(createEvent('click'));\n\t\trerender();\n\t\texpect(cOnClickSpy).toHaveBeenCalledOnce();\n\n\t\treturn resolve(() => <div onClick={bOnClickSpy}>b1</div>)\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML, 'hydration resumes').to.equal(originalHtml);\n\t\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\t\tclearLog();\n\n\t\t\t\tscratch.firstChild.nextSibling.dispatchEvent(createEvent('click'));\n\t\t\t\trerender();\n\t\t\t\texpect(bOnClickSpy).toHaveBeenCalledOnce();\n\n\t\t\t\t// suspend again and validate normal suspension works (fallback renders\n\t\t\t\t// and result)\n\t\t\t\tconst [Lazy2, resolve2] = createLazy();\n\t\t\t\tsetChild(<Lazy2 />);\n\t\t\t\trerender();\n\n\t\t\t\texpect(scratch.innerHTML, 'second suspend').to.equal(div('fallback'));\n\t\t\t\texpect(getLog()).to.deep.equal([\n\t\t\t\t\t'<div>b1.remove()',\n\t\t\t\t\t'<div>a.remove()',\n\t\t\t\t\t'<div>c.remove()',\n\t\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t\t'<div>.appendChild(<div>fallback)'\n\t\t\t\t]);\n\t\t\t\tclearLog();\n\n\t\t\t\treturn resolve2(() => <div onClick={bOnClickSpy}>b2</div>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML, 'second suspend resumes').to.equal(\n\t\t\t\t\t[div('a'), div('b2'), div('c')].join('')\n\t\t\t\t);\n\t\t\t\texpect(getLog()).to.deep.equal([\n\t\t\t\t\t'<div>fallback.appendChild(<div>a)',\n\t\t\t\t\t'<div>fallback.remove()',\n\t\t\t\t\t'<div>a.appendChild(<div>a)',\n\t\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t\t'<div>a.appendChild(<div>b2)',\n\t\t\t\t\t'<div>ab2.appendChild(<div>c)'\n\t\t\t\t]);\n\n\t\t\t\tscratch.firstChild.nextSibling.dispatchEvent(createEvent('click'));\n\t\t\t\texpect(bOnClickSpy).toHaveBeenCalledTimes(2);\n\n\t\t\t\tscratch.lastChild.dispatchEvent(createEvent('click'));\n\t\t\t\texpect(cOnClickSpy).toHaveBeenCalledTimes(2);\n\t\t\t});\n\t});\n\n\tit('should correctly hydrate and rerender a memoized lazy data loader', () => {\n\t\tconst originalHtml = '<p>Count: 5</p>';\n\t\tscratch.innerHTML = originalHtml;\n\n\t\tconst [useSuspenseLoader, resolve] = createSuspenseLoader();\n\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\t\tconst DataLoader = memo(function DataLoader() {\n\t\t\tconst initialCount = useSuspenseLoader();\n\t\t\tconst [count, setCount] = useState(initialCount);\n\t\t\tincrement = () => setCount(c => c + 1);\n\n\t\t\treturn <p>Count: {count}</p>;\n\t\t});\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<Suspense>\n\t\t\t\t\t<DataLoader />\n\t\t\t\t</Suspense>\n\t\t\t);\n\t\t}\n\n\t\thydrate(<App />, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\n\t\treturn resolve(5).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<p>Count: 5</p>');\n\n\t\t\tincrement();\n\t\t\trerender();\n\n\t\t\texpect(scratch.innerHTML).to.equal('<p>Count: 6</p>');\n\t\t});\n\t});\n\n\tit('should properly hydrate suspense when resolves to a Fragment', () => {\n\t\tconst originalHtml = ul([\n\t\t\tli(0),\n\t\t\tli(1),\n\t\t\t'<!--$s-->',\n\t\t\tli(2),\n\t\t\tli(3),\n\t\t\t'<!--/$s-->',\n\t\t\tli(4),\n\t\t\tli(5)\n\t\t]);\n\n\t\tconst listeners = [vi.fn(), vi.fn(), vi.fn(), vi.fn(), vi.fn(), vi.fn()];\n\n\t\tscratch.innerHTML = originalHtml;\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={listeners[0]}>0</ListItem>\n\t\t\t\t\t<ListItem onClick={listeners[1]}>1</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={listeners[4]}>4</ListItem>\n\t\t\t\t\t<ListItem onClick={listeners[5]}>5</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\texpect(listeners[5]).not.toHaveBeenCalled();\n\n\t\tclearLog();\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\t\texpect(listeners[5]).toHaveBeenCalledOnce();\n\n\t\treturn resolve(() => (\n\t\t\t<Fragment>\n\t\t\t\t<ListItem onClick={listeners[2]}>2</ListItem>\n\t\t\t\t<ListItem onClick={listeners[3]}>3</ListItem>\n\t\t\t</Fragment>\n\t\t)).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:nth-child(4)')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[3]).toHaveBeenCalledOnce();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:last-child')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[5]).toHaveBeenCalledTimes(2);\n\t\t});\n\t});\n\n\tit('should properly hydrate suspense when resolves to a Fragment without children', () => {\n\t\tconst originalHtml = ul([\n\t\t\tli(0),\n\t\t\tli(1),\n\t\t\t'<!--$s-->',\n\t\t\t'<!--/$s-->',\n\t\t\tli(2),\n\t\t\tli(3)\n\t\t]);\n\n\t\tconst listeners = [vi.fn(), vi.fn(), vi.fn(), vi.fn()];\n\n\t\tscratch.innerHTML = originalHtml;\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={listeners[0]}>0</ListItem>\n\t\t\t\t\t<ListItem onClick={listeners[1]}>1</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={listeners[2]}>2</ListItem>\n\t\t\t\t\t<ListItem onClick={listeners[3]}>3</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\texpect(listeners[3]).not.toHaveBeenCalled();\n\n\t\tclearLog();\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\t\texpect(listeners[3]).toHaveBeenCalledOnce();\n\n\t\treturn resolve(() => null).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\t\t\tclearLog();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:nth-child(2)')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[1]).toHaveBeenCalledOnce();\n\n\t\t\tscratch\n\t\t\t\t.querySelector('li:last-child')\n\t\t\t\t.dispatchEvent(createEvent('click'));\n\t\t\texpect(listeners[3]).toHaveBeenCalledTimes(2);\n\t\t});\n\t});\n\n\tit('Should hydrate a fragment with multiple children correctly', () => {\n\t\tscratch.innerHTML = '<!--$s--><div>Hello</div><div>World!</div><!--/$s-->';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<Suspense>\n\t\t\t\t<Lazy />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<!--$s--><div>Hello</div><div>World!</div><!--/$s-->'\n\t\t);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(() => (\n\t\t\t<>\n\t\t\t\t<div>Hello</div>\n\t\t\t\t<div>World!</div>\n\t\t\t</>\n\t\t)).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t'<!--$s--><div>Hello</div><div>World!</div><!--/$s-->'\n\t\t\t);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('Should hydrate a fragment with no children correctly', () => {\n\t\tscratch.innerHTML = '<!--$s--><!--/$s--><div>Hello world</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\thydrate(\n\t\t\t<>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t\t<div>Hello world</div>\n\t\t\t</>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<!--$s--><!--/$s--><div>Hello world</div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(() => null).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t'<!--$s--><!--/$s--><div>Hello world</div>'\n\t\t\t);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\tclearLog();\n\t\t});\n\t});\n\n\tit('Should hydrate a fragment with no children correctly deeply', () => {\n\t\tscratch.innerHTML =\n\t\t\t'<!--$s--><!--$s--><!--/$s--><!--/$s--><div>Hello world</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\tconst [Lazy2, resolve2] = createLazy();\n\t\thydrate(\n\t\t\t<>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy>\n\t\t\t\t\t\t<Suspense>\n\t\t\t\t\t\t\t<Lazy2 />\n\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t</Lazy>\n\t\t\t\t</Suspense>\n\t\t\t\t<div>Hello world</div>\n\t\t\t</>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<!--$s--><!--$s--><!--/$s--><!--/$s--><div>Hello world</div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(p => p.children).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t'<!--$s--><!--$s--><!--/$s--><!--/$s--><div>Hello world</div>'\n\t\t\t);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\tclearLog();\n\t\t\treturn resolve2(() => null).then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t'<!--$s--><!--$s--><!--/$s--><!--/$s--><div>Hello world</div>'\n\t\t\t\t);\n\t\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\t\tclearLog();\n\t\t\t});\n\t\t});\n\t});\n\n\tit('Should hydrate a fragment with multiple children correctly deeply', () => {\n\t\tscratch.innerHTML =\n\t\t\t'<!--$s--><!--$s--><p>I am</p><span>Fragment</span><!--/$s--><!--/$s--><div>Hello world</div>';\n\t\tclearLog();\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\tconst [Lazy2, resolve2] = createLazy();\n\t\thydrate(\n\t\t\t<>\n\t\t\t\t<Suspense>\n\t\t\t\t\t<Lazy>\n\t\t\t\t\t\t<Suspense>\n\t\t\t\t\t\t\t<Lazy2 />\n\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t</Lazy>\n\t\t\t\t</Suspense>\n\t\t\t\t<div>Hello world</div>\n\t\t\t</>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<!--$s--><!--$s--><p>I am</p><span>Fragment</span><!--/$s--><!--/$s--><div>Hello world</div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\treturn resolve(p => p.children).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t'<!--$s--><!--$s--><p>I am</p><span>Fragment</span><!--/$s--><!--/$s--><div>Hello world</div>'\n\t\t\t);\n\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\tclearLog();\n\t\t\treturn resolve2(() => (\n\t\t\t\t<>\n\t\t\t\t\t<p>I am</p>\n\t\t\t\t\t<span>Fragment</span>\n\t\t\t\t</>\n\t\t\t)).then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t'<!--$s--><!--$s--><p>I am</p><span>Fragment</span><!--/$s--><!--/$s--><div>Hello world</div>'\n\t\t\t\t);\n\t\t\t\texpect(getLog()).to.deep.equal([]);\n\n\t\t\t\tclearLog();\n\t\t\t});\n\t\t});\n\t});\n\n\tit('Should not crash when oldVNode._children is null during shouldComponentUpdate optimization', () => {\n\t\tconst originalHtml = '<div>Hello</div>';\n\t\tscratch.innerHTML = originalHtml;\n\t\tclearLog();\n\n\t\tclass ErrorBoundary extends React.Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { hasError: false };\n\t\t\t}\n\n\t\t\tstatic getDerivedStateFromError() {\n\t\t\t\treturn { hasError: true };\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<Suspense>\n\t\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t\t<Lazy />\n\t\t\t\t\t</ErrorBoundary>\n\t\t\t\t</Suspense>\n\t\t\t);\n\t\t}\n\n\t\thydrate(<App />, scratch);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\tclearLog();\n\n\t\tlet i = 0;\n\t\tclass ThrowOrRender extends React.Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn i === 0;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tif (i === 0) {\n\t\t\t\t\ti++;\n\t\t\t\t\tthrow new Error('Test error');\n\t\t\t\t}\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\treturn resolve(ThrowOrRender).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(originalHtml);\n\t\t\tclearLog();\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/suspense-utils.js",
    "content": "import React, { Component, lazy } from 'preact/compat';\nimport { vi } from 'vitest';\n\nconst h = React.createElement;\n\n/**\n * Create a Lazy component whose promise is controlled by by the test. This\n * function returns 3 values: The Lazy component to render, a `resolve`\n * function, and a `reject` function. Call `resolve` with the component the Lazy\n * component should resolve with. Call `reject` with the error the Lazy\n * component should reject with\n *\n * @example\n * // 1. Create and render the Lazy component\n * const [Lazy, resolve] = createLazy();\n * render(\n * \t<Suspense fallback={<div>Suspended...</div>}>\n * \t\t<Lazy />\n * \t</Suspense>,\n * \tscratch\n * );\n * rerender(); // Rerender is required so the fallback is displayed\n * expect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n *\n * // 2. Resolve the Lazy with a new component to render\n * return resolve(() => <div>Hello</div>).then(() => {\n * \trerender();\n * \texpect(scratch.innerHTML).to.equal(`<div>Hello</div>`);\n * });\n *\n * @typedef {import('../../../src').ComponentType<any>} ComponentType\n * @returns {[typeof Component, (c: ComponentType) => Promise<void>, (e: Error) => Promise<void>]}\n */\nexport function createLazy() {\n\t/** @type {(c: ComponentType) => Promise<void>} */\n\tlet resolver, rejecter;\n\tconst Lazy = lazy(() => {\n\t\tlet promise = new Promise((resolve, reject) => {\n\t\t\tresolver = c => {\n\t\t\t\tresolve({ default: c });\n\t\t\t\treturn promise;\n\t\t\t};\n\n\t\t\trejecter = e => {\n\t\t\t\treject(e);\n\t\t\t\treturn promise;\n\t\t\t};\n\t\t});\n\n\t\treturn promise;\n\t});\n\n\treturn [Lazy, c => resolver(c), e => rejecter(e)];\n}\n\n/**\n * Returns a Component and a function (named `suspend`) that will suspend the component when called.\n * `suspend` will return two functions, `resolve` and `reject`. Call `resolve` with a Component the\n * suspended component should resume with or reject with the Error the suspended component should\n * reject with\n *\n * @example\n * // 1. Create a suspender with initial children (argument to createSuspender) and render it\n * const [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n * render(\n * \t<Suspense fallback={<div>Suspended...</div>}>\n * \t\t<Suspender />\n * \t</Suspense>,\n * \tscratch\n * );\n * expect(scratch.innerHTML).to.eql(`div>Hello</div>`);\n *\n * // 2. Cause the component to suspend and rerender the update (i.e. the fallback)\n * const [resolve] = suspend();\n * rerender();\n * expect(scratch.innerHTML).to.eql(`div>Suspended...</div>`);\n *\n * // 3. Resolve the suspended component with a new component and rerender\n * return resolve(() => <div>Hello2</div>).then(() => {\n * \trerender();\n * \texpect(scratch.innerHTML).to.eql(`div>Hello2</div>`);\n * });\n *\n * @typedef {Component<{}, any>} Suspender\n * @typedef {[(c: ComponentType) => Promise<void>, (error: Error) => Promise<void>]} Resolvers\n * @param {ComponentType} DefaultComponent\n * @returns {[typeof Suspender, () => Resolvers]}\n */\nexport function createSuspender(DefaultComponent) {\n\t/** @type {(lazy: typeof Component) => void} */\n\tlet renderLazy;\n\tclass Suspender extends Component {\n\t\tconstructor(props, context) {\n\t\t\tsuper(props, context);\n\t\t\tthis.state = { Lazy: null };\n\n\t\t\trenderLazy = Lazy => this.setState({ Lazy });\n\t\t}\n\n\t\trender(props, state) {\n\t\t\treturn state.Lazy ? h(state.Lazy, props) : h(DefaultComponent, props);\n\t\t}\n\t}\n\n\tvi.spyOn(Suspender.prototype, 'render');\n\n\t/**\n\t * @returns {Resolvers}\n\t */\n\tfunction suspend() {\n\t\tconst [Lazy, resolve, reject] = createLazy();\n\t\trenderLazy(Lazy);\n\t\treturn [resolve, reject];\n\t}\n\n\treturn [Suspender, suspend];\n}\n\n/**\n * @returns {[() => any, (data: any) => Promise<any>, (error: Error) => Promise<any>]}\n */\nexport function createSuspenseLoader() {\n\t/** @type {(data: any) => Promise<any>} */\n\tlet resolver;\n\t/** @type {(error: Error) => Promise<any>} */\n\tlet rejecter;\n\t/** @type {any} */\n\tlet data = null;\n\t/** @type {Error} */\n\tlet error = null;\n\n\t/** @type {Promise<any>} */\n\tlet promise = new Promise((resolve, reject) => {\n\t\tresolver = result => {\n\t\t\tdata = result;\n\t\t\tresolve(result);\n\t\t\treturn promise;\n\t\t};\n\n\t\trejecter = e => {\n\t\t\terror = e;\n\t\t\treject(e);\n\t\t\treturn promise;\n\t\t};\n\t});\n\n\tfunction useSuspenseLoader() {\n\t\tif (error) {\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (!data) {\n\t\t\tthrow promise;\n\t\t}\n\n\t\treturn data;\n\t}\n\n\treturn [useSuspenseLoader, resolver, rejecter];\n}\n"
  },
  {
    "path": "compat/test/browser/suspense.test.jsx",
    "content": "import { act, setupRerender } from 'preact/test-utils';\nimport React, {\n\tcreateElement,\n\trender,\n\tComponent,\n\tSuspense,\n\tlazy,\n\tFragment,\n\tcreateContext,\n\tuseState,\n\tuseEffect,\n\tuseLayoutEffect,\n\tmemo\n} from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { createLazy, createSuspender } from './suspense-utils';\nimport { vi } from 'vitest';\n\nconst h = React.createElement;\n/* eslint-env browser */\n\nclass Catcher extends Component {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = { error: false };\n\t}\n\n\tcomponentDidCatch(e) {\n\t\tif (e.then) {\n\t\t\tthis.setState({ error: { message: '{Promise}' } });\n\t\t} else {\n\t\t\tthis.setState({ error: e });\n\t\t}\n\t}\n\n\trender(props, state) {\n\t\treturn state.error ? (\n\t\t\t<div>Catcher did catch: {state.error.message}</div>\n\t\t) : (\n\t\t\tprops.children\n\t\t);\n\t}\n}\n\ndescribe('suspense', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch,\n\t\trerender,\n\t\tunhandledEvents = [];\n\n\tfunction onUnhandledRejection(event) {\n\t\tunhandledEvents.push(event);\n\t}\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\n\t\tunhandledEvents = [];\n\t\tif ('onunhandledrejection' in window) {\n\t\t\twindow.addEventListener('unhandledrejection', onUnhandledRejection);\n\t\t}\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\n\t\tif ('onunhandledrejection' in window) {\n\t\t\twindow.removeEventListener('unhandledrejection', onUnhandledRejection);\n\n\t\t\tif (unhandledEvents.length) {\n\t\t\t\tthrow unhandledEvents[0].reason;\n\t\t\t}\n\t\t}\n\t});\n\n\tit('should support lazy', () => {\n\t\tconst LazyComp = ({ name }) => <div>Hello from {name}</div>;\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tconst Lazy = lazy(() => {\n\t\t\tconst p = new Promise(res => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\tres({ default: LazyComp });\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn p;\n\t\t});\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Lazy name=\"LazyComp\" />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t); // Render initial state\n\t\trerender(); // Re-render with fallback cuz lazy threw\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>Hello from LazyComp</div>`);\n\t\t});\n\t});\n\n\tit('should handle lazy component that rejects without returning a component', async () => {\n\t\tconst errorSpy = vi.fn();\n\t\tlet renderCount = 0;\n\n\t\tlet resolve;\n\t\tfunction fakeImport() {\n\t\t\tconst p = new Promise((_, reject) => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\treject(new Error('import failed'));\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn p;\n\t\t}\n\n\t\tconst SomeComponent = lazy(() =>\n\t\t\tfakeImport().catch(e => {\n\t\t\t\tconsole.log('caught', e);\n\t\t\t\terrorSpy(e);\n\t\t\t})\n\t\t);\n\n\t\tconst App = () => {\n\t\t\trenderCount++;\n\t\t\tif (renderCount > 5) {\n\t\t\t\tthrow new Error('Infinite loop detected!');\n\t\t\t}\n\n\t\t\tconsole.log('RENDER COUNT', renderCount);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Suspense fallback={<div>loading</div>}>\n\t\t\t\t\t\t<SomeComponent />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.contain('loading');\n\n\t\tconst assert = () => {\n\t\t\trerender();\n\n\t\t\texpect(scratch.innerHTML).to.contain('<div></div>');\n\t\t\texpect(errorSpy).toHaveBeenCalledOnce;\n\t\t};\n\n\t\tresolve().then(assert).catch(assert);\n\t});\n\n\tit('should reset hooks of components', () => {\n\t\t/** @type {(v) => void} */\n\t\tlet set;\n\t\tconst LazyComp = ({ name }) => <div>Hello from {name}</div>;\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tconst Lazy = lazy(() => {\n\t\t\tconst p = new Promise(res => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\tres({ default: LazyComp });\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn p;\n\t\t});\n\n\t\tconst Parent = ({ children }) => {\n\t\t\tconst [state, setState] = useState(false);\n\t\t\tset = setState;\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>hi</p>\n\t\t\t\t\t{state && children}\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Parent>\n\t\t\t\t\t<Lazy name=\"LazyComp\" />\n\t\t\t\t</Parent>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.eql(`<div><p>hi</p></div>`);\n\n\t\tset(true);\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql('<div>Suspended...</div>');\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div><p>hi</p></div>`);\n\t\t});\n\t});\n\n\tit('should call effect cleanups', () => {\n\t\t/** @type {(v) => void} */\n\t\tlet set;\n\t\tconst effectSpy = vi.fn();\n\t\tconst layoutEffectSpy = vi.fn();\n\t\tconst LazyComp = ({ name }) => <div>Hello from {name}</div>;\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tconst Lazy = lazy(() => {\n\t\t\tconst p = new Promise(res => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\tres({ default: LazyComp });\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn p;\n\t\t});\n\n\t\tconst Parent = ({ children }) => {\n\t\t\tconst [state, setState] = useState(false);\n\t\t\tset = setState;\n\t\t\tuseEffect(() => {\n\t\t\t\treturn () => {\n\t\t\t\t\teffectSpy();\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\treturn () => {\n\t\t\t\t\tlayoutEffectSpy();\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\treturn state ? (\n\t\t\t\t<div>{children}</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<p>hi</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Parent>\n\t\t\t\t\t<Lazy name=\"LazyComp\" />\n\t\t\t\t</Parent>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\tset(true);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>Suspended...</div>');\n\t\texpect(effectSpy).toHaveBeenCalledOnce();\n\t\texpect(layoutEffectSpy).toHaveBeenCalledOnce();\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\t\t\texpect(effectSpy).toHaveBeenCalledOnce();\n\t\t\texpect(layoutEffectSpy).toHaveBeenCalledOnce();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div><p>hi</p></div>`);\n\t\t});\n\t});\n\n\tit('should support a call to setState before rendering the fallback', () => {\n\t\tconst LazyComp = ({ name }) => <div>Hello from {name}</div>;\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tconst Lazy = lazy(() => {\n\t\t\tconst p = new Promise(res => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\tres({ default: LazyComp });\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn p;\n\t\t});\n\n\t\t/** @type {(Object) => void} */\n\t\tlet setState;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = {};\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t\t\t\t<Lazy name=\"LazyComp\" />\n\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch); // Render initial state\n\n\t\tsetState({ foo: 'bar' });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>Hello from LazyComp</div>`);\n\t\t});\n\t});\n\n\tit('lazy should forward refs', () => {\n\t\tconst LazyComp = props => <div ref={props.ref} />;\n\t\tlet ref = {};\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tconst Lazy = lazy(() => {\n\t\t\tconst p = new Promise(res => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\tres({ default: LazyComp });\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn p;\n\t\t});\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Lazy ref={ref} />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\t\t\texpect(ref.current).to.equal(scratch.firstChild);\n\t\t});\n\t});\n\n\tit('should not duplicate DOM when suspending while rendering', () => {\n\t\tscratch.innerHTML = '<div>Hello</div>';\n\n\t\tconst [Lazy, resolve] = createLazy();\n\t\trender(\n\t\t\t<Suspense>\n\t\t\t\t<Lazy />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Flush rerender queue to mimic what preact will really do\n\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\treturn resolve(() => <div>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\t});\n\t});\n\n\tit('should suspend when a promise is thrown', () => {\n\t\tclass ClassWrapper extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div id=\"class-wrapper\">{props.children}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst FuncWrapper = props => <div id=\"func-wrapper\">{props.children}</div>;\n\n\t\tconst [Suspender, suspend] = createSuspender(() => (\n\t\t\t<div id=\"initial-contents\">Hello</div>\n\t\t));\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<ClassWrapper>\n\t\t\t\t\t<FuncWrapper>\n\t\t\t\t\t\t<Suspender />\n\t\t\t\t\t</FuncWrapper>\n\t\t\t\t</ClassWrapper>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div id=\"class-wrapper\"><div id=\"func-wrapper\"><div id=\"initial-contents\">Hello</div></div></div>`\n\t\t);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <div id=\"resolved-contents\">Hello2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t`<div id=\"class-wrapper\"><div id=\"func-wrapper\"><div id=\"resolved-contents\">Hello2</div></div></div>`\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should properly call lifecycle methods of an initially suspending component', () => {\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tlet resolved = false;\n\t\tconst promise = new Promise(_resolve => {\n\t\t\tresolve = () => {\n\t\t\t\tresolved = true;\n\t\t\t\t_resolve();\n\t\t\t\treturn promise;\n\t\t\t};\n\t\t});\n\n\t\tclass LifecycleSuspender extends Component {\n\t\t\trender() {\n\t\t\t\tif (!resolved) {\n\t\t\t\t\tthrow promise;\n\t\t\t\t}\n\t\t\t\treturn <div>Lifecycle</div>;\n\t\t\t}\n\t\t\tcomponentWillMount() {}\n\t\t\tcomponentDidMount() {}\n\t\t\tcomponentDidUpdate() {}\n\t\t\tcomponentWillUnmount() {}\n\t\t}\n\n\t\tconst lifecycles = LifecycleSuspender.prototype;\n\t\tvi.spyOn(lifecycles, 'componentWillMount');\n\t\tvi.spyOn(lifecycles, 'componentDidMount');\n\t\tvi.spyOn(lifecycles, 'componentDidUpdate');\n\t\tvi.spyOn(lifecycles, 'componentWillUnmount');\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<LifecycleSuspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(``);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentDidUpdate).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentDidUpdate).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>Lifecycle</div>`);\n\n\t\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\t\t// TODO: This is unexpected. See TODO in next test regarding this and preactjs/preact#2098\n\t\t\texpect(lifecycles.componentDidUpdate).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tit('should properly call lifecycle methods and maintain state of a delayed suspending component', () => {\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tlet resolved = false;\n\t\tconst promise = new Promise(_resolve => {\n\t\t\tresolve = () => {\n\t\t\t\tresolved = true;\n\t\t\t\t_resolve();\n\t\t\t\treturn promise;\n\t\t\t};\n\t\t});\n\n\t\tclass LifecycleSuspender extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { count: 0 };\n\n\t\t\t\tincrement = () => this.setState(({ count }) => ({ count: count + 1 }));\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tif (this.state.count == 2 && !resolved) {\n\t\t\t\t\tthrow promise;\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<p>Count: {this.state.count}</p>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t\tcomponentWillMount() {}\n\t\t\tcomponentDidMount() {}\n\t\t\tcomponentWillUnmount() {}\n\t\t\tcomponentDidUpdate() {}\n\t\t}\n\n\t\tconst lifecycles = LifecycleSuspender.prototype;\n\t\tvi.spyOn(lifecycles, 'componentWillMount');\n\t\tvi.spyOn(lifecycles, 'componentDidMount');\n\t\tvi.spyOn(lifecycles, 'componentDidUpdate');\n\t\tvi.spyOn(lifecycles, 'componentWillUnmount');\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<LifecycleSuspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<p>Count: 0</p>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidUpdate).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<p>Count: 1</p>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidUpdate).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidUpdate).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\treturn resolve().then(() => {\n\t\t\trerender();\n\n\t\t\texpect(scratch.innerHTML).to.eql(`<p>Count: 2</p>`);\n\t\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\t\t// TODO: This is called thrice since the cDU queued up after the second\n\t\t\t// increment is never cleared once the component suspends. So when it\n\t\t\t// resumes and the component is rerendered, we queue up another cDU so\n\t\t\t// cDU is called an extra time.\n\t\t\texpect(lifecycles.componentDidUpdate).toHaveBeenCalledTimes(3);\n\t\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tit('should not call lifecycle methods when a sibling suspends', () => {\n\t\tclass LifecycleLogger extends Component {\n\t\t\trender() {\n\t\t\t\treturn <div>Lifecycle</div>;\n\t\t\t}\n\t\t\tcomponentWillMount() {}\n\t\t\tcomponentDidMount() {}\n\t\t\tcomponentDidUpdate() {}\n\t\t\tcomponentWillUnmount() {}\n\t\t}\n\n\t\tconst lifecycles = LifecycleLogger.prototype;\n\t\tvi.spyOn(lifecycles, 'componentWillMount');\n\t\tvi.spyOn(lifecycles, 'componentDidMount');\n\t\tvi.spyOn(lifecycles, 'componentDidUpdate');\n\t\tvi.spyOn(lifecycles, 'componentWillUnmount');\n\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Suspender />\n\t\t\t\t<LifecycleLogger />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspense</div><div>Lifecycle</div>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidUpdate).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\tconst [resolve] = suspend();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidUpdate).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\treturn resolve(() => <div>Suspense 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t`<div>Suspense 2</div><div>Lifecycle</div>`\n\t\t\t);\n\n\t\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentDidUpdate).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tit(\"should call fallback's lifecycle methods when suspending\", () => {\n\t\tclass LifecycleLogger extends Component {\n\t\t\trender() {\n\t\t\t\treturn <div>Lifecycle</div>;\n\t\t\t}\n\t\t\tcomponentWillMount() {}\n\t\t\tcomponentDidMount() {}\n\t\t\tcomponentWillUnmount() {}\n\t\t}\n\n\t\tconst lifecycles = LifecycleLogger.prototype;\n\t\tvi.spyOn(lifecycles, 'componentWillMount');\n\t\tvi.spyOn(lifecycles, 'componentDidMount');\n\t\tvi.spyOn(lifecycles, 'componentWillUnmount');\n\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<LifecycleLogger />}>\n\t\t\t\t<Suspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspense</div>`);\n\t\texpect(lifecycles.componentWillMount).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentDidMount).not.toHaveBeenCalled();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\tconst [resolve] = suspend();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Lifecycle</div>`);\n\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\texpect(lifecycles.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\treturn resolve(() => <div>Suspense 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>Suspense 2</div>`);\n\n\t\t\texpect(lifecycles.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(lifecycles.componentWillUnmount).toHaveBeenCalledOnce();\n\t\t});\n\t});\n\n\tit('should keep state of siblings when suspending', () => {\n\t\t/** @type {(state: { s: string }) => void} */\n\t\tlet setState;\n\t\tclass Stateful extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t\tthis.state = { s: 'initial' };\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\treturn <div>Stateful: {state.s}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Suspender />\n\t\t\t\t<Stateful />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspense</div><div>Stateful: initial</div>`\n\t\t);\n\n\t\tsetState({ s: 'first' });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspense</div><div>Stateful: first</div>`\n\t\t);\n\n\t\tconst [resolve] = suspend();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <div>Suspense 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t`<div>Suspense 2</div><div>Stateful: first</div>`\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should allow children to update state while suspending', () => {\n\t\t/** @type {(state: { s: string }) => void} */\n\t\tlet setState;\n\t\tclass Stateful extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t\tthis.state = { s: 'initial' };\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\treturn <div>Stateful: {state.s}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Suspender />\n\t\t\t\t<Stateful />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspense</div><div>Stateful: initial</div>`\n\t\t);\n\n\t\tsetState({ s: 'first' });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspense</div><div>Stateful: first</div>`\n\t\t);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\tsetState({ s: 'second' });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <div>Suspense 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t`<div>Suspense 2</div><div>Stateful: second</div>`\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should allow siblings of Suspense to update state while suspending', () => {\n\t\t/** @type {(state: { s: string }) => void} */\n\t\tlet setState;\n\t\tclass Stateful extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t\tthis.state = { s: 'initial' };\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\treturn <div>Stateful: {state.s}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspense</div>);\n\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t\t<Suspender />\n\t\t\t\t</Suspense>\n\t\t\t\t<Stateful />\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspense</div><div>Stateful: initial</div>`\n\t\t);\n\n\t\tsetState({ s: 'first' });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspense</div><div>Stateful: first</div>`\n\t\t);\n\n\t\tconst [resolve] = suspend();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspended...</div><div>Stateful: first</div>`\n\t\t);\n\n\t\tsetState({ s: 'second' });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Suspended...</div><div>Stateful: second</div>`\n\t\t);\n\n\t\treturn resolve(() => <div>Suspense 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t`<div>Suspense 2</div><div>Stateful: second</div>`\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should suspend with custom error boundary', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => (\n\t\t\t<div>within error boundary</div>\n\t\t));\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Catcher>\n\t\t\t\t\t<Suspender />\n\t\t\t\t</Catcher>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>within error boundary</div>`);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <div>within error boundary 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>within error boundary 2</div>`);\n\t\t});\n\t});\n\n\tit('should allow multiple sibling children to suspend', () => {\n\t\tconst [Suspender1, suspend1] = createSuspender(() => (\n\t\t\t<div>Hello first</div>\n\t\t));\n\t\tconst [Suspender2, suspend2] = createSuspender(() => (\n\t\t\t<div>Hello second</div>\n\t\t));\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Catcher>\n\t\t\t\t\t<Suspender1 />\n\t\t\t\t\t<Suspender2 />\n\t\t\t\t</Catcher>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Hello first</div><div>Hello second</div>`\n\t\t);\n\t\texpect(Suspender1.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(Suspender2.prototype.render).toHaveBeenCalledOnce();\n\n\t\tconst [resolve1] = suspend1();\n\t\tconst [resolve2] = suspend2();\n\t\texpect(Suspender1.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(Suspender2.prototype.render).toHaveBeenCalledOnce();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\texpect(Suspender1.prototype.render).toHaveBeenCalledTimes(2);\n\t\texpect(Suspender2.prototype.render).toHaveBeenCalledTimes(2);\n\n\t\treturn resolve1(() => <div>Hello first 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\t\texpect(Suspender1.prototype.render).toHaveBeenCalledTimes(2);\n\t\t\texpect(Suspender2.prototype.render).toHaveBeenCalledTimes(2);\n\n\t\t\treturn resolve2(() => <div>Hello second 2</div>).then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t\t`<div>Hello first 2</div><div>Hello second 2</div>`\n\t\t\t\t);\n\t\t\t\texpect(Suspender1.prototype.render).toHaveBeenCalledTimes(3);\n\t\t\t\texpect(Suspender2.prototype.render).toHaveBeenCalledTimes(3);\n\t\t\t});\n\t\t});\n\t});\n\n\tit('should call multiple nested sibling suspending components render in one go', () => {\n\t\tconst [Suspender1, suspend1] = createSuspender(() => (\n\t\t\t<div>Hello first</div>\n\t\t));\n\t\tconst [Suspender2, suspend2] = createSuspender(() => (\n\t\t\t<div>Hello second</div>\n\t\t));\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Catcher>\n\t\t\t\t\t<Suspender1 />\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Suspender2 />\n\t\t\t\t\t</div>\n\t\t\t\t</Catcher>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>Hello first</div><div><div>Hello second</div></div>`\n\t\t);\n\t\texpect(Suspender1.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(Suspender2.prototype.render).toHaveBeenCalledOnce();\n\n\t\tconst [resolve1] = suspend1();\n\t\tconst [resolve2] = suspend2();\n\t\texpect(Suspender1.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(Suspender2.prototype.render).toHaveBeenCalledOnce();\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\texpect(Suspender1.prototype.render).toHaveBeenCalledTimes(2);\n\t\texpect(Suspender2.prototype.render).toHaveBeenCalledTimes(2);\n\n\t\treturn resolve1(() => <div>Hello first 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\t\t\texpect(Suspender1.prototype.render).toHaveBeenCalledTimes(2);\n\t\t\texpect(Suspender2.prototype.render).toHaveBeenCalledTimes(2);\n\n\t\t\treturn resolve2(() => <div>Hello second 2</div>).then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t\t`<div>Hello first 2</div><div><div>Hello second 2</div></div>`\n\t\t\t\t);\n\t\t\t\texpect(Suspender1.prototype.render).toHaveBeenCalledTimes(3);\n\t\t\t\texpect(Suspender2.prototype.render).toHaveBeenCalledTimes(3);\n\t\t\t});\n\t\t});\n\t});\n\n\tit('should support text directly under Suspense', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\tText\n\t\t\t\t{/* Adding a <div> here will make things work... */}\n\t\t\t\t<Suspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`Text<div>Hello</div>`);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <div>Hello 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`Text<div>Hello 2</div>`);\n\t\t});\n\t});\n\n\tit('should support to change DOM tag directly under suspense', () => {\n\t\t/** @type {(state: {tag: string}) => void} */\n\t\tlet setState;\n\t\tclass StatefulComp extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t\tthis.state = {\n\t\t\t\t\ttag: props.defaultTag\n\t\t\t\t};\n\t\t\t}\n\t\t\trender(props, { tag: Tag }) {\n\t\t\t\treturn <Tag>Stateful</Tag>;\n\t\t\t}\n\t\t}\n\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<StatefulComp defaultTag=\"div\" />\n\t\t\t\t<Suspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Stateful</div><div>Hello</div>`);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\tsetState({ tag: 'article' });\n\n\t\treturn resolve(() => <div>Hello 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t`<article>Stateful</article><div>Hello 2</div>`\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should only suspend the most inner Suspend', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended... 1</div>}>\n\t\t\t\tNot suspended...\n\t\t\t\t<Suspense fallback={<div>Suspended... 2</div>}>\n\t\t\t\t\t<Catcher>\n\t\t\t\t\t\t<Suspender />\n\t\t\t\t\t</Catcher>\n\t\t\t\t</Suspense>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`Not suspended...<div>Hello</div>`);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`Not suspended...<div>Suspended... 2</div>`\n\t\t);\n\n\t\treturn resolve(() => <div>Hello 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`Not suspended...<div>Hello 2</div>`);\n\t\t});\n\t});\n\n\tit('should throw when missing Suspense', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n\n\t\trender(\n\t\t\t<Catcher>\n\t\t\t\t<Suspender />\n\t\t\t</Catcher>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(`<div>Hello</div>`);\n\n\t\tsuspend();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(`<div>Catcher did catch: {Promise}</div>`);\n\t});\n\n\tit(\"should throw when lazy's loader throws\", () => {\n\t\t/** @type {() => Promise<any>} */\n\t\tlet reject;\n\t\tconst ThrowingLazy = lazy(() => {\n\t\t\tconst prom = new Promise((res, rej) => {\n\t\t\t\treject = () => {\n\t\t\t\t\trej(new Error(\"Thrown in lazy's loader...\"));\n\t\t\t\t\treturn prom;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn prom;\n\t\t});\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Catcher>\n\t\t\t\t\t<ThrowingLazy />\n\t\t\t\t</Catcher>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn reject().then(\n\t\t\t() => {\n\t\t\t\texpect.fail('Suspended promises resolved instead of rejected.');\n\t\t\t},\n\t\t\t() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t\t`<div>Catcher did catch: Thrown in lazy's loader...</div>`\n\t\t\t\t);\n\t\t\t}\n\t\t);\n\t});\n\n\tit('should support null fallback', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n\n\t\trender(\n\t\t\t<div id=\"wrapper\">\n\t\t\t\t<Suspense fallback={null}>\n\t\t\t\t\t<div id=\"inner\">\n\t\t\t\t\t\t<Suspender />\n\t\t\t\t\t</div>\n\t\t\t\t</Suspense>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div id=\"wrapper\"><div id=\"inner\"><div>Hello</div></div></div>`\n\t\t);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(`<div id=\"wrapper\"></div>`);\n\n\t\treturn resolve(() => <div>Hello2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t`<div id=\"wrapper\"><div id=\"inner\"><div>Hello2</div></div></div>`\n\t\t\t);\n\t\t});\n\t});\n\n\tit('should support suspending multiple times', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => (\n\t\t\t<div>initial render</div>\n\t\t));\n\t\tconst Loading = () => <div>Suspended...</div>;\n\n\t\trender(\n\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t<Suspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>initial render</div>`);\n\n\t\tlet [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <div>Hello1</div>)\n\t\t\t.then(() => {\n\t\t\t\t// Rerender promise resolution\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(`<div>Hello1</div>`);\n\n\t\t\t\t// suspend again\n\t\t\t\t[resolve] = suspend();\n\t\t\t\trerender();\n\n\t\t\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\t\t\treturn resolve(() => <div>Hello2</div>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\t// Rerender promise resolution\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(`<div>Hello2</div>`);\n\t\t\t});\n\t});\n\n\tit(\"should correctly render when a suspended component's child also suspends\", () => {\n\t\tconst [Suspender1, suspend1] = createSuspender(() => <div>Hello1</div>);\n\t\tconst [LazyChild, resolveChild] = createLazy();\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Suspender1 />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(`<div>Hello1</div>`);\n\n\t\tlet [resolve1] = suspend1();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\treturn resolve1(() => <LazyChild />)\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\t\t\treturn resolveChild(() => <div>All done!</div>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal('<div>All done!</div>');\n\t\t\t});\n\t});\n\n\tit('should correctly render nested Suspense components', () => {\n\t\t// Inspired by the nested-suspense demo from #1865\n\t\t// TODO: Explore writing a test that varies the loading orders\n\n\t\tconst [Lazy1, resolve1] = createLazy();\n\t\tconst [Lazy2, resolve2] = createLazy();\n\t\tconst [Lazy3, resolve3] = createLazy();\n\n\t\tconst Loading = () => <div>Suspended...</div>;\n\t\tconst loadingHtml = `<div>Suspended...</div>`;\n\n\t\trender(\n\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t<Lazy1 />\n\t\t\t\t<div>\n\t\t\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t\t\t<Lazy2 />\n\t\t\t\t\t</Suspense>\n\t\t\t\t\t<Lazy3 />\n\t\t\t\t</div>\n\t\t\t\t<b>4</b>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender(); // Rerender with the fallback HTML\n\n\t\texpect(scratch.innerHTML).to.equal(loadingHtml);\n\n\t\treturn resolve1(() => <b>1</b>)\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(loadingHtml);\n\n\t\t\t\treturn resolve3(() => <b>3</b>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t`<b>1</b><div>${loadingHtml}<b>3</b></div><b>4</b>`\n\t\t\t\t);\n\n\t\t\t\treturn resolve2(() => <b>2</b>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t`<b>1</b><div><b>2</b><b>3</b></div><b>4</b>`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tit('should correctly render nested Suspense components without intermediate DOM #2747', () => {\n\t\tconst [ProfileDetails, resolveDetails] = createLazy();\n\t\tconst [ProfileTimeline, resolveTimeline] = createLazy();\n\n\t\tfunction ProfilePage() {\n\t\t\treturn (\n\t\t\t\t<Suspense fallback={<h1>Loading profile...</h1>}>\n\t\t\t\t\t<ProfileDetails />\n\t\t\t\t\t<Suspense fallback={<h2>Loading posts...</h2>}>\n\t\t\t\t\t\t<ProfileTimeline />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</Suspense>\n\t\t\t);\n\t\t}\n\n\t\trender(<ProfilePage />, scratch);\n\t\trerender(); // Render fallback\n\n\t\texpect(scratch.innerHTML).to.equal('<h1>Loading profile...</h1>');\n\n\t\treturn resolveDetails(() => <h1>Ringo Starr</h1>)\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t'<h1>Ringo Starr</h1><h2>Loading posts...</h2>'\n\t\t\t\t);\n\n\t\t\t\treturn resolveTimeline(() => <p>Timeline details</p>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t'<h1>Ringo Starr</h1><p>Timeline details</p>'\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tit('should correctly render Suspense components inside Fragments', () => {\n\t\t// Issue #2106.\n\n\t\tconst [Lazy1, resolve1] = createLazy();\n\t\tconst [Lazy2, resolve2] = createLazy();\n\t\tconst [Lazy3, resolve3] = createLazy();\n\n\t\tconst Loading = () => <div>Suspended...</div>;\n\t\tconst loadingHtml = `<div>Suspended...</div>`;\n\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t\t<Lazy1 />\n\t\t\t\t</Suspense>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t\t\t<Lazy2 />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</Fragment>\n\t\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t\t<Lazy3 />\n\t\t\t\t</Suspense>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`${loadingHtml}${loadingHtml}${loadingHtml}`\n\t\t);\n\n\t\treturn resolve2(() => <span>2</span>)\n\t\t\t.then(() => {\n\t\t\t\treturn resolve1(() => <span>1</span>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t\t`<span>1</span><span>2</span>${loadingHtml}`\n\t\t\t\t);\n\t\t\t\treturn resolve3(() => <span>3</span>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t\t\t`<span>1</span><span>2</span><span>3</span>`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tit('should not render any of the children if one child suspends', () => {\n\t\tconst [Lazy, resolve] = createLazy();\n\n\t\tconst Loading = () => <div>Suspended...</div>;\n\t\tconst loadingHtml = `<div>Suspended...</div>`;\n\n\t\trender(\n\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t<Lazy />\n\t\t\t\t<div>World</div>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(loadingHtml);\n\n\t\treturn resolve(() => <div>Hello</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(`<div>Hello</div><div>World</div>`);\n\t\t});\n\t});\n\n\tit('should render correctly when multiple children suspend with the same promise', () => {\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tlet resolved = false;\n\t\tconst promise = new Promise(_resolve => {\n\t\t\tresolve = () => {\n\t\t\t\tresolved = true;\n\t\t\t\t_resolve();\n\t\t\t\treturn promise;\n\t\t\t};\n\t\t});\n\n\t\tconst Child = props => {\n\t\t\tif (!resolved) {\n\t\t\t\tthrow promise;\n\t\t\t}\n\t\t\treturn props.children;\n\t\t};\n\n\t\tconst Loading = () => <div>Suspended...</div>;\n\t\tconst loadingHtml = `<div>Suspended...</div>`;\n\n\t\trender(\n\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t<Child>\n\t\t\t\t\t<div>A</div>\n\t\t\t\t</Child>\n\t\t\t\t<Child>\n\t\t\t\t\t<div>B</div>\n\t\t\t\t</Child>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(loadingHtml);\n\n\t\treturn resolve().then(() => {\n\t\t\tresolved = true;\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(`<div>A</div><div>B</div>`);\n\t\t});\n\t});\n\n\tit('should un-suspend when suspender unmounts', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspender</div>);\n\n\t\t/** @type {() => void} */\n\t\tlet hide;\n\n\t\tclass Conditional extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true };\n\n\t\t\t\thide = () => {\n\t\t\t\t\tthis.setState({ show: false });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(props, { show }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\tconditional {show ? 'show' : 'hide'}\n\t\t\t\t\t\t{show && <Suspender />}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Conditional />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div>conditional show<div>Suspender</div></div>`\n\t\t);\n\t\texpect(Suspender.prototype.render).toHaveBeenCalledOnce();\n\n\t\tsuspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\thide();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>conditional hide</div>`);\n\t});\n\n\tit('should allow suspended multiple times', async () => {\n\t\tconst [Suspender1, suspend1] = createSuspender(() => (\n\t\t\t<div>Suspender 1</div>\n\t\t));\n\t\tconst [Suspender2, suspend2] = createSuspender(() => (\n\t\t\t<div>Suspender 2</div>\n\t\t));\n\n\t\t/** @type {() => void} */\n\t\tlet hide, resolve;\n\n\t\tclass Conditional extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true };\n\n\t\t\t\thide = () => {\n\t\t\t\t\tthis.setState({ show: false });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(props, { show }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\tconditional {show ? 'show' : 'hide'}\n\t\t\t\t\t\t{show && (\n\t\t\t\t\t\t\t<Suspense fallback=\"Suspended\">\n\t\t\t\t\t\t\t\t<Suspender1 />\n\t\t\t\t\t\t\t\t<Suspender2 />\n\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Conditional />, scratch);\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Suspender 1</div><div>Suspender 2</div></div>'\n\t\t);\n\n\t\tresolve = suspend1()[0];\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional showSuspended</div>');\n\n\t\tawait resolve(() => <div>Done 1</div>);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Done 1</div><div>Suspender 2</div></div>'\n\t\t);\n\n\t\tresolve = suspend2()[0];\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional showSuspended</div>');\n\n\t\tawait resolve(() => <div>Done 2</div>);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Done 1</div><div>Done 2</div></div>'\n\t\t);\n\n\t\thide();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional hide</div>');\n\t});\n\n\tit('should allow same component to be suspended multiple times', async () => {\n\t\tconst cache = { 1: true };\n\t\tfunction Lazy({ value }) {\n\t\t\tif (!cache[value]) {\n\t\t\t\tthrow new Promise(resolve => {\n\t\t\t\t\tcache[value] = resolve;\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn <div>{`Lazy ${value}`}</div>;\n\t\t}\n\n\t\t/** @type {() => void} */\n\t\tlet hide,\n\t\t\t/** @type {(v) => void} */\n\t\t\tsetValue;\n\n\t\tclass Conditional extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true, value: '1' };\n\n\t\t\t\thide = () => {\n\t\t\t\t\tthis.setState({ show: false });\n\t\t\t\t};\n\t\t\t\tsetValue = value => {\n\t\t\t\t\tthis.setState({ value });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(props, { show, value }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\tconditional {show ? 'show' : 'hide'}\n\t\t\t\t\t\t{show && (\n\t\t\t\t\t\t\t<Suspense fallback=\"Suspended\">\n\t\t\t\t\t\t\t\t<Lazy value={value} />\n\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Conditional />, scratch);\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Lazy 1</div></div>'\n\t\t);\n\n\t\tsetValue('2');\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional showSuspended</div>');\n\n\t\tawait cache[2]();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Lazy 2</div></div>'\n\t\t);\n\n\t\tsetValue('3');\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional showSuspended</div>');\n\n\t\tawait cache[3]();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Lazy 3</div></div>'\n\t\t);\n\n\t\thide();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional hide</div>');\n\t});\n\n\tit('should allow resolve suspense promise after unmounts', async () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspender</div>);\n\n\t\t/** @type {() => void} */\n\t\tlet hide, resolve;\n\n\t\tclass Conditional extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true };\n\n\t\t\t\thide = () => {\n\t\t\t\t\tthis.setState({ show: false });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(props, { show }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\tconditional {show ? 'show' : 'hide'}\n\t\t\t\t\t\t{show && (\n\t\t\t\t\t\t\t<Suspense fallback=\"Suspended\">\n\t\t\t\t\t\t\t\t<Suspender />\n\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Conditional />, scratch);\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<div>conditional show<div>Suspender</div></div>'\n\t\t);\n\n\t\tresolve = suspend()[0];\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional showSuspended</div>');\n\n\t\thide();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional hide</div>');\n\n\t\tawait resolve(() => <div>Done</div>);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<div>conditional hide</div>');\n\t});\n\n\tit('should support updating state while suspended', async () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Suspender</div>);\n\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\n\t\tclass Updater extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { i: 0 };\n\n\t\t\t\tincrement = () => {\n\t\t\t\t\tthis.setState(({ i }) => ({ i: i + 1 }));\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(props, { i }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\ti: {i}\n\t\t\t\t\t\t<Suspender />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Updater />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>i: 0<div>Suspender</div></div>`);\n\t\texpect(Suspender.prototype.render).toHaveBeenCalledOnce();\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\tawait resolve(() => <div>Resolved</div>);\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(`<div>i: 1<div>Resolved</div></div>`);\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(`<div>i: 2<div>Resolved</div></div>`);\n\t});\n\n\tit('should call componentWillUnmount on a suspended component', () => {\n\t\tconst cWUSpy = vi.fn();\n\n\t\t// eslint-disable-next-line react/require-render-return\n\t\tclass Suspender extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { promise: new Promise(() => {}) };\n\t\t\t\tif (typeof props.ref === 'function') {\n\t\t\t\t\tprops.ref(this);\n\t\t\t\t} else if (props.ref) {\n\t\t\t\t\tprops.ref.current = this;\n\t\t\t\t}\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tthrow this.state.promise;\n\t\t\t}\n\t\t}\n\n\t\tSuspender.prototype.componentWillUnmount = cWUSpy;\n\n\t\t/** @type {() => void} */\n\t\tlet hide;\n\n\t\tlet suspender = null;\n\t\tlet suspenderRef = s => {\n\t\t\t// skip null values as we want to keep the ref even after unmount\n\t\t\tif (s) {\n\t\t\t\tsuspender = s;\n\t\t\t}\n\t\t};\n\n\t\tclass Conditional extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true };\n\n\t\t\t\thide = () => {\n\t\t\t\t\tthis.setState({ show: false });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(props, { show }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\tconditional {show ? 'show' : 'hide'}\n\t\t\t\t\t\t{show && <Suspender ref={suspenderRef} />}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Conditional />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>conditional show</div>`);\n\t\texpect(cWUSpy).not.toHaveBeenCalled();\n\n\t\thide();\n\t\trerender();\n\n\t\texpect(cWUSpy).toHaveBeenCalledOnce();\n\t\texpect(suspender).not.to.be.undefined;\n\t\texpect(suspender).not.to.be.null;\n\t\texpect(cWUSpy.mock.contexts[0]).to.eql(suspender);\n\t\texpect(scratch.innerHTML).to.eql(`<div>conditional hide</div>`);\n\t});\n\n\tit('should support sCU=false when un-suspending', () => {\n\t\t// See #2176 #2125\n\t\tconst [Suspender, suspend] = createSuspender(() => <div>Hello</div>);\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\tText\n\t\t\t\t{/* Adding a <div> here will make things work... */}\n\t\t\t\t<Suspender />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`Text<div>Hello</div>`);\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\tSuspender.prototype.shouldComponentUpdate = () => false;\n\n\t\treturn resolve(() => <div>Hello 2</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`Text<div>Hello 2</div>`);\n\t\t});\n\t});\n\n\t// TODO: Revisit later. Consider using an \"options.commit\" plugin to detect\n\t// when a suspended component has rerendered and trigger a rerender on the\n\t// parent Suspense\n\tit.skip('should allow suspended children to update', () => {\n\t\tconst log = [];\n\t\tclass Logger extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tlog.push('construct');\n\t\t\t}\n\n\t\t\trender({ children }) {\n\t\t\t\tlog.push('render');\n\t\t\t\treturn children;\n\t\t\t}\n\t\t}\n\n\t\t/** @type {Suspender} */\n\t\tlet suspender;\n\t\tclass Suspender extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { promise: new Promise(() => {}) };\n\t\t\t\tsuspender = this;\n\t\t\t}\n\n\t\t\tunsuspend() {\n\t\t\t\tthis.setState({ promise: null });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tif (this.state.promise) {\n\t\t\t\t\tthrow this.state.promise;\n\t\t\t\t}\n\n\t\t\t\treturn <div>Suspender un-suspended</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<section>\n\t\t\t\t<Suspense fallback={<div>fallback</div>}>\n\t\t\t\t\t<Suspender />\n\t\t\t\t\t<Logger />\n\t\t\t\t</Suspense>\n\t\t\t</section>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(log).to.eql(['construct', 'render']);\n\t\texpect(scratch.innerHTML).to.eql('<section></section>');\n\n\t\t// this rerender is needed because of Suspense issuing a forceUpdate itself\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<section><div>fallback</div></section>');\n\n\t\tsuspender.unsuspend();\n\n\t\trerender();\n\n\t\texpect(log).to.eql(['construct', 'render', 'render']);\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<section><div>Suspender un-suspended</div></section>'\n\t\t);\n\t});\n\n\t// TODO: Revisit later. Consider using an \"options.commit\" plugin to detect\n\t// when a suspended component has rerendered and trigger a rerender on the\n\t// parent Suspense\n\tit.skip('should allow multiple suspended children to update', () => {\n\t\tfunction createSuspender() {\n\t\t\tlet suspender;\n\t\t\tclass Suspender extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { promise: new Promise(() => {}) };\n\t\t\t\t\tsuspender = this;\n\t\t\t\t}\n\n\t\t\t\tunsuspend(content) {\n\t\t\t\t\tthis.setState({ promise: null, content });\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tif (this.state.promise) {\n\t\t\t\t\t\tthrow this.state.promise;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this.state.content;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn [content => suspender.unsuspend(content), Suspender];\n\t\t}\n\n\t\tconst [unsuspender1, Suspender1] = createSuspender();\n\t\tconst [unsuspender2, Suspender2] = createSuspender();\n\n\t\trender(\n\t\t\t<section>\n\t\t\t\t<Suspense fallback={<div>fallback</div>}>\n\t\t\t\t\t<Suspender1 />\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Suspender2 />\n\t\t\t\t\t</div>\n\t\t\t\t</Suspense>\n\t\t\t</section>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql('<section><div></div></section>');\n\n\t\t// this rerender is needed because of Suspense issuing a forceUpdate itself\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<section><div>fallback</div></section>');\n\n\t\tunsuspender1(\n\t\t\t<>\n\t\t\t\t<div>Suspender un-suspended 1</div>\n\t\t\t\t<div>Suspender un-suspended 2</div>\n\t\t\t</>\n\t\t);\n\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<section><div>fallback</div></section>');\n\n\t\tunsuspender2(<div>Suspender 2</div>);\n\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t'<section><div>Suspender un-suspended 1</div><div>Suspender un-suspended 2</div><div><div>Suspender 2</div></div></section>'\n\t\t);\n\t});\n\n\t// TODO: Revisit later. Consider using an \"options.commit\" plugin to detect\n\t// when a suspended component has rerendered and trigger a rerender on the\n\t// parent Suspense\n\tit.skip('should allow suspended children children to update', () => {\n\t\tfunction Suspender({ promise, content }) {\n\t\t\tif (promise) {\n\t\t\t\tthrow promise;\n\t\t\t}\n\t\t\treturn content;\n\t\t}\n\n\t\t/** @type {Component} */\n\t\tlet parent;\n\t\tclass Parent extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { promise: new Promise(() => {}), condition: true };\n\t\t\t\tparent = this;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tconst { condition, promise, content } = this.state;\n\t\t\t\tif (condition) {\n\t\t\t\t\treturn <Suspender promise={promise} content={content} />;\n\t\t\t\t}\n\t\t\t\treturn <div>Parent</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<section>\n\t\t\t\t<Suspense fallback={<div>fallback</div>}>\n\t\t\t\t\t<Parent />\n\t\t\t\t</Suspense>\n\t\t\t</section>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql('<section></section>');\n\n\t\t// this rerender is needed because of Suspense issuing a forceUpdate itself\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<section><div>fallback</div></section>');\n\n\t\t// hide the <Suspender /> thus unsuspends\n\t\tparent.setState({ condition: false });\n\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.eql('<section><div>Parent</div></section>');\n\n\t\t// show the <Suspender /> thus re-suspends\n\t\tparent.setState({ condition: true });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql('<section><div>fallback</div></section>');\n\n\t\t// update state so that <Suspender /> no longer suspends\n\t\tparent.setState({ promise: null, content: <div>Content</div> });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql('<section><div>Content</div></section>');\n\n\t\t// hide the <Suspender /> again\n\t\tparent.setState({ condition: false });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql('<section><div>Parent</div></section>');\n\t});\n\n\tit('should render delayed lazy components through components using shouldComponentUpdate', () => {\n\t\tconst [Suspender1, suspend1] = createSuspender(() => <i>1</i>);\n\t\tconst [Suspender2, suspend2] = createSuspender(() => <i>2</i>);\n\n\t\tclass Blocker extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<b>\n\t\t\t\t\t\t<i>a</i>\n\t\t\t\t\t\t{props.children}\n\t\t\t\t\t\t<i>d</i>\n\t\t\t\t\t</b>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Blocker>\n\t\t\t\t\t<Suspender1 />\n\t\t\t\t\t<Suspender2 />\n\t\t\t\t</Blocker>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<b><i>a</i><i>1</i><i>2</i><i>d</i></b>'\n\t\t);\n\n\t\tconst [resolve1] = suspend1();\n\t\tconst [resolve2] = suspend2();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\treturn resolve1(() => <i>b</i>)\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\t\t\treturn resolve2(() => <i>c</i>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t'<b><i>a</i><i>b</i><i>c</i><i>d</i></b>'\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tit('should render initially lazy components through components using shouldComponentUpdate', () => {\n\t\tconst [Lazy1, resolve1] = createLazy();\n\t\tconst [Lazy2, resolve2] = createLazy();\n\n\t\tclass Blocker extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<b>\n\t\t\t\t\t\t<i>a</i>\n\t\t\t\t\t\t{props.children}\n\t\t\t\t\t\t<i>d</i>\n\t\t\t\t\t</b>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Blocker>\n\t\t\t\t\t<Lazy1 />\n\t\t\t\t\t<Lazy2 />\n\t\t\t\t</Blocker>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\treturn resolve1(() => <i>b</i>)\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\t\t\treturn resolve2(() => <i>c</i>);\n\t\t\t})\n\t\t\t.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t\t'<b><i>a</i><i>b</i><i>c</i><i>d</i></b>'\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tit('should render initially lazy components through createContext', () => {\n\t\tconst ctx = createContext(null);\n\t\tconst [Lazy, resolve] = createLazy();\n\n\t\tconst suspense = (\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<ctx.Provider value=\"123\">\n\t\t\t\t\t<ctx.Consumer>{value => <Lazy value={value} />}</ctx.Consumer>\n\t\t\t\t</ctx.Provider>\n\t\t\t</Suspense>\n\t\t);\n\n\t\trender(suspense, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(`<div>Suspended...</div>`);\n\n\t\treturn resolve(props => <div>{props.value}</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>123</div>`);\n\t\t});\n\t});\n\n\tit('should render delayed lazy components through createContext', () => {\n\t\tconst ctx = createContext(null);\n\t\tconst [Suspender, suspend] = createSuspender(({ value }) => (\n\t\t\t<span>{value}</span>\n\t\t));\n\n\t\tconst suspense = (\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<ctx.Provider value=\"123\">\n\t\t\t\t\t<ctx.Consumer>{value => <Suspender value={value} />}</ctx.Consumer>\n\t\t\t\t</ctx.Provider>\n\t\t\t</Suspense>\n\t\t);\n\n\t\trender(suspense, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<span>123</span>');\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(`<div>Suspended...</div>`);\n\n\t\treturn resolve(props => <div>{props.value}</div>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<div>123</div>`);\n\t\t});\n\t});\n\n\tit('should not crash due to suspending a component with useState', () => {\n\t\tconst [Suspender, suspend] = createSuspender(() => {\n\t\t\tconst [state] = useState('hello world');\n\t\t\treturn <p>{state}</p>;\n\t\t});\n\n\t\tconst suspense = (\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<Suspender />\n\t\t\t</Suspense>\n\t\t);\n\n\t\trender(suspense, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>hello world</p>');\n\n\t\tconst [resolve] = suspend();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(`<div>Suspended...</div>`);\n\n\t\treturn resolve(() => <p>hello new world</p>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.eql(`<p>hello new world</p>`);\n\t\t});\n\t});\n\n\tit('should not crash when suspended child updates after unmount', () => {\n\t\tlet childInstance = null;\n\t\tconst neverResolvingPromise = new Promise(() => {});\n\n\t\tclass ThrowingChild extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { suspend: false, value: 0 };\n\t\t\t\tchildInstance = this;\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (state.suspend) {\n\t\t\t\t\tthrow neverResolvingPromise;\n\t\t\t\t}\n\t\t\t\treturn <div>value:{state.value}</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<ThrowingChild />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>value:0</div>');\n\n\t\tchildInstance.setState({ suspend: true });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\trender(null, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\tchildInstance.setState({ value: 1 });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should not crash when suspended child updates after diffed unmount', () => {\n\t\tlet childInstance = null;\n\t\tconst neverResolvingPromise = new Promise(() => {});\n\n\t\tclass ThrowingChild extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { suspend: false, value: 0 };\n\t\t\t\tchildInstance = this;\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (state.suspend) {\n\t\t\t\t\tthrow neverResolvingPromise;\n\t\t\t\t}\n\t\t\t\treturn <div>value:{state.value}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst HelloWorld = () => <p>Hello world</p>;\n\n\t\tlet set;\n\t\tconst App = () => {\n\t\t\tconst [show, setShow] = useState(true);\n\t\t\tset = setShow;\n\t\t\treturn show ? (\n\t\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t\t<ThrowingChild />\n\t\t\t\t</Suspense>\n\t\t\t) : (\n\t\t\t\t<HelloWorld />\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>value:0</div>');\n\n\t\tchildInstance.setState({ suspend: true });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\tset(false);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello world</p>');\n\n\t\tchildInstance.setState({ value: 1 });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello world</p>');\n\t});\n\n\tit('should not crash when suspended child resolves after unmount', async () => {\n\t\tlet childInstance = null,\n\t\t\tres;\n\t\tconst neverResolvingPromise = new Promise(r => {\n\t\t\tres = r;\n\t\t});\n\n\t\tclass ThrowingChild extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { suspend: false, value: 0 };\n\t\t\t\tchildInstance = this;\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (state.suspend) {\n\t\t\t\t\tthrow neverResolvingPromise;\n\t\t\t\t}\n\t\t\t\treturn <div>value:{state.value}</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<ThrowingChild />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>value:0</div>');\n\n\t\tchildInstance.setState({ suspend: true });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\trender(null, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\tres();\n\t\treturn neverResolvingPromise.then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\t\t});\n\t});\n\n\tit('should not crash when suspended child resolves after diffed unmount', async () => {\n\t\tlet childInstance = null,\n\t\t\tres;\n\t\tconst neverResolvingPromise = new Promise(r => {\n\t\t\tres = r;\n\t\t});\n\n\t\tclass ThrowingChild extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { suspend: false, value: 0 };\n\t\t\t\tchildInstance = this;\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (state.suspend) {\n\t\t\t\t\tthrow neverResolvingPromise;\n\t\t\t\t}\n\t\t\t\treturn <div>value:{state.value}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst HelloWorld = () => <p>Hello world</p>;\n\n\t\tlet set;\n\t\tconst App = () => {\n\t\t\tconst [show, setShow] = useState(true);\n\t\t\tset = setShow;\n\t\t\treturn show ? (\n\t\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t\t<ThrowingChild />\n\t\t\t\t</Suspense>\n\t\t\t) : (\n\t\t\t\t<HelloWorld />\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>value:0</div>');\n\n\t\tchildInstance.setState({ suspend: true });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\tset(false);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello world</p>');\n\n\t\tres();\n\t\treturn neverResolvingPromise.then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<p>Hello world</p>');\n\t\t});\n\t});\n\n\tit('should not crash when suspense promise resolves after unmount', () => {\n\t\tlet resolve;\n\t\tconst promise = new Promise(r => {\n\t\t\tresolve = r;\n\t\t});\n\n\t\tclass ThrowingChild extends Component {\n\t\t\trender() {\n\t\t\t\tthrow promise;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<ThrowingChild />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\trender(null, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\tresolve();\n\n\t\treturn promise.then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\t\t});\n\t});\n\n\tit('should not crash when useContext is used in a suspending component', () => {\n\t\tconst TestContext = createContext('default');\n\t\tlet resolve;\n\t\tlet shouldSuspend = false;\n\t\tconst promise = new Promise(r => {\n\t\t\tresolve = r;\n\t\t});\n\n\t\tfunction ContextUser() {\n\t\t\tconst value = React.useContext(TestContext);\n\t\t\tif (shouldSuspend) {\n\t\t\t\tthrow promise;\n\t\t\t}\n\t\t\treturn <div>Context: {value}</div>;\n\t\t}\n\n\t\trender(\n\t\t\t<TestContext.Provider value=\"test-value\">\n\t\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t\t<ContextUser />\n\t\t\t\t</Suspense>\n\t\t\t</TestContext.Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Context: test-value</div>');\n\n\t\tshouldSuspend = true;\n\t\trender(\n\t\t\t<TestContext.Provider value=\"test-value\">\n\t\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t\t<ContextUser />\n\t\t\t\t</Suspense>\n\t\t\t</TestContext.Provider>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Suspended...</div>');\n\n\t\tshouldSuspend = false;\n\t\tresolve();\n\n\t\treturn promise.then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Context: test-value</div>');\n\t\t});\n\t});\n\n\tit('should not crash if fallback has same DOM as suspended nodes', () => {\n\t\tconst [Lazy, resolveLazy] = createLazy();\n\n\t\tconst App = () => {\n\t\t\tconst [, setTest] = useState(false);\n\t\t\tuseLayoutEffect(() => setTest(true), []);\n\n\t\t\treturn (\n\t\t\t\t<Suspense fallback={<div />}>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Lazy />\n\t\t\t\t\t</div>\n\t\t\t\t</Suspense>\n\t\t\t);\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\trerender();\n\n\t\treturn resolveLazy(() => <p>hello world</p>).then(() => {\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div><p>hello world</p></div>');\n\t\t});\n\t});\n\n\tit('should re-execute descendant memoed component effect when lazy boundary resolves', async () => {\n\t\tconst MemodComp = memo(() => {\n\t\t\tconst [state, setState] = useState('Memod effect not executed');\n\t\t\tuseEffect(() => {\n\t\t\t\tsetState('Memod effect executed');\n\t\t\t}, []);\n\t\t\treturn <span>{state}</span>;\n\t\t});\n\n\t\tconst NormalComp = () => {\n\t\t\tconst [state, setState] = useState('effect not executed');\n\t\t\tuseEffect(() => {\n\t\t\t\tsetState('effect executed');\n\t\t\t}, []);\n\t\t\treturn <span>{state}</span>;\n\t\t};\n\n\t\t/** @type {() => Promise<void>} */\n\t\tlet resolve;\n\t\tconst LazyComp = lazy(() => {\n\t\t\tconst p = new Promise(res => {\n\t\t\t\tresolve = () => {\n\t\t\t\t\tres({ default: NormalComp });\n\t\t\t\t\treturn p;\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn p;\n\t\t});\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Suspended...</div>}>\n\t\t\t\t<div>\n\t\t\t\t\t<MemodComp />\n\t\t\t\t\t<LazyComp />\n\t\t\t\t</div>\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div>Suspended...</div>`);\n\n\t\tawait resolve();\n\n\t\tawait act(() => rerender());\n\n\t\treturn expect(scratch.innerHTML).to.eql(\n\t\t\t`<div><span>Memod effect executed</span><span>effect executed</span></div>`\n\t\t);\n\t});\n\n\tit('should not schedule renders for setState on suspended component', async () => {\n\t\tlet suspenderSetState;\n\t\tlet renderCount = 0;\n\n\t\tclass Suspender extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { count: 0 };\n\t\t\t\tsuspenderSetState = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\trenderCount++;\n\t\t\t\tif (props.suspend && !props.resolved) {\n\t\t\t\t\tthrow props.promise;\n\t\t\t\t}\n\t\t\t\treturn <div>Count: {state.count}</div>;\n\t\t\t}\n\t\t}\n\n\t\tlet resolve;\n\t\tconst promise = new Promise(r => {\n\t\t\tresolve = r;\n\t\t});\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<Suspense fallback={<div>Loading...</div>}>\n\t\t\t\t\t<Suspender suspend={true} resolved={false} promise={promise} />\n\t\t\t\t</Suspense>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Loading...</div>');\n\t\tconst renderCountAfterSuspend = renderCount;\n\n\t\t// Call setState on the suspended component multiple times\n\t\tsuspenderSetState({ count: 1 });\n\t\tsuspenderSetState({ count: 2 });\n\t\tsuspenderSetState({ count: 3 });\n\t\trerender();\n\n\t\t// Render count should not have increased - setState should not trigger re-renders while suspended\n\t\texpect(renderCount).to.equal(renderCountAfterSuspend);\n\t\texpect(scratch.innerHTML).to.equal('<div>Loading...</div>');\n\n\t\t// Resolve the suspension\n\t\tresolve();\n\t\tawait promise;\n\n\t\trender(\n\t\t\t<Suspense fallback={<div>Loading...</div>}>\n\t\t\t\t<Suspender suspend={false} resolved={true} promise={promise} />\n\t\t\t</Suspense>,\n\t\t\tscratch\n\t\t);\n\t\trerender();\n\n\t\t// After resolving, the state should have been buffered and applied\n\t\texpect(scratch.innerHTML).to.equal('<div>Count: 3</div>');\n\t});\n\n\tit('should not schedule renders for forceUpdate on suspended component', () => {\n\t\tlet suspenderForceUpdate;\n\t\tlet renderCount = 0;\n\n\t\tclass Suspender extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tsuspenderForceUpdate = this.forceUpdate.bind(this);\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\trenderCount++;\n\t\t\t\tif (props.suspend && !props.resolved) {\n\t\t\t\t\tthrow props.promise;\n\t\t\t\t}\n\t\t\t\treturn <div>Rendered {renderCount} times</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst promise = new Promise(() => {});\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<Suspense fallback={<div>Loading...</div>}>\n\t\t\t\t\t<Suspender suspend={true} resolved={false} promise={promise} />\n\t\t\t\t</Suspense>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Loading...</div>');\n\t\tconst renderCountAfterSuspend = renderCount;\n\n\t\t// Call forceUpdate on the suspended component\n\t\tsuspenderForceUpdate();\n\t\tsuspenderForceUpdate();\n\t\trerender();\n\n\t\t// Render count should not have increased\n\t\texpect(renderCount).to.equal(renderCountAfterSuspend);\n\t\texpect(scratch.innerHTML).to.equal('<div>Loading...</div>');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/svg.test.jsx",
    "content": "import React, { createElement } from 'preact/compat';\nimport {\n\tsetupScratch,\n\tteardown,\n\tserializeHtml,\n\tsortAttributes\n} from '../../../test/_util/helpers';\n\ndescribe('svg', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should render SVG to string', () => {\n\t\tlet svg = (\n\t\t\t<svg viewBox=\"0 0 360 360\">\n\t\t\t\t<path\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t\td=\"M347.1 357.9L183.3 256.5 13 357.9V1.7h334.1v356.2zM58.5 47.2v231.4l124.8-74.1 118.3 72.8V47.2H58.5z\"\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t);\n\t\t// string -> parse\n\t\texpect(svg).to.eql(svg);\n\t});\n\n\tit('should render SVG to DOM #1', () => {\n\t\tconst Demo = () => (\n\t\t\t<svg viewBox=\"0 0 360 360\">\n\t\t\t\t<path\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t\td=\"M347.1 357.9L183.3 256.5 L 13 357.9V1.7h334.1v356.2zM58.5 47.2v231.4l124.8-74.1 l 118.3 72.8V47.2H58.5z\"\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t);\n\t\tReact.render(<Demo />, scratch);\n\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t'<svg viewBox=\"0 0 360 360\"><path stroke=\"white\" fill=\"black\" d=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\"></path></svg>'\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should render SVG to DOM #2', () => {\n\t\tReact.render(\n\t\t\t<svg viewBox=\"0 0 100 100\">\n\t\t\t\t<text textAnchor=\"mid\">foo</text>\n\t\t\t\t<path vectorEffect=\"non-scaling-stroke\" d=\"M0 0 L100 100\" />\n\t\t\t</svg>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t'<svg viewBox=\"0 0 100 100\"><text text-anchor=\"mid\">foo</text><path vector-effect=\"non-scaling-stroke\" d=\"M 0 0 L 100 100\"></path></svg>'\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should render correct SVG attribute names to the DOM', () => {\n\t\tReact.render(\n\t\t\t<svg\n\t\t\t\tclipPath=\"value\"\n\t\t\t\tclipRule=\"value\"\n\t\t\t\tclipPathUnits=\"value\"\n\t\t\t\tcolorInterpolationFilters=\"auto\"\n\t\t\t\tfontSizeAdjust=\"value\"\n\t\t\t\tglyphOrientationHorizontal=\"value\"\n\t\t\t\tglyphOrientationVertical=\"value\"\n\t\t\t\tshapeRendering=\"crispEdges\"\n\t\t\t\tglyphRef=\"value\"\n\t\t\t\thorizAdvX=\"value\"\n\t\t\t\thorizOriginX=\"value\"\n\t\t\t\tmarkerStart=\"value\"\n\t\t\t\tmarkerHeight=\"value\"\n\t\t\t\tmarkerUnits=\"value\"\n\t\t\t\tmarkerWidth=\"value\"\n\t\t\t\tunitsPerEm=\"value\"\n\t\t\t\tvertAdvY=\"value\"\n\t\t\t\tvertOriginX=\"value\"\n\t\t\t\tvertOriginY=\"value\"\n\t\t\t\tx1=\"value\"\n\t\t\t\txChannelSelector=\"value\"\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(serializeHtml(scratch)).to.eql(\n\t\t\tsortAttributes(\n\t\t\t\t'<svg clip-path=\"value\" clip-rule=\"value\" clipPathUnits=\"value\" color-interpolation-filters=\"auto\" font-size-adjust=\"value\" glyph-orientation-horizontal=\"value\" glyph-orientation-vertical=\"value\" shape-rendering=\"crispEdges\" glyphRef=\"value\" horiz-adv-x=\"value\" horiz-origin-x=\"value\" marker-start=\"value\" markerHeight=\"value\" markerUnits=\"value\" markerWidth=\"value\" units-per-em=\"value\" vert-adv-y=\"value\" vert-origin-x=\"value\" vert-origin-y=\"value\" x1=\"value\" xChannelSelector=\"value\"></svg>'\n\t\t\t)\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/testUtils.js",
    "content": "/**\n * Retrieve a Symbol if supported or use the fallback value\n * @param {string} name The name of the Symbol to look up\n * @param {number} fallback Fallback value if Symbols are not supported\n */\nexport function getSymbol(name, fallback) {\n\tlet out = fallback;\n\n\ttry {\n\t\t// eslint-disable-next-line\n\t\tif (\n\t\t\tFunction.prototype.toString\n\t\t\t\t.call((0, eval)('Symbol.for'))\n\t\t\t\t.match(/\\[native code\\]/)\n\t\t) {\n\t\t\t// Concatenate these string literals to prevent the test\n\t\t\t// harness and/or Babel from modifying the symbol value.\n\t\t\t// eslint-disable-next-line\n\t\t\tout = (0, eval)('Sym' + 'bol.for(\"' + name + '\")');\n\t\t}\n\t} catch (e) {}\n\n\treturn out;\n}\n"
  },
  {
    "path": "compat/test/browser/textarea.test.jsx",
    "content": "import React, { createElement, render, hydrate, useState } from 'preact/compat';\nimport ReactDOMServer from 'preact/compat/server';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { act } from 'preact/test-utils';\n\ndescribe('Textarea', () => {\n\t/** @type {HTMLElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should alias value to children', () => {\n\t\trender(<textarea value=\"foo\" />, scratch);\n\n\t\texpect(scratch.firstElementChild.value).to.equal('foo');\n\t});\n\n\tit('should hydrate textarea value', () => {\n\t\tfunction App() {\n\t\t\treturn <textarea value=\"foo\" />;\n\t\t}\n\n\t\tscratch.innerHTML = ReactDOMServer.renderToString(<App />);\n\t\texpect(scratch.firstElementChild.value).to.equal('foo');\n\t\texpect(scratch.innerHTML).to.be.equal('<textarea>foo</textarea>');\n\n\t\thydrate(<App />, scratch);\n\t\texpect(scratch.firstElementChild.value).to.equal('foo');\n\n\t\texpect(scratch.innerHTML).to.be.equal('<textarea></textarea>');\n\t});\n\n\tit('should alias defaultValue to children', () => {\n\t\trender(<textarea defaultValue=\"foo\" />, scratch);\n\n\t\texpect(scratch.firstElementChild.value).to.equal('foo');\n\t});\n\n\tit('should support resetting the value', () => {\n\t\tlet set;\n\t\tconst App = () => {\n\t\t\tconst [state, setState] = useState('');\n\t\t\tset = setState;\n\t\t\treturn <textarea value={state} />;\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<textarea></textarea>');\n\n\t\tact(() => {\n\t\t\tset('hello');\n\t\t});\n\t\t// Note: This looks counterintuitive, but it's working correctly - the value\n\t\t// missing from HTML because innerHTML doesn't serialize form field values.\n\t\t// See demo: https://jsfiddle.net/4had2Lu8\n\t\t// Related renderToString PR: preactjs/preact-render-to-string#161\n\t\texpect(scratch.innerHTML).to.equal('<textarea></textarea>');\n\t\texpect(scratch.firstElementChild.value).to.equal('hello');\n\n\t\tact(() => {\n\t\t\tset('');\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<textarea></textarea>');\n\t\texpect(scratch.firstElementChild.value).to.equal('');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/unmountComponentAtNode.test.jsx",
    "content": "import React, { createElement, unmountComponentAtNode } from 'preact/compat';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('unmountComponentAtNode', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should unmount a root node', () => {\n\t\tconst App = () => <div>foo</div>;\n\t\tReact.render(<App />, scratch);\n\n\t\texpect(unmountComponentAtNode(scratch)).to.equal(true);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should do nothing if root is not mounted', () => {\n\t\texpect(unmountComponentAtNode(scratch)).to.equal(false);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/unstable_batchedUpdates.test.js",
    "content": "import { unstable_batchedUpdates } from 'preact/compat';\n\ndescribe('unstable_batchedUpdates', () => {\n\tit('should execute & return cb', () => {\n\t\texpect(unstable_batchedUpdates(() => false)).to.equal(false);\n\t\texpect(unstable_batchedUpdates(arg => arg, true)).to.equal(true);\n\t});\n});\n"
  },
  {
    "path": "compat/test/browser/useSyncExternalStore.test.jsx",
    "content": "import React, {\n\tcreateElement,\n\tFragment,\n\tuseSyncExternalStore,\n\trender,\n\tuseState,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect\n} from 'preact/compat';\nimport { setupRerender, act } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\nconst ReactDOM = React;\n\ndescribe('useSyncExternalStore', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t/** @type {{ logs: string[], log(arg: string): void; }} */\n\tconst Scheduler = {\n\t\tlogs: [],\n\t\tlog(arg) {\n\t\t\tthis.logs.push(arg);\n\t\t}\n\t};\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tScheduler.logs = [];\n\t});\n\n\tfunction defer(cb) {\n\t\treturn Promise.resolve().then(cb);\n\t}\n\n\tfunction assertLog(expected) {\n\t\texpect(Scheduler.logs).to.deep.equal(expected);\n\t\tScheduler.logs = [];\n\t}\n\n\tfunction Text({ text }) {\n\t\tScheduler.log(text);\n\t\treturn text;\n\t}\n\n\t/** @type {(container: Element) => { render(children: React.JSX.Element): void}} */\n\tfunction createRoot(container) {\n\t\treturn {\n\t\t\trender(children) {\n\t\t\t\trender(children, container);\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction createExternalStore(initialState) {\n\t\tconst listeners = new Set();\n\t\tlet currentState = initialState;\n\t\treturn {\n\t\t\tlisteners,\n\t\t\tset(text) {\n\t\t\t\tcurrentState = text;\n\t\t\t\tlisteners.forEach(listener => listener());\n\t\t\t},\n\t\t\tsubscribe(listener) {\n\t\t\t\tlisteners.add(listener);\n\t\t\t\treturn () => listeners.delete(listener);\n\t\t\t},\n\t\t\tgetState() {\n\t\t\t\treturn currentState;\n\t\t\t},\n\t\t\tgetSubscriberCount() {\n\t\t\t\treturn listeners.size;\n\t\t\t}\n\t\t};\n\t}\n\n\tit('subscribes and follows effects', () => {\n\t\tconst subscribe = vi.fn(() => () => {});\n\t\tconst getSnapshot = vi.fn(() => 'hello world');\n\n\t\tconst App = () => {\n\t\t\tconst value = useSyncExternalStore(subscribe, getSnapshot);\n\t\t\treturn <p>{value}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>hello world</p>');\n\t\texpect(subscribe).toHaveBeenCalledOnce();\n\t\texpect(getSnapshot).toHaveBeenCalledTimes(3);\n\t});\n\n\tit('subscribes and rerenders when called', () => {\n\t\t/** @type {() => void} */\n\t\tlet flush;\n\t\tconst subscribe = vi.fn(cb => {\n\t\t\tflush = cb;\n\t\t\treturn () => {};\n\t\t});\n\t\tlet called = false;\n\t\tconst getSnapshot = vi.fn(() => {\n\t\t\tif (called) {\n\t\t\t\treturn 'hello new world';\n\t\t\t}\n\n\t\t\treturn 'hello world';\n\t\t});\n\n\t\tconst App = () => {\n\t\t\tconst value = useSyncExternalStore(subscribe, getSnapshot);\n\t\t\treturn <p>{value}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>hello world</p>');\n\t\texpect(subscribe).toHaveBeenCalledOnce();\n\t\texpect(getSnapshot).toHaveBeenCalledTimes(3);\n\n\t\tcalled = true;\n\t\tflush();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<p>hello new world</p>');\n\t});\n\n\tit('getSnapshot can return NaN without causing infinite loop', () => {\n\t\t/** @type {() => void} */\n\t\tlet flush;\n\t\tconst subscribe = vi.fn(cb => {\n\t\t\tflush = cb;\n\t\t\treturn () => {};\n\t\t});\n\t\tlet called = false;\n\t\tconst getSnapshot = vi.fn(() => {\n\t\t\tif (called) {\n\t\t\t\treturn NaN;\n\t\t\t}\n\n\t\t\treturn 1;\n\t\t});\n\n\t\tconst App = () => {\n\t\t\tconst value = useSyncExternalStore(subscribe, getSnapshot);\n\t\t\treturn <p>{value}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>1</p>');\n\t\texpect(subscribe).toHaveBeenCalledOnce();\n\t\texpect(getSnapshot).toHaveBeenCalledTimes(3);\n\n\t\tcalled = true;\n\t\tflush();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<p>NaN</p>');\n\t});\n\n\tit('should not call function values on subscription', () => {\n\t\t/** @type {() => void} */\n\t\tlet flush;\n\t\tconst subscribe = vi.fn(cb => {\n\t\t\tflush = cb;\n\t\t\treturn () => {};\n\t\t});\n\n\t\tconst func = () => 'value: ' + i++;\n\n\t\tlet i = 0;\n\t\tconst getSnapshot = vi.fn(() => {\n\t\t\treturn func;\n\t\t});\n\n\t\tconst App = () => {\n\t\t\tconst value = useSyncExternalStore(subscribe, getSnapshot);\n\t\t\treturn <p>{value()}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>value: 0</p>');\n\t\texpect(subscribe).toHaveBeenCalledOnce();\n\t\texpect(getSnapshot).toHaveBeenCalledTimes(3);\n\n\t\tflush();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<p>value: 0</p>');\n\t});\n\n\tit('should work with changing getSnapshot', () => {\n\t\t/** @type {() => void} */\n\t\tlet flush;\n\t\tconst subscribe = vi.fn(cb => {\n\t\t\tflush = cb;\n\t\t\treturn () => {};\n\t\t});\n\n\t\tlet i = 0;\n\t\tconst App = () => {\n\t\t\tconst value = useSyncExternalStore(subscribe, () => {\n\t\t\t\treturn i;\n\t\t\t});\n\t\t\treturn <p>value: {value}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>value: 0</p>');\n\t\texpect(subscribe).toHaveBeenCalledOnce();\n\n\t\ti++;\n\t\tflush();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<p>value: 1</p>');\n\t});\n\n\tit('works with useCallback', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\t\tconst App = () => {\n\t\t\tconst [state, setState] = useState(true);\n\t\t\ttoggle = setState.bind(this, () => false);\n\n\t\t\tconst value = useSyncExternalStore(\n\t\t\t\tuseCallback(() => {\n\t\t\t\t\treturn () => {};\n\t\t\t\t}, [state]),\n\t\t\t\t() => (state ? 'yep' : 'nope')\n\t\t\t);\n\n\t\t\treturn <p>{value}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>yep</p>');\n\n\t\ttoggle();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('<p>nope</p>');\n\t});\n\n\tit('handles store updates before subscribing', async () => {\n\t\t// This test is testing scheduling mechanics, so teardown the manual\n\t\t// rerender test setup to rely on Preact's built-in scheduling and verify\n\t\t// this behavior works. We still need a DOM container to render into so set\n\t\t// that back up.\n\t\tteardown(scratch);\n\t\tscratch = setupScratch();\n\n\t\tconst store = createExternalStore(0);\n\n\t\tfunction App() {\n\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\tuseEffect(() => {\n\t\t\t\tScheduler.log('Passive effect: ' + value);\n\t\t\t}, [value]);\n\t\t\treturn <Text text={value} />;\n\t\t}\n\n\t\tconst container = document.createElement('div');\n\t\tconst root = createRoot(container);\n\n\t\t// Schedule a mutation in the next microtask after the initial render but\n\t\t// before subscribing to the store\n\t\tconst mutation = defer(() => {\n\t\t\t// Assert we are running this mutation before subscribing to the store\n\t\t\texpect(store.listeners.size).to.equal(0);\n\t\t\tstore.set(1);\n\t\t});\n\n\t\troot.render(<App />);\n\t\texpect(container.textContent).to.equal('0');\n\t\tassertLog([0]);\n\n\t\t// Wait for the mutation to occur. Then wait for the passive effects that\n\t\t// subscribe to the store and log the new value.\n\t\tawait mutation;\n\t\tawait new Promise(r => setTimeout(r, 32));\n\n\t\texpect(container.textContent).to.equal('1');\n\t\texpect(store.listeners.size).to.equal(1);\n\t\tassertLog(['Passive effect: 0', 1, 'Passive effect: 1']);\n\t});\n\n\t// The following tests are taken from the React test suite:\n\t// https://github.com/facebook/react/blob/3e09c27b880e1fecdb1eca5db510ecce37ea6be2/packages/use-sync-external-store/src/__tests__/useSyncExternalStoreShared-test.js\n\tdescribe('React useSyncExternalStore test suite', () => {\n\t\tit('basic usage', async () => {\n\t\t\tconst store = createExternalStore('Initial');\n\n\t\t\tfunction App() {\n\t\t\t\tconst text = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\treturn <Text text={text} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\n\t\t\tassertLog(['Initial']);\n\t\t\texpect(container.textContent).to.equal('Initial');\n\n\t\t\tawait act(() => {\n\t\t\t\tstore.set('Updated');\n\t\t\t});\n\t\t\tassertLog(['Updated']);\n\t\t\texpect(container.textContent).to.equal('Updated');\n\t\t});\n\n\t\tit('skips re-rendering if nothing changes', async () => {\n\t\t\tconst store = createExternalStore('Initial');\n\n\t\t\tfunction App() {\n\t\t\t\tconst text = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\treturn <Text text={text} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\n\t\t\tassertLog(['Initial']);\n\t\t\texpect(container.textContent).to.equal('Initial');\n\n\t\t\t// Update to the same value\n\t\t\tawait act(() => {\n\t\t\t\tstore.set('Initial');\n\t\t\t});\n\t\t\t// Should not re-render\n\t\t\tassertLog([]);\n\t\t\texpect(container.textContent).to.equal('Initial');\n\t\t});\n\n\t\tit('switch to a different store', async () => {\n\t\t\tconst storeA = createExternalStore(0);\n\t\t\tconst storeB = createExternalStore(0);\n\n\t\t\tlet setStore;\n\t\t\tfunction App() {\n\t\t\t\tconst [store, _setStore] = useState(storeA);\n\t\t\t\tsetStore = _setStore;\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\treturn <Text text={value} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\n\t\t\tassertLog([0]);\n\t\t\texpect(container.textContent).to.equal('0');\n\n\t\t\tawait act(() => {\n\t\t\t\tstoreA.set(1);\n\t\t\t});\n\t\t\tassertLog([1]);\n\t\t\texpect(container.textContent).to.equal('1');\n\n\t\t\t// Switch stores and update in the same batch\n\t\t\tawait act(() => {\n\t\t\t\t// This update will be disregarded\n\t\t\t\tstoreA.set(2);\n\t\t\t\tsetStore(storeB);\n\t\t\t});\n\t\t\t// Now reading from B instead of A\n\t\t\tassertLog([0]);\n\t\t\texpect(container.textContent).to.equal('0');\n\n\t\t\t// Update A\n\t\t\tawait act(() => {\n\t\t\t\tstoreA.set(3);\n\t\t\t});\n\t\t\t// Nothing happened, because we're no longer subscribed to A\n\t\t\tassertLog([]);\n\t\t\texpect(container.textContent).to.equal('0');\n\n\t\t\t// Update B\n\t\t\tawait act(() => {\n\t\t\t\tstoreB.set(1);\n\t\t\t});\n\t\t\tassertLog([1]);\n\t\t\texpect(container.textContent).to.equal('1');\n\t\t});\n\n\t\tit('selecting a specific value inside getSnapshot', async () => {\n\t\t\tconst store = createExternalStore({ a: 0, b: 0 });\n\n\t\t\tfunction A() {\n\t\t\t\tconst a = useSyncExternalStore(\n\t\t\t\t\tstore.subscribe,\n\t\t\t\t\t() => store.getState().a\n\t\t\t\t);\n\t\t\t\treturn <Text text={'A' + a} />;\n\t\t\t}\n\t\t\tfunction B() {\n\t\t\t\tconst b = useSyncExternalStore(\n\t\t\t\t\tstore.subscribe,\n\t\t\t\t\t() => store.getState().b\n\t\t\t\t);\n\t\t\t\treturn <Text text={'B' + b} />;\n\t\t\t}\n\n\t\t\tfunction App() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<A />\n\t\t\t\t\t\t<B />\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\n\t\t\tassertLog(['A0', 'B0']);\n\t\t\texpect(container.textContent).to.equal('A0B0');\n\n\t\t\t// Update b but not a\n\t\t\tawait act(() => {\n\t\t\t\tstore.set({ a: 0, b: 1 });\n\t\t\t});\n\t\t\t// Only b re-renders\n\t\t\tassertLog(['B1']);\n\t\t\texpect(container.textContent).to.equal('A0B1');\n\n\t\t\t// Update a but not b\n\t\t\tawait act(() => {\n\t\t\t\tstore.set({ a: 1, b: 1 });\n\t\t\t});\n\t\t\t// Only a re-renders\n\t\t\tassertLog(['A1']);\n\t\t\texpect(container.textContent).to.equal('A1B1');\n\t\t});\n\n\t\t// In React 18, you can't observe in between a sync render and its\n\t\t// passive effects, so this is only relevant to legacy roots\n\t\t// @gate enableUseSyncExternalStoreShim\n\t\tit(\"compares to current state before bailing out, even when there's a mutation in between the sync and passive effects\", async () => {\n\t\t\tconst store = createExternalStore(0);\n\n\t\t\tfunction App() {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\tuseEffect(() => {\n\t\t\t\t\tScheduler.log('Passive effect: ' + value);\n\t\t\t\t}, [value]);\n\t\t\t\treturn <Text text={value} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\t\t\tassertLog([0, 'Passive effect: 0']);\n\n\t\t\t// Schedule an update. We'll intentionally not use `act` so that we can\n\t\t\t// insert a mutation before React subscribes to the store in a\n\t\t\t// passive effect.\n\t\t\tstore.set(1);\n\t\t\trerender();\n\t\t\tassertLog([\n\t\t\t\t1\n\t\t\t\t// Passive effect hasn't fired yet\n\t\t\t]);\n\t\t\texpect(container.textContent).to.equal('1');\n\n\t\t\t// Flip the store state back to the previous value.\n\t\t\tstore.set(0);\n\t\t\trerender();\n\t\t\tassertLog([\n\t\t\t\t'Passive effect: 1',\n\t\t\t\t// Re-render. If the current state were tracked by updating a ref in a\n\t\t\t\t// passive effect, then this would break because the previous render's\n\t\t\t\t// passive effect hasn't fired yet, so we'd incorrectly think that\n\t\t\t\t// the state hasn't changed.\n\t\t\t\t0\n\t\t\t]);\n\t\t\t// Should flip back to 0\n\t\t\texpect(container.textContent).to.equal('0');\n\n\t\t\t// Preact: Wait for 'Passive effect: 0' to flush from the rAF so it doesn't impact other tests\n\t\t\tawait new Promise(r => setTimeout(r, 32));\n\t\t});\n\n\t\tit('mutating the store in between render and commit when getSnapshot has changed', async () => {\n\t\t\tconst store = createExternalStore({ a: 1, b: 1 });\n\n\t\t\tconst getSnapshotA = () => store.getState().a;\n\t\t\tconst getSnapshotB = () => store.getState().b;\n\n\t\t\tfunction Child1({ step }) {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\tuseLayoutEffect(() => {\n\t\t\t\t\tif (step === 1) {\n\t\t\t\t\t\t// Update B in a layout effect. This happens in the same commit\n\t\t\t\t\t\t// that changed the getSnapshot in Child2. Child2's effects haven't\n\t\t\t\t\t\t// fired yet, so it doesn't have access to the latest getSnapshot. So\n\t\t\t\t\t\t// it can't use the getSnapshot to bail out.\n\t\t\t\t\t\tScheduler.log('Update B in commit phase');\n\t\t\t\t\t\tstore.set({ a: value.a, b: 2 });\n\t\t\t\t\t}\n\t\t\t\t}, [step]);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tfunction Child2({ step }) {\n\t\t\t\tconst label = step === 0 ? 'A' : 'B';\n\t\t\t\tconst getSnapshot = step === 0 ? getSnapshotA : getSnapshotB;\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, getSnapshot);\n\t\t\t\treturn <Text text={label + value} />;\n\t\t\t}\n\n\t\t\tlet setStep;\n\t\t\tfunction App() {\n\t\t\t\tconst [step, _setStep] = useState(0);\n\t\t\t\tsetStep = _setStep;\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Child1 step={step} />\n\t\t\t\t\t\t<Child2 step={step} />\n\t\t\t\t\t</>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\t\t\tassertLog(['A1']);\n\t\t\texpect(container.textContent).to.equal('A1');\n\n\t\t\tawait act(() => {\n\t\t\t\t// Change getSnapshot and update the store in the same batch\n\t\t\t\tsetStep(1);\n\t\t\t});\n\t\t\tassertLog([\n\t\t\t\t'B1',\n\t\t\t\t'Update B in commit phase',\n\t\t\t\t// If Child2 had used the old getSnapshot to bail out, then it would have\n\t\t\t\t// incorrectly bailed out here instead of re-rendering.\n\t\t\t\t'B2'\n\t\t\t]);\n\t\t\texpect(container.textContent).to.equal('B2');\n\t\t});\n\n\t\tit('mutating the store in between render and commit when getSnapshot has _not_ changed', async () => {\n\t\t\t// Same as previous test, but `getSnapshot` does not change\n\t\t\tconst store = createExternalStore({ a: 1, b: 1 });\n\n\t\t\tconst getSnapshotA = () => store.getState().a;\n\n\t\t\tfunction Child1({ step }) {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\tuseLayoutEffect(() => {\n\t\t\t\t\tif (step === 1) {\n\t\t\t\t\t\t// Update B in a layout effect. This happens in the same commit\n\t\t\t\t\t\t// that changed the getSnapshot in Child2. Child2's effects haven't\n\t\t\t\t\t\t// fired yet, so it doesn't have access to the latest getSnapshot. So\n\t\t\t\t\t\t// it can't use the getSnapshot to bail out.\n\t\t\t\t\t\tScheduler.log('Update B in commit phase');\n\t\t\t\t\t\tstore.set({ a: value.a, b: 2 });\n\t\t\t\t\t}\n\t\t\t\t}, [step]);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tfunction Child2({ step }) {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, getSnapshotA);\n\t\t\t\treturn <Text text={'A' + value} />;\n\t\t\t}\n\n\t\t\tlet setStep;\n\t\t\tfunction App() {\n\t\t\t\tconst [step, _setStep] = useState(0);\n\t\t\t\tsetStep = _setStep;\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Child1 step={step} />\n\t\t\t\t\t\t<Child2 step={step} />\n\t\t\t\t\t</>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\t\t\tassertLog(['A1']);\n\t\t\texpect(container.textContent).to.equal('A1');\n\n\t\t\t// This will cause a layout effect, and in the layout effect we'll update\n\t\t\t// the store\n\t\t\tawait act(() => {\n\t\t\t\tsetStep(1);\n\t\t\t});\n\t\t\tassertLog([\n\t\t\t\t'A1',\n\t\t\t\t// This updates B, but since Child2 doesn't subscribe to B, it doesn't\n\t\t\t\t// need to re-render.\n\t\t\t\t'Update B in commit phase'\n\t\t\t\t// No re-render\n\t\t\t]);\n\t\t\texpect(container.textContent).to.equal('A1');\n\t\t});\n\n\t\tit(\"does not bail out if the previous update hasn't finished yet\", async () => {\n\t\t\tconst store = createExternalStore(0);\n\n\t\t\tfunction Child1() {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\tuseLayoutEffect(() => {\n\t\t\t\t\tif (value === 1) {\n\t\t\t\t\t\tScheduler.log('Reset back to 0');\n\t\t\t\t\t\tstore.set(0);\n\t\t\t\t\t}\n\t\t\t\t}, [value]);\n\t\t\t\treturn <Text text={value} />;\n\t\t\t}\n\n\t\t\tfunction Child2() {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\treturn <Text text={value} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() =>\n\t\t\t\troot.render(\n\t\t\t\t\t<>\n\t\t\t\t\t\t<Child1 />\n\t\t\t\t\t\t<Child2 />\n\t\t\t\t\t</>\n\t\t\t\t)\n\t\t\t);\n\t\t\tassertLog([0, 0]);\n\t\t\texpect(container.textContent).to.equal('00');\n\n\t\t\tawait act(() => {\n\t\t\t\tstore.set(1);\n\t\t\t});\n\t\t\t// Preact logs differ from React here cuz of how we do rerendering. We\n\t\t\t// rerender subtrees and then commit effects so Child2 never sees the\n\t\t\t// update to 1 cuz Child1 rerenders and runs its layout effects first.\n\t\t\tassertLog([1, /*1,*/ 'Reset back to 0', 0, 0]);\n\t\t\texpect(container.textContent).to.equal('00');\n\t\t});\n\n\t\tit('uses the latest getSnapshot, even if it changed in the same batch as a store update', async () => {\n\t\t\tconst store = createExternalStore({ a: 0, b: 0 });\n\n\t\t\tconst getSnapshotA = () => store.getState().a;\n\t\t\tconst getSnapshotB = () => store.getState().b;\n\n\t\t\tlet setGetSnapshot;\n\t\t\tfunction App() {\n\t\t\t\tconst [getSnapshot, _setGetSnapshot] = useState(() => getSnapshotA);\n\t\t\t\tsetGetSnapshot = _setGetSnapshot;\n\t\t\t\tconst text = useSyncExternalStore(store.subscribe, getSnapshot);\n\t\t\t\treturn <Text text={text} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\t\t\tassertLog([0]);\n\n\t\t\t// Update the store and getSnapshot at the same time\n\t\t\tawait act(() => {\n\t\t\t\tsetGetSnapshot(() => getSnapshotB);\n\t\t\t\tstore.set({ a: 1, b: 2 });\n\t\t\t});\n\t\t\t// It should read from B instead of A\n\t\t\tassertLog([2]);\n\t\t\texpect(container.textContent).to.equal('2');\n\t\t});\n\n\t\tit('handles errors thrown by getSnapshot', async () => {\n\t\t\tclass ErrorBoundary extends React.Component {\n\t\t\t\tstate = { error: null };\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tif (this.state.error) {\n\t\t\t\t\t\treturn <Text text={this.state.error.message} />;\n\t\t\t\t\t}\n\t\t\t\t\treturn this.props.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst store = createExternalStore({\n\t\t\t\tvalue: 0,\n\t\t\t\tthrowInGetSnapshot: false,\n\t\t\t\tthrowInIsEqual: false\n\t\t\t});\n\n\t\t\tfunction App() {\n\t\t\t\tconst { value } = useSyncExternalStore(store.subscribe, () => {\n\t\t\t\t\tconst state = store.getState();\n\t\t\t\t\tif (state.throwInGetSnapshot) {\n\t\t\t\t\t\tthrow new Error('Error in getSnapshot');\n\t\t\t\t\t}\n\t\t\t\t\treturn state;\n\t\t\t\t});\n\t\t\t\treturn <Text text={value} />;\n\t\t\t}\n\n\t\t\tconst errorBoundary = React.createRef();\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() =>\n\t\t\t\troot.render(\n\t\t\t\t\t<ErrorBoundary ref={errorBoundary}>\n\t\t\t\t\t\t<App />\n\t\t\t\t\t</ErrorBoundary>\n\t\t\t\t)\n\t\t\t);\n\t\t\tassertLog([0]);\n\t\t\texpect(container.textContent).to.equal('0');\n\n\t\t\t// Update that throws in a getSnapshot. We can catch it with an error boundary.\n\t\t\tawait act(() => {\n\t\t\t\tstore.set({\n\t\t\t\t\tvalue: 1,\n\t\t\t\t\tthrowInGetSnapshot: true,\n\t\t\t\t\tthrowInIsEqual: false\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tassertLog(['Error in getSnapshot']);\n\t\t\texpect(container.textContent).to.equal('Error in getSnapshot');\n\t\t});\n\n\t\tit('getSnapshot can return NaN without infinite loop warning', async () => {\n\t\t\tconst store = createExternalStore('not a number');\n\n\t\t\tfunction App() {\n\t\t\t\tconst value = useSyncExternalStore(store.subscribe, () =>\n\t\t\t\t\tparseInt(store.getState(), 10)\n\t\t\t\t);\n\t\t\t\treturn <Text text={value} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\n\t\t\t// Initial render that reads a snapshot of NaN. This is OK because we use\n\t\t\t// Object.is algorithm to compare values.\n\t\t\tawait act(() => root.render(<App />));\n\t\t\texpect(container.textContent).to.equal('NaN');\n\n\t\t\t// Update to real number\n\t\t\tawait act(() => store.set(123));\n\t\t\texpect(container.textContent).to.equal('123');\n\n\t\t\t// Update back to NaN\n\t\t\tawait act(() => store.set('not a number'));\n\t\t\texpect(container.textContent).to.equal('NaN');\n\t\t});\n\n\t\tit('regression test for facebook/react#23150', async () => {\n\t\t\tconst store = createExternalStore('Initial');\n\n\t\t\tfunction App() {\n\t\t\t\tconst text = useSyncExternalStore(store.subscribe, store.getState);\n\t\t\t\tconst [derivedText, setDerivedText] = useState(text);\n\t\t\t\tuseEffect(() => {}, []);\n\t\t\t\tif (derivedText !== text.toUpperCase()) {\n\t\t\t\t\tsetDerivedText(text.toUpperCase());\n\t\t\t\t}\n\t\t\t\treturn <Text text={derivedText} />;\n\t\t\t}\n\n\t\t\tconst container = document.createElement('div');\n\t\t\tconst root = createRoot(container);\n\t\t\tawait act(() => root.render(<App />));\n\n\t\t\tassertLog(['INITIAL']);\n\t\t\texpect(container.textContent).to.equal('INITIAL');\n\n\t\t\tawait act(() => {\n\t\t\t\tstore.set('Updated');\n\t\t\t});\n\t\t\tassertLog(['UPDATED']);\n\t\t\texpect(container.textContent).to.equal('UPDATED');\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "compat/test/ts/forward-ref.tsx",
    "content": "import React from '../../src';\n\nconst MyInput: React.ForwardRefRenderFunction<\n\t{ focus(): void },\n\t{ id: string }\n> = (props, ref) => {\n\tconst inputRef = React.useRef<HTMLInputElement>(null);\n\n\tReact.useImperativeHandle(ref, () => ({\n\t\tfocus: () => {\n\t\t\tif (inputRef.current) {\n\t\t\t\tinputRef.current.focus();\n\t\t\t}\n\t\t}\n\t}));\n\n\treturn <input {...props} ref={inputRef} />;\n};\n\nexport const foo = React.forwardRef(MyInput);\n\nexport const Bar = React.forwardRef<HTMLDivElement, { children: any }>(\n\t(props, ref) => {\n\t\treturn <div ref={ref}>{props.children}</div>;\n\t}\n);\n\nexport const baz = (\n\tref: React.ForwardedRef<HTMLElement>\n): React.Ref<HTMLElement> => ref;\n"
  },
  {
    "path": "compat/test/ts/index.tsx",
    "content": "import React from '../../src';\n\nReact.render(<div />, document.createElement('div'));\nReact.render(<div />, document.createDocumentFragment());\nReact.render(<div />, document.body.shadowRoot!);\n\nReact.hydrate(<div />, document.createElement('div'));\nReact.hydrate(<div />, document.createDocumentFragment());\nReact.hydrate(<div />, document.body.shadowRoot!);\n\nReact.unmountComponentAtNode(document.createElement('div'));\nReact.unmountComponentAtNode(document.createDocumentFragment());\nReact.unmountComponentAtNode(document.body.shadowRoot!);\n\nReact.createPortal(<div />, document.createElement('div'));\nReact.createPortal(<div />, document.createDocumentFragment());\nReact.createPortal(<div />, document.body.shadowRoot!);\n\nconst Ctx = React.createContext({ contextValue: '' });\nclass SimpleComponentWithContextAsProvider extends React.Component {\n\tcomponentProp = 'componentProp';\n\trender() {\n\t\t// Render inside div to ensure standard JSX elements still work\n\t\treturn (\n\t\t\t<Ctx value={{ contextValue: 'value' }}>\n\t\t\t\t<div>\n\t\t\t\t\t{/* Ensure context still works */}\n\t\t\t\t\t<Ctx.Consumer>\n\t\t\t\t\t\t{({ contextValue }) => contextValue.toLowerCase()}\n\t\t\t\t\t</Ctx.Consumer>\n\t\t\t\t</div>\n\t\t\t</Ctx>\n\t\t);\n\t}\n}\n\nSimpleComponentWithContextAsProvider.defaultProps = { foo: 'default' };\n\nReact.render(\n\t<SimpleComponentWithContextAsProvider />,\n\tdocument.createElement('div')\n);\n"
  },
  {
    "path": "compat/test/ts/lazy.tsx",
    "content": "import * as React from '../../src';\n\nexport interface LazyProps {\n\tisProp: boolean;\n}\n\ninterface LazyState {\n\tforState: string;\n}\nexport default class IsLazyComponent extends React.Component<\n\tLazyProps,\n\tLazyState\n> {\n\trender({ isProp }: LazyProps) {\n\t\treturn <div>{isProp ? 'Super Lazy TRUE' : 'Super Lazy FALSE'}</div>;\n\t}\n}\n"
  },
  {
    "path": "compat/test/ts/memo.tsx",
    "content": "import * as React from '../../src';\nimport { expectType } from './utils';\n\ninterface MemoProps {\n\trequired: string;\n\toptional?: string;\n\tdefaulted: string;\n}\n\ninterface MemoPropsExceptDefaults {\n\trequired: string;\n\toptional?: string;\n}\n\nconst ComponentExceptDefaults = () => <div></div>;\n\nconst ReadonlyBaseComponent = (props: Readonly<MemoProps>) => (\n\t<div>{props.required + props.optional + props.defaulted}</div>\n);\nReadonlyBaseComponent.defaultProps = { defaulted: '' };\n\nconst BaseComponent = (props: MemoProps) => (\n\t<div>{props.required + props.optional + props.defaulted}</div>\n);\nBaseComponent.defaultProps = { defaulted: '' };\n\n// memo for readonly component with default comparison\nconst MemoedReadonlyComponent = React.memo(ReadonlyBaseComponent);\nexpectType<React.FunctionComponent<MemoProps>>(MemoedReadonlyComponent);\nexport const memoedReadonlyComponent = (\n\t<MemoedReadonlyComponent required=\"hi\" />\n);\n\n// memo for non-readonly component with default comparison\nconst MemoedComponent = React.memo(BaseComponent);\nexpectType<React.FunctionComponent<MemoProps>>(MemoedComponent);\nexport const memoedComponent = <MemoedComponent required=\"hi\" />;\n\n// memo with custom comparison\nconst CustomMemoedComponent = React.memo(BaseComponent, (a, b) => {\n\texpectType<MemoProps>(a);\n\texpectType<MemoProps>(b);\n\treturn a.required === b.required;\n});\nexpectType<React.FunctionComponent<MemoProps>>(CustomMemoedComponent);\nexport const customMemoedComponent = <CustomMemoedComponent required=\"hi\" />;\n\nconst MemoedComponentExceptDefaults = React.memo<MemoPropsExceptDefaults>(\n\tComponentExceptDefaults\n);\nexpectType<React.FunctionComponent<MemoPropsExceptDefaults>>(\n\tMemoedComponentExceptDefaults\n);\nexport const memoedComponentExceptDefaults = (\n\t<MemoedComponentExceptDefaults required=\"hi\" />\n);\n"
  },
  {
    "path": "compat/test/ts/react-default.tsx",
    "content": "import React from '../../src';\nclass ReactIsh extends React.Component {\n\trender() {\n\t\treturn <div>Text</div>;\n\t}\n}\n"
  },
  {
    "path": "compat/test/ts/react-star.tsx",
    "content": "// import React from '../../src';\nimport * as React from '../../src';\nclass ReactIsh extends React.Component {\n\trender() {\n\t\treturn <div>Text</div>;\n\t}\n}\n"
  },
  {
    "path": "compat/test/ts/scheduler.ts",
    "content": "import {\n\tunstable_runWithPriority,\n\tunstable_NormalPriority,\n\tunstable_LowPriority,\n\tunstable_IdlePriority,\n\tunstable_UserBlockingPriority,\n\tunstable_ImmediatePriority,\n\tunstable_now\n} from '../../src';\n\nconst noop = () => null;\nunstable_runWithPriority(unstable_IdlePriority, noop);\nunstable_runWithPriority(unstable_LowPriority, noop);\nunstable_runWithPriority(unstable_NormalPriority, noop);\nunstable_runWithPriority(unstable_UserBlockingPriority, noop);\nunstable_runWithPriority(unstable_ImmediatePriority, noop);\n\nif (typeof unstable_now() === 'number') {\n}\n"
  },
  {
    "path": "compat/test/ts/suspense.tsx",
    "content": "import * as React from '../../src';\n\ninterface LazyProps {\n\tisProp: boolean;\n}\n\nconst IsLazyFunctional = (props: LazyProps) => (\n\t<div>{props.isProp ? 'Super Lazy TRUE' : 'Super Lazy FALSE'}</div>\n);\n\nconst FallBack = () => <div>Still working...</div>;\n/**\n * Have to mock dynamic import as import() throws a syntax error in the test runner\n */\nconst componentPromise = new Promise<{ default: typeof IsLazyFunctional }>(\n\tresolve => {\n\t\tsetTimeout(() => {\n\t\t\tresolve({ default: IsLazyFunctional });\n\t\t}, 800);\n\t}\n);\n\n/**\n * For usage with import:\n * const IsLazyComp = lazy(() => import('./lazy'));\n */\nconst IsLazyFunc = React.lazy(() => componentPromise);\n\n// Suspense using lazy component\nclass ReactSuspensefulFunc extends React.Component {\n\trender() {\n\t\treturn (\n\t\t\t<React.Suspense fallback={<FallBack />}>\n\t\t\t\t<IsLazyFunc isProp={false} />\n\t\t\t</React.Suspense>\n\t\t);\n\t}\n}\n\nconst Comp = () => <p>Hello world</p>;\n\nconst importComponent = async () => {\n\treturn { MyComponent: Comp };\n};\n\nconst Lazy = React.lazy(() =>\n\timportComponent().then(mod => ({ default: mod.MyComponent }))\n);\n\n// eslint-disable-next-line\nfunction App() {\n\treturn <Lazy />;\n}\n"
  },
  {
    "path": "compat/test/ts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"module\": \"es6\",\n    \"moduleResolution\": \"node\",\n    \"lib\": [\"es6\", \"dom\"],\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"jsx\": \"react\",\n    \"noEmit\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"paths\": {\n      \"preact\": [\"../../../src/index.d.ts\"]\n    }\n  },\n  \"include\": [\"./**/*.ts\", \"./**/*.tsx\"]\n}\n"
  },
  {
    "path": "compat/test/ts/utils.ts",
    "content": "/**\n * Assert the parameter is of a specific type.\n */\nexport const expectType = <T>(_: T): void => undefined;\n"
  },
  {
    "path": "compat/test-utils.js",
    "content": "module.exports = require('preact/test-utils');\n"
  },
  {
    "path": "compat/test-utils.mjs",
    "content": "export * from 'preact/test-utils';\n"
  },
  {
    "path": "config/compat-entries.js",
    "content": "const path = require('path');\nconst fs = require('fs');\nconst kl = require('kolorist');\n\nconst pkgFiles = new Set(require('../package.json').files);\nconst compatDir = path.join(__dirname, '..', 'compat');\nconst files = fs.readdirSync(compatDir);\n\nlet missing = 0;\nfor (const file of files) {\n\tconst expected = 'compat/' + file;\n\tif (/\\.(js|mjs)$/.test(file) && !pkgFiles.has(expected)) {\n\t\tmissing++;\n\n\t\tconst filePath = kl.cyan('compat/' + file);\n\t\tconst label = kl.inverse(kl.red(' ERROR '));\n\t\tconsole.error(\n\t\t\t`${label} File ${filePath} is missing in \"files\" entry in package.json`\n\t\t);\n\t}\n}\n\nif (missing > 0) {\n\tprocess.exit(1);\n}\n"
  },
  {
    "path": "debug/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-present Jason Miller\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": "debug/mangle.json",
    "content": "{\n  \"help\": {\n    \"what is this file?\": \"It controls protected/private property mangling so that minified builds have consistent property names.\",\n    \"why are there duplicate minified properties?\": \"Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size.\"\n  },\n  \"minify\": {\n    \"mangle\": {\n      \"properties\": {\n        \"regex\": \"^_[^_]\",\n        \"reserved\": [\n          \"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\",\n          \"__REACT_DEVTOOLS_GLOBAL_HOOK__\",\n          \"__PREACT_DEVTOOLS__\",\n          \"_renderers\",\n          \"__source\",\n          \"__self\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "debug/package.json",
    "content": "{\n  \"name\": \"preact-debug\",\n  \"amdName\": \"preactDebug\",\n  \"private\": true,\n  \"description\": \"Preact extensions for development\",\n  \"main\": \"dist/debug.js\",\n  \"module\": \"dist/debug.mjs\",\n  \"umd:main\": \"dist/debug.umd.js\",\n  \"source\": \"src/index.js\",\n  \"types\": \"src/index.d.ts\",\n  \"license\": \"MIT\",\n  \"mangle\": {\n    \"regex\": \"^(?!_renderer)^_\"\n  },\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "debug/src/check-props.js",
    "content": "const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';\n\nlet loggedTypeFailures = {};\n\n/**\n * Reset the history of which prop type warnings have been logged.\n */\nexport function resetPropWarnings() {\n\tloggedTypeFailures = {};\n}\n\n/**\n * Assert that the values match with the type specs.\n * Error messages are memorized and will only be shown once.\n *\n * Adapted from https://github.com/facebook/prop-types/blob/master/checkPropTypes.js\n *\n * @param {object} typeSpecs Map of name to a ReactPropType\n * @param {object} values Runtime values that need to be type-checked\n * @param {string} location e.g. \"prop\", \"context\", \"child context\"\n * @param {string} componentName Name of the component for error messages.\n * @param {?Function} getStack Returns the component stack.\n */\nexport function checkPropTypes(\n\ttypeSpecs,\n\tvalues,\n\tlocation,\n\tcomponentName,\n\tgetStack\n) {\n\tObject.keys(typeSpecs).forEach(typeSpecName => {\n\t\tlet error;\n\t\ttry {\n\t\t\terror = typeSpecs[typeSpecName](\n\t\t\t\tvalues,\n\t\t\t\ttypeSpecName,\n\t\t\t\tcomponentName,\n\t\t\t\tlocation,\n\t\t\t\tnull,\n\t\t\t\tReactPropTypesSecret\n\t\t\t);\n\t\t} catch (e) {\n\t\t\terror = e;\n\t\t}\n\t\tif (error && !(error.message in loggedTypeFailures)) {\n\t\t\tloggedTypeFailures[error.message] = true;\n\t\t\tconsole.error(\n\t\t\t\t`Failed ${location} type: ${error.message}${\n\t\t\t\t\t(getStack && `\\n${getStack()}`) || ''\n\t\t\t\t}`\n\t\t\t);\n\t\t}\n\t});\n}\n"
  },
  {
    "path": "debug/src/component-stack.js",
    "content": "import { options, Fragment } from 'preact';\n\n/**\n * Get human readable name of the component/dom node\n *\n * @param {import('./internal').VNode} vnode\n * @returns {string}\n */\nexport function getDisplayName(vnode) {\n\tif (vnode.type === Fragment) {\n\t\treturn 'Fragment';\n\t} else if (typeof vnode.type == 'function') {\n\t\treturn vnode.type.displayName || vnode.type.name;\n\t} else if (typeof vnode.type == 'string') {\n\t\treturn vnode.type;\n\t}\n\n\treturn '#text';\n}\n\n/**\n * Used to keep track of the currently rendered `vnode` and print it\n * in debug messages.\n */\nlet renderStack = [];\n\n/**\n * Keep track of the current owners. An owner describes a component\n * which was responsible to render a specific `vnode`. This exclude\n * children that are passed via `props.children`, because they belong\n * to the parent owner.\n *\n * ```jsx\n * const Foo = props => <div>{props.children}</div> // div's owner is Foo\n * const Bar = props => {\n *   return (\n *     <Foo><span /></Foo> // Foo's owner is Bar, span's owner is Bar\n *   )\n * }\n * ```\n *\n * Note: A `vnode` may be hoisted to the root scope due to compiler\n * optimiztions. In these cases the owner will be different.\n */\nlet ownerStack = [];\n\nconst ownerMap = new WeakMap();\n\n/**\n * Get the currently rendered `vnode`\n * @returns {import('./internal').VNode | null}\n */\nexport function getCurrentVNode() {\n\treturn renderStack.length > 0 ? renderStack[renderStack.length - 1] : null;\n}\n\n/**\n * If the user doesn't have `@babel/plugin-transform-react-jsx-source`\n * somewhere in his tool chain we can't print the filename and source\n * location of a component. In that case we just omit that, but we'll\n * print a helpful message to the console, notifying the user of it.\n */\nlet showJsxSourcePluginWarning = true;\n\n/**\n * Check if a `vnode` is a possible owner.\n * @param {import('./internal').VNode} vnode\n */\nfunction isPossibleOwner(vnode) {\n\treturn typeof vnode.type == 'function' && vnode.type != Fragment;\n}\n\n/**\n * Return the component stack that was captured up to this point.\n * @param {import('./internal').VNode} vnode\n * @returns {string}\n */\nexport function getOwnerStack(vnode) {\n\tconst stack = [vnode];\n\tlet next = vnode;\n\twhile ((next = ownerMap.get(next)) != null) {\n\t\tstack.push(next);\n\t}\n\n\treturn stack.reduce((acc, owner) => {\n\t\tacc += `  in ${getDisplayName(owner)}`;\n\n\t\tconst source = owner.__source;\n\t\tif (source) {\n\t\t\tacc += ` (at ${source.fileName}:${source.lineNumber})`;\n\t\t} else if (showJsxSourcePluginWarning) {\n\t\t\tconsole.warn(\n\t\t\t\t'Add @babel/plugin-transform-react-jsx-source to get a more detailed component stack. Note that you should not add it to production builds of your App for bundle size reasons.'\n\t\t\t);\n\t\t}\n\t\tshowJsxSourcePluginWarning = false;\n\n\t\treturn (acc += '\\n');\n\t}, '');\n}\n\n/**\n * Setup code to capture the component trace while rendering. Note that\n * we cannot simply traverse `vnode._parent` upwards, because we have some\n * debug messages for `this.setState` where the `vnode` is `undefined`.\n */\nexport function setupComponentStack() {\n\tlet oldDiff = options._diff;\n\tlet oldDiffed = options.diffed;\n\tlet oldRoot = options._root;\n\tlet oldVNode = options.vnode;\n\tlet oldRender = options._render;\n\n\toptions.diffed = vnode => {\n\t\tif (isPossibleOwner(vnode)) {\n\t\t\townerStack.pop();\n\t\t}\n\t\trenderStack.pop();\n\t\tif (oldDiffed) oldDiffed(vnode);\n\t};\n\n\toptions._diff = vnode => {\n\t\tif (isPossibleOwner(vnode)) {\n\t\t\trenderStack.push(vnode);\n\t\t}\n\t\tif (oldDiff) oldDiff(vnode);\n\t};\n\n\toptions._root = (vnode, parent) => {\n\t\townerStack = [];\n\t\tif (oldRoot) oldRoot(vnode, parent);\n\t};\n\n\toptions.vnode = vnode => {\n\t\townerMap.set(\n\t\t\tvnode,\n\t\t\townerStack.length > 0 ? ownerStack[ownerStack.length - 1] : null\n\t\t);\n\t\tif (oldVNode) oldVNode(vnode);\n\t};\n\n\toptions._render = vnode => {\n\t\tif (isPossibleOwner(vnode)) {\n\t\t\townerStack.push(vnode);\n\t\t}\n\n\t\tif (oldRender) oldRender(vnode);\n\t};\n}\n\n/**\n * Return the component stack that was captured up to this point.\n * @returns {string}\n */\nexport function captureOwnerStack() {\n\treturn getOwnerStack(getCurrentVNode());\n}\n"
  },
  {
    "path": "debug/src/constants.js",
    "content": "export const ELEMENT_NODE = 1;\nexport const DOCUMENT_NODE = 9;\nexport const DOCUMENT_FRAGMENT_NODE = 11;\n"
  },
  {
    "path": "debug/src/debug.js",
    "content": "import { checkPropTypes } from './check-props';\nimport { options, Component } from 'preact';\nimport {\n\tELEMENT_NODE,\n\tDOCUMENT_NODE,\n\tDOCUMENT_FRAGMENT_NODE\n} from './constants';\nimport {\n\tgetOwnerStack,\n\tsetupComponentStack,\n\tgetCurrentVNode,\n\tgetDisplayName\n} from './component-stack';\nimport { isNaN } from './util';\n\nconst isWeakMapSupported = typeof WeakMap == 'function';\n\n/**\n * @param {import('./internal').VNode} vnode\n * @returns {Array<string>}\n */\nfunction getDomChildren(vnode) {\n\tlet domChildren = [];\n\n\tif (!vnode._children) return domChildren;\n\n\tvnode._children.forEach(child => {\n\t\tif (child && typeof child.type === 'function') {\n\t\t\tdomChildren.push.apply(domChildren, getDomChildren(child));\n\t\t} else if (child && typeof child.type === 'string') {\n\t\t\tdomChildren.push(child.type);\n\t\t}\n\t});\n\n\treturn domChildren;\n}\n\n/**\n * @param {import('./internal').VNode} parent\n * @returns {string}\n */\nfunction getClosestDomNodeParentName(parent) {\n\tif (!parent) return '';\n\tif (typeof parent.type == 'function') {\n\t\tif (parent._parent == null) {\n\t\t\tif (parent._dom != null && parent._dom.parentNode != null) {\n\t\t\t\treturn parent._dom.parentNode.localName;\n\t\t\t}\n\t\t\treturn '';\n\t\t}\n\t\treturn getClosestDomNodeParentName(parent._parent);\n\t}\n\treturn /** @type {string} */ (parent.type);\n}\n\nexport function initDebug() {\n\tsetupComponentStack();\n\n\tlet hooksAllowed = false;\n\n\t/* eslint-disable no-console */\n\tlet oldBeforeDiff = options._diff;\n\tlet oldDiffed = options.diffed;\n\tlet oldVnode = options.vnode;\n\tlet oldRender = options._render;\n\tlet oldCatchError = options._catchError;\n\tlet oldRoot = options._root;\n\tlet oldHook = options._hook;\n\tconst warnedComponents = !isWeakMapSupported\n\t\t? null\n\t\t: {\n\t\t\t\tuseEffect: new WeakMap(),\n\t\t\t\tuseLayoutEffect: new WeakMap(),\n\t\t\t\tlazyPropTypes: new WeakMap()\n\t\t\t};\n\tconst deprecations = [];\n\n\toptions._catchError = (error, vnode, oldVNode, errorInfo) => {\n\t\tlet component = vnode && vnode._component;\n\t\tif (component && typeof error.then == 'function') {\n\t\t\tconst promise = error;\n\t\t\terror = new Error(\n\t\t\t\t`Missing Suspense. The throwing component was: ${getDisplayName(vnode)}`\n\t\t\t);\n\n\t\t\tlet parent = vnode;\n\t\t\tfor (; parent; parent = parent._parent) {\n\t\t\t\tif (parent._component && parent._component._childDidSuspend) {\n\t\t\t\t\terror = promise;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We haven't recovered and we know at this point that there is no\n\t\t\t// Suspense component higher up in the tree\n\t\t\tif (error instanceof Error) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\terrorInfo = errorInfo || {};\n\t\t\terrorInfo.componentStack = getOwnerStack(vnode);\n\t\t\toldCatchError(error, vnode, oldVNode, errorInfo);\n\n\t\t\t// when an error was handled by an ErrorBoundary we will nonetheless emit an error\n\t\t\t// event on the window object. This is to make up for react compatibility in dev mode\n\t\t\t// and thus make the Next.js dev overlay work.\n\t\t\tif (typeof error.then != 'function') {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tthrow e;\n\t\t}\n\t};\n\n\toptions._root = (vnode, parentNode) => {\n\t\tif (!parentNode) {\n\t\t\tthrow new Error(\n\t\t\t\t'Undefined parent passed to render(), this is the second argument.\\n' +\n\t\t\t\t\t'Check if the element is available in the DOM/has the correct id.'\n\t\t\t);\n\t\t}\n\n\t\tlet isValid;\n\t\tswitch (parentNode.nodeType) {\n\t\t\tcase ELEMENT_NODE:\n\t\t\tcase DOCUMENT_FRAGMENT_NODE:\n\t\t\tcase DOCUMENT_NODE:\n\t\t\t\tisValid = true;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tisValid = false;\n\t\t}\n\n\t\tif (!isValid) {\n\t\t\tlet componentName = getDisplayName(vnode);\n\t\t\tthrow new Error(\n\t\t\t\t`Expected a valid HTML node as a second argument to render.\tReceived ${parentNode} instead: render(<${componentName} />, ${parentNode});`\n\t\t\t);\n\t\t}\n\n\t\tif (oldRoot) oldRoot(vnode, parentNode);\n\t};\n\n\toptions._diff = vnode => {\n\t\tlet { type } = vnode;\n\n\t\thooksAllowed = true;\n\n\t\tif (type === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t'Undefined component passed to createElement()\\n\\n' +\n\t\t\t\t\t'You likely forgot to export your component or might have mixed up default and named imports' +\n\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t);\n\t\t} else if (type != null && typeof type == 'object') {\n\t\t\tif (type._children !== undefined && type._dom !== undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid type passed to createElement(): ${type}\\n\\n` +\n\t\t\t\t\t\t'Did you accidentally pass a JSX literal as JSX twice?\\n\\n' +\n\t\t\t\t\t\t`  let My${getDisplayName(vnode)} = ${serializeVNode(type)};\\n` +\n\t\t\t\t\t\t`  let vnode = <My${getDisplayName(vnode)} />;\\n\\n` +\n\t\t\t\t\t\t'This usually happens when you export a JSX literal and not the component.' +\n\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new Error(\n\t\t\t\t'Invalid type passed to createElement(): ' +\n\t\t\t\t\t(Array.isArray(type) ? 'array' : type)\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\tvnode.ref !== undefined &&\n\t\t\ttypeof vnode.ref != 'function' &&\n\t\t\ttypeof vnode.ref != 'object' &&\n\t\t\t!('$$typeof' in vnode) // allow string refs when preact-compat is installed\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Component's \"ref\" property should be a function, or an object created ` +\n\t\t\t\t\t`by createRef(), but got [${typeof vnode.ref}] instead\\n` +\n\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t);\n\t\t}\n\n\t\tif (typeof vnode.type == 'string') {\n\t\t\tfor (const key in vnode.props) {\n\t\t\t\tif (\n\t\t\t\t\tkey[0] === 'o' &&\n\t\t\t\t\tkey[1] === 'n' &&\n\t\t\t\t\ttypeof vnode.props[key] != 'function' &&\n\t\t\t\t\tvnode.props[key] != null\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Component's \"${key}\" property should be a function, ` +\n\t\t\t\t\t\t\t`but got [${typeof vnode.props[key]}] instead\\n` +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check prop-types if available\n\t\tif (typeof vnode.type == 'function' && vnode.type.propTypes) {\n\t\t\tif (\n\t\t\t\tvnode.type.displayName === 'Lazy' &&\n\t\t\t\twarnedComponents &&\n\t\t\t\t!warnedComponents.lazyPropTypes.has(vnode.type)\n\t\t\t) {\n\t\t\t\tconst m =\n\t\t\t\t\t'PropTypes are not supported on lazy(). Use propTypes on the wrapped component itself. ';\n\t\t\t\ttry {\n\t\t\t\t\tconst lazyVNode = vnode.type();\n\t\t\t\t\twarnedComponents.lazyPropTypes.set(vnode.type, true);\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\tm + `Component wrapped in lazy() is ${getDisplayName(lazyVNode)}`\n\t\t\t\t\t);\n\t\t\t\t} catch (promise) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\tm + \"We will log the wrapped component's name once it is loaded.\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* eslint-disable-next-line */\n\t\t\tconst { ref: _ref, ...props } = vnode.props;\n\n\t\t\tcheckPropTypes(\n\t\t\t\tvnode.type.propTypes,\n\t\t\t\tprops,\n\t\t\t\t'prop',\n\t\t\t\tgetDisplayName(vnode),\n\t\t\t\t() => getOwnerStack(vnode)\n\t\t\t);\n\t\t}\n\n\t\tif (oldBeforeDiff) oldBeforeDiff(vnode);\n\t};\n\n\tlet renderCount = 0;\n\tlet currentComponent;\n\toptions._render = vnode => {\n\t\tif (oldRender) {\n\t\t\toldRender(vnode);\n\t\t}\n\t\thooksAllowed = true;\n\n\t\tconst nextComponent = vnode._component;\n\t\tif (nextComponent === currentComponent) {\n\t\t\trenderCount++;\n\t\t} else {\n\t\t\trenderCount = 1;\n\t\t}\n\n\t\tif (renderCount >= 25) {\n\t\t\tthrow new Error(\n\t\t\t\t`Too many re-renders. This is limited to prevent an infinite loop ` +\n\t\t\t\t\t`which may lock up your browser. The component causing this is: ${getDisplayName(\n\t\t\t\t\t\tvnode\n\t\t\t\t\t)}`\n\t\t\t);\n\t\t}\n\n\t\tcurrentComponent = nextComponent;\n\t};\n\n\toptions._hook = (comp, index, type) => {\n\t\tif (!comp || !hooksAllowed) {\n\t\t\tthrow new Error('Hook can only be invoked from render methods.');\n\t\t}\n\n\t\tif (oldHook) oldHook(comp, index, type);\n\t};\n\n\t// Ideally we'd want to print a warning once per component, but we\n\t// don't have access to the vnode that triggered it here. As a\n\t// compromise and to avoid flooding the console with warnings we\n\t// print each deprecation warning only once.\n\tconst warn = (property, message) => ({\n\t\tget() {\n\t\t\tconst key = 'get' + property + message;\n\t\t\tif (deprecations && deprecations.indexOf(key) < 0) {\n\t\t\t\tdeprecations.push(key);\n\t\t\t\tconsole.warn(`getting vnode.${property} is deprecated, ${message}`);\n\t\t\t}\n\t\t},\n\t\tset() {\n\t\t\tconst key = 'set' + property + message;\n\t\t\tif (deprecations && deprecations.indexOf(key) < 0) {\n\t\t\t\tdeprecations.push(key);\n\t\t\t\tconsole.warn(`setting vnode.${property} is not allowed, ${message}`);\n\t\t\t}\n\t\t}\n\t});\n\n\tconst deprecatedAttributes = {\n\t\tnodeName: warn('nodeName', 'use vnode.type'),\n\t\tattributes: warn('attributes', 'use vnode.props'),\n\t\tchildren: warn('children', 'use vnode.props.children')\n\t};\n\n\tconst deprecatedProto = Object.create({}, deprecatedAttributes);\n\n\toptions.vnode = vnode => {\n\t\tconst props = vnode.props;\n\t\tif (\n\t\t\tvnode.type !== null &&\n\t\t\tprops != null &&\n\t\t\t('__source' in props || '__self' in props)\n\t\t) {\n\t\t\tconst newProps = (vnode.props = {});\n\t\t\tfor (let i in props) {\n\t\t\t\tconst v = props[i];\n\t\t\t\tif (i === '__source') vnode.__source = v;\n\t\t\t\telse if (i === '__self') vnode.__self = v;\n\t\t\t\telse newProps[i] = v;\n\t\t\t}\n\t\t}\n\n\t\t// eslint-disable-next-line\n\t\tvnode.__proto__ = deprecatedProto;\n\t\tif (oldVnode) oldVnode(vnode);\n\t};\n\n\toptions.diffed = vnode => {\n\t\tconst { type, _parent: parent } = vnode;\n\t\t// Check if the user passed plain objects as children. Note that we cannot\n\t\t// move this check into `options.vnode` because components can receive\n\t\t// children in any shape they want (e.g.\n\t\t// `<MyJSONFormatter>{{ foo: 123, bar: \"abc\" }}</MyJSONFormatter>`).\n\t\t// Putting this check in `options.diffed` ensures that\n\t\t// `vnode._children` is set and that we only validate the children\n\t\t// that were actually rendered.\n\t\tif (vnode._children) {\n\t\t\tvnode._children.forEach(child => {\n\t\t\t\tif (typeof child === 'object' && child && child.type === undefined) {\n\t\t\t\t\tconst keys = Object.keys(child).join(',');\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Objects are not valid as a child. Encountered an object with the keys {${keys}}.` +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif (vnode._component === currentComponent) {\n\t\t\trenderCount = 0;\n\t\t}\n\n\t\tif (\n\t\t\ttypeof type === 'string' &&\n\t\t\t(isTableElement(type) ||\n\t\t\t\ttype === 'p' ||\n\t\t\t\ttype === 'a' ||\n\t\t\t\ttype === 'button')\n\t\t) {\n\t\t\t// Avoid false positives when Preact only partially rendered the\n\t\t\t// HTML tree. Whilst we attempt to include the outer DOM in our\n\t\t\t// validation, this wouldn't work on the server for\n\t\t\t// `preact-render-to-string`. There we'd otherwise flood the terminal\n\t\t\t// with false positives, which we'd like to avoid.\n\t\t\tlet domParentName = getClosestDomNodeParentName(parent);\n\t\t\tif (domParentName !== '' && isTableElement(type)) {\n\t\t\t\tif (\n\t\t\t\t\ttype === 'table' &&\n\t\t\t\t\t// Tables can be nested inside each other if it's inside a cell.\n\t\t\t\t\t// See https://developer.mozilla.org/en-US/docs/Learn/HTML/Tables/Advanced#nesting_tables\n\t\t\t\t\tdomParentName !== 'td' &&\n\t\t\t\t\tisTableElement(domParentName)\n\t\t\t\t) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Improper nesting of table. Your <table> should not have a table-node parent.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t} else if (\n\t\t\t\t\t(type === 'thead' || type === 'tfoot' || type === 'tbody') &&\n\t\t\t\t\tdomParentName !== 'table'\n\t\t\t\t) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Improper nesting of table. Your <thead/tbody/tfoot> should have a <table> parent.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t} else if (\n\t\t\t\t\ttype === 'tr' &&\n\t\t\t\t\tdomParentName !== 'thead' &&\n\t\t\t\t\tdomParentName !== 'tfoot' &&\n\t\t\t\t\tdomParentName !== 'tbody'\n\t\t\t\t) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Improper nesting of table. Your <tr> should have a <thead/tbody/tfoot> parent.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t} else if (type === 'td' && domParentName !== 'tr') {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Improper nesting of table. Your <td> should have a <tr> parent.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t} else if (type === 'th' && domParentName !== 'tr') {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Improper nesting of table. Your <th> should have a <tr>.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (type === 'p') {\n\t\t\t\tlet illegalDomChildrenTypes = getDomChildren(vnode).filter(childType =>\n\t\t\t\t\tILLEGAL_PARAGRAPH_CHILD_ELEMENTS.test(childType)\n\t\t\t\t);\n\t\t\t\tif (illegalDomChildrenTypes.length) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Improper nesting of paragraph. Your <p> should not have ' +\n\t\t\t\t\t\t\tillegalDomChildrenTypes.join(', ') +\n\t\t\t\t\t\t\t' as child-elements.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (type === 'a' || type === 'button') {\n\t\t\t\tif (getDomChildren(vnode).indexOf(type) !== -1) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t`Improper nesting of interactive content. Your <${type}>` +\n\t\t\t\t\t\t\t` should not have other ${type === 'a' ? 'anchor' : 'button'}` +\n\t\t\t\t\t\t\t' tags as child-elements.' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\thooksAllowed = false;\n\n\t\tif (oldDiffed) oldDiffed(vnode);\n\n\t\tif (vnode._children != null) {\n\t\t\tconst keys = [];\n\t\t\tfor (let i = 0; i < vnode._children.length; i++) {\n\t\t\t\tconst child = vnode._children[i];\n\t\t\t\tif (!child || child.key == null) continue;\n\n\t\t\t\tconst key = child.key;\n\t\t\t\tif (keys.indexOf(key) !== -1) {\n\t\t\t\t\tconsole.error(\n\t\t\t\t\t\t'Following component has two or more children with the ' +\n\t\t\t\t\t\t\t`same key attribute: \"${key}\". This may cause glitches and misbehavior ` +\n\t\t\t\t\t\t\t'in rendering process. Component: \\n\\n' +\n\t\t\t\t\t\t\tserializeVNode(vnode) +\n\t\t\t\t\t\t\t`\\n\\n${getOwnerStack(vnode)}`\n\t\t\t\t\t);\n\n\t\t\t\t\t// Break early to not spam the console\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tkeys.push(key);\n\t\t\t}\n\t\t}\n\n\t\tif (vnode._component != null && vnode._component.__hooks != null) {\n\t\t\t// Validate that none of the hooks in this component contain arguments that are NaN.\n\t\t\t// This is a common mistake that can be hard to debug, so we want to catch it early.\n\t\t\tconst hooks = vnode._component.__hooks._list;\n\t\t\tif (hooks) {\n\t\t\t\tfor (let i = 0; i < hooks.length; i += 1) {\n\t\t\t\t\tconst hook = hooks[i];\n\t\t\t\t\tif (hook._args) {\n\t\t\t\t\t\tfor (let j = 0; j < hook._args.length; j++) {\n\t\t\t\t\t\t\tconst arg = hook._args[j];\n\t\t\t\t\t\t\tif (isNaN(arg)) {\n\t\t\t\t\t\t\t\tconst componentName = getDisplayName(vnode);\n\t\t\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t\t\t`Invalid argument passed to hook. Hooks should not be called with NaN in the dependency array. Hook index ${i} in component ${componentName} was called with NaN.`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\nconst setState = Component.prototype.setState;\nComponent.prototype.setState = function (update, callback) {\n\tif (this._vnode == null) {\n\t\t// `this._vnode` will be `null` during componentWillMount. But it\n\t\t// is perfectly valid to call `setState` during cWM. So we\n\t\t// need an additional check to verify that we are dealing with a\n\t\t// call inside constructor.\n\t\tif (this.state == null) {\n\t\t\tconsole.warn(\n\t\t\t\t`Calling \"this.setState\" inside the constructor of a component is a ` +\n\t\t\t\t\t`no-op and might be a bug in your application. Instead, set ` +\n\t\t\t\t\t`\"this.state = {}\" directly.\\n\\n${getOwnerStack(getCurrentVNode())}`\n\t\t\t);\n\t\t}\n\t}\n\n\treturn setState.call(this, update, callback);\n};\n\nfunction isTableElement(type) {\n\treturn (\n\t\ttype === 'table' ||\n\t\ttype === 'tfoot' ||\n\t\ttype === 'tbody' ||\n\t\ttype === 'thead' ||\n\t\ttype === 'td' ||\n\t\ttype === 'tr' ||\n\t\ttype === 'th'\n\t);\n}\n\nconst ILLEGAL_PARAGRAPH_CHILD_ELEMENTS =\n\t/^(address|article|aside|blockquote|details|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|main|menu|nav|ol|p|pre|search|section|table|ul)$/;\n\nconst forceUpdate = Component.prototype.forceUpdate;\nComponent.prototype.forceUpdate = function (callback) {\n\tif (this._vnode == null) {\n\t\tconsole.warn(\n\t\t\t`Calling \"this.forceUpdate\" inside the constructor of a component is a ` +\n\t\t\t\t`no-op and might be a bug in your application.\\n\\n${getOwnerStack(\n\t\t\t\t\tgetCurrentVNode()\n\t\t\t\t)}`\n\t\t);\n\t} else if (this._parentDom == null) {\n\t\tconsole.warn(\n\t\t\t`Can't call \"this.forceUpdate\" on an unmounted component. This is a no-op, ` +\n\t\t\t\t`but it indicates a memory leak in your application. To fix, cancel all ` +\n\t\t\t\t`subscriptions and asynchronous tasks in the componentWillUnmount method.` +\n\t\t\t\t`\\n\\n${getOwnerStack(this._vnode)}`\n\t\t);\n\t}\n\treturn forceUpdate.call(this, callback);\n};\n\n/**\n * Serialize a vnode tree to a string\n * @param {import('./internal').VNode} vnode\n * @returns {string}\n */\nexport function serializeVNode(vnode) {\n\tlet { props } = vnode;\n\tlet name = getDisplayName(vnode);\n\n\tlet attrs = '';\n\tfor (let prop in props) {\n\t\tif (props.hasOwnProperty(prop) && prop !== 'children') {\n\t\t\tlet value = props[prop];\n\n\t\t\t// If it is an object but doesn't have toString(), use Object.toString\n\t\t\tif (typeof value == 'function') {\n\t\t\t\tvalue = `function ${value.displayName || value.name}() {}`;\n\t\t\t}\n\n\t\t\tvalue =\n\t\t\t\tObject(value) === value && !value.toString\n\t\t\t\t\t? Object.prototype.toString.call(value)\n\t\t\t\t\t: value + '';\n\n\t\t\tattrs += ` ${prop}=${JSON.stringify(value)}`;\n\t\t}\n\t}\n\n\tlet children = props.children;\n\treturn `<${name}${attrs}${\n\t\tchildren && children.length ? '>..</' + name + '>' : ' />'\n\t}`;\n}\n\noptions._hydrationMismatch = (newVNode, excessDomChildren) => {\n\tconst { type } = newVNode;\n\tconst availableTypes = excessDomChildren\n\t\t.map(child => child && child.localName)\n\t\t.filter(Boolean);\n\tconsole.error(\n\t\t`Expected a DOM node of type \"${type}\" but found \"${availableTypes.join(', ')}\" as available DOM-node(s), this is caused by the SSR'd HTML containing different DOM-nodes compared to the hydrated one.\\n\\n${getOwnerStack(newVNode)}`\n\t);\n};\n"
  },
  {
    "path": "debug/src/index.d.ts",
    "content": "import { VNode } from '../../src/index';\n\n/**\n * Return the component stack that was captured up to this point.\n */\nexport function captureOwnerStack(): string;\n\n/**\n * Get the currently rendered `vnode`\n */\nexport function getCurrentVNode(): VNode | null;\n\n/**\n * Get human readable name of the component/dom node\n */\nexport function getDisplayName(vnode: VNode): string;\n\n/**\n * Return the component stack that was captured up to this point.\n */\nexport function getOwnerStack(vnode: VNode): string;\n\n/**\n * Setup code to capture the component trace while rendering. Note that\n * we cannot simply traverse `vnode._parent` upwards, because we have some\n * debug messages for `this.setState` where the `vnode` is `undefined`.\n */\nexport function setupComponentStack(): void;\n\n/**\n * Reset the history of which prop type warnings have been logged.\n */\nexport function resetPropWarnings(): void;\n"
  },
  {
    "path": "debug/src/index.js",
    "content": "import { initDebug } from './debug';\nimport 'preact/devtools';\n\ninitDebug();\n\nexport { resetPropWarnings } from './check-props';\n\nexport {\n\tcaptureOwnerStack,\n\tgetCurrentVNode,\n\tgetDisplayName,\n\tgetOwnerStack,\n\tsetupComponentStack\n} from './component-stack';\n"
  },
  {
    "path": "debug/src/internal.d.ts",
    "content": "import { Component, PreactElement, VNode, Options } from '../../src/internal';\n\nexport { Component, PreactElement, VNode, Options };\n\nexport interface DevtoolsInjectOptions {\n\t/** 1 = DEV, 0 = production */\n\tbundleType: 1 | 0;\n\t/** The devtools enable different features for different versions of react */\n\tversion: string;\n\t/** Informative string, currently unused in the devtools  */\n\trendererPackageName: string;\n\t/** Find the root dom node of a vnode */\n\tfindHostInstanceByFiber(vnode: VNode): HTMLElement | null;\n\t/** Find the closest vnode given a dom node */\n\tfindFiberByHostInstance(instance: HTMLElement): VNode | null;\n}\n\nexport interface DevtoolsUpdater {\n\tsetState(objOrFn: any): void;\n\tforceUpdate(): void;\n\tsetInState(path: Array<string | number>, value: any): void;\n\tsetInProps(path: Array<string | number>, value: any): void;\n\tsetInContext(): void;\n}\n\nexport type NodeType = 'Composite' | 'Native' | 'Wrapper' | 'Text';\n\nexport interface DevtoolData {\n\tnodeType: NodeType;\n\t// Component type\n\ttype: any;\n\tname: string;\n\tref: any;\n\tkey: string | number;\n\tupdater: DevtoolsUpdater | null;\n\ttext: string | number | null;\n\tstate: any;\n\tprops: any;\n\tchildren: VNode[] | string | number | null;\n\tpublicInstance: PreactElement | Text | Component;\n\tmemoizedInteractions: any[];\n\n\tactualDuration: number;\n\tactualStartTime: number;\n\ttreeBaseDuration: number;\n}\n\nexport type EventType =\n\t| 'unmount'\n\t| 'rootCommitted'\n\t| 'root'\n\t| 'mount'\n\t| 'update'\n\t| 'updateProfileTimes';\n\nexport interface DevtoolsEvent {\n\tdata?: DevtoolData;\n\tinternalInstance: VNode;\n\trenderer: string;\n\ttype: EventType;\n}\n\nexport interface DevtoolsHook {\n\t_renderers: Record<string, any>;\n\t_roots: Set<VNode>;\n\ton(ev: string, listener: () => void): void;\n\temit(ev: string, data?: object): void;\n\thelpers: Record<string, any>;\n\tgetFiberRoots(rendererId: string): Set<any>;\n\tinject(config: DevtoolsInjectOptions): string;\n\tonCommitFiberRoot(rendererId: string, root: VNode): void;\n\tonCommitFiberUnmount(rendererId: string, vnode: VNode): void;\n}\n\nexport interface DevtoolsWindow extends Window {\n\t/**\n\t * If the devtools extension is installed it will inject this object into\n\t * the dom. This hook handles all communications between preact and the\n\t * devtools panel.\n\t */\n\t__REACT_DEVTOOLS_GLOBAL_HOOK__?: DevtoolsHook;\n}\n"
  },
  {
    "path": "debug/src/util.js",
    "content": "export const assign = Object.assign;\n\nexport function isNaN(value) {\n\treturn value !== value;\n}\n"
  },
  {
    "path": "debug/test/browser/component-stack-2.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport 'preact/debug';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\n// This test is not part of component-stack.test.js to avoid it being\n// transpiled with '@babel/plugin-transform-react-jsx-source' enabled.\n\ndescribe('component stack', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tlet errors = [];\n\tlet warnings = [];\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\n\t\terrors = [];\n\t\twarnings = [];\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\tconsole.error.mockRestore();\n\t\tconsole.warn.mockRestore();\n\t\tteardown(scratch);\n\t});\n\n\tit('should print a warning when \"@babel/plugin-transform-react-jsx-source\" is not installed', () => {\n\t\tfunction Foo() {\n\t\t\treturn <Thrower />;\n\t\t}\n\n\t\tclass Thrower extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.setState({ foo: 1 });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\n\t\texpect(\n\t\t\twarnings[0].indexOf('@babel/plugin-transform-react-jsx-source') > -1\n\t\t).to.equal(true);\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/component-stack.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport 'preact/debug';\nimport { vi } from 'vitest';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('component stack', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tlet errors = [];\n\tlet warnings = [];\n\n\tconst getStack = arr => arr[0].split('\\n\\n')[1];\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\n\t\terrors = [];\n\t\twarnings = [];\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\tvi.resetAllMocks();\n\t\tteardown(scratch);\n\t});\n\n\tit('should print component stack', () => {\n\t\tfunction Foo() {\n\t\t\treturn <Thrower />;\n\t\t}\n\n\t\tclass Thrower extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.setState({ foo: 1 });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\n\t\t// This has a JSX transform warning, so we need to remove it\n\t\twarnings.shift();\n\t\tlet lines = getStack(warnings).split('\\n');\n\t\texpect(lines[0].indexOf('Thrower') > -1).to.equal(true);\n\t\texpect(lines[1].indexOf('Foo') > -1).to.equal(true);\n\t});\n\n\tit('should only print owners', () => {\n\t\tfunction Foo(props) {\n\t\t\treturn <div>{props.children}</div>;\n\t\t}\n\n\t\tfunction Bar() {\n\t\t\treturn (\n\t\t\t\t<Foo>\n\t\t\t\t\t<Thrower />\n\t\t\t\t</Foo>\n\t\t\t);\n\t\t}\n\n\t\tclass Thrower extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<table>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<tr>foo</tr>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</table>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Bar />, scratch);\n\n\t\tlet lines = getStack(errors).split('\\n');\n\t\texpect(lines[0].indexOf('tr') > -1).to.equal(true);\n\t\texpect(lines[1].indexOf('Thrower') > -1).to.equal(true);\n\t\texpect(lines[2].indexOf('Bar') > -1).to.equal(true);\n\t});\n\n\tit('should not print a warning when \"@babel/plugin-transform-react-jsx-source\" is installed', () => {\n\t\tfunction Thrower() {\n\t\t\tthrow new Error('foo');\n\t\t}\n\n\t\ttry {\n\t\t\trender(<Thrower />, scratch);\n\t\t} catch {}\n\n\t\texpect(warnings.join(' ')).to.not.include(\n\t\t\t'@babel/plugin-transform-react-jsx-source'\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/debug-compat.test.jsx",
    "content": "import { createElement, render, createRef } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport './fakeDevTools';\nimport 'preact/debug';\nimport * as PropTypes from 'prop-types';\n\n// eslint-disable-next-line no-duplicate-imports\nimport { resetPropWarnings } from 'preact/debug';\nimport { forwardRef, createPortal } from 'preact/compat';\nimport { vi } from 'vitest';\n\nconst h = createElement;\n\ndescribe('debug compat', () => {\n\tlet scratch;\n\tlet root;\n\tlet errors = [];\n\tlet warnings = [];\n\n\tbeforeEach(() => {\n\t\terrors = [];\n\t\twarnings = [];\n\t\tscratch = setupScratch();\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\n\t\troot = document.createElement('div');\n\t\tdocument.body.appendChild(root);\n\t});\n\n\tafterEach(() => {\n\t\t/** @type {*} */\n\t\tconsole.error.mockRestore();\n\t\tconsole.warn.mockRestore();\n\t\tteardown(scratch);\n\n\t\tdocument.body.removeChild(root);\n\t});\n\n\tdescribe('portals', () => {\n\t\tit('should not throw an invalid render argument for a portal.', () => {\n\t\t\tfunction Foo(props) {\n\t\t\t\treturn <div>{createPortal(props.children, root)}</div>;\n\t\t\t}\n\t\t\texpect(() => render(<Foo>foobar</Foo>, scratch)).not.to.throw();\n\t\t});\n\t});\n\n\tdescribe('PropTypes', () => {\n\t\tbeforeEach(() => {\n\t\t\tresetPropWarnings();\n\t\t});\n\n\t\tit('should not fail if ref is passed to comp wrapped in forwardRef', () => {\n\t\t\t// This test ensures compat with airbnb/prop-types-exact, mui exact prop types util, etc.\n\n\t\t\tconst Foo = forwardRef(function Foo(props, ref) {\n\t\t\t\treturn <h1 ref={ref}>{props.text}</h1>;\n\t\t\t});\n\n\t\t\tFoo.propTypes = {\n\t\t\t\ttext: PropTypes.string.isRequired,\n\t\t\t\tref(props) {\n\t\t\t\t\tif ('ref' in props) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'ref should not be passed to prop-types valiation!'\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst ref = createRef();\n\n\t\t\trender(<Foo ref={ref} text=\"123\" />, scratch);\n\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\n\t\t\texpect(ref.current).to.not.be.undefined;\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/debug-hooks.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport { useState, useEffect } from 'preact/hooks';\nimport 'preact/debug';\nimport { act } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('debug with hooks', () => {\n\tlet scratch;\n\tlet errors = [];\n\tlet warnings = [];\n\n\tbeforeEach(() => {\n\t\terrors = [];\n\t\twarnings = [];\n\t\tscratch = setupScratch();\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\tconsole.error.mockRestore();\n\t\tconsole.warn.mockRestore();\n\t\tteardown(scratch);\n\t});\n\n\tit('should throw an error when using a hook outside a render', () => {\n\t\tclass Foo extends Component {\n\t\t\tcomponentWillMount() {\n\t\t\t\tuseState();\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn <p>test</p>;\n\t\t\t}\n\t\t}\n\t\tconst fn = () =>\n\t\t\tact(() =>\n\t\t\t\trender(\n\t\t\t\t\t<Foo>\n\t\t\t\t\t\t<App />\n\t\t\t\t\t</Foo>,\n\t\t\t\t\tscratch\n\t\t\t\t)\n\t\t\t);\n\t\texpect(fn).to.throw(/Hook can only be invoked from render/);\n\t});\n\n\tit('should throw an error when invoked outside of a component', () => {\n\t\tfunction foo() {\n\t\t\tuseEffect(() => {}); // Pretend to use a hook\n\t\t\treturn <p>test</p>;\n\t\t}\n\n\t\tconst fn = () =>\n\t\t\tact(() => {\n\t\t\t\trender(foo(), scratch);\n\t\t\t});\n\t\texpect(fn).to.throw(/Hook can only be invoked from render/);\n\t});\n\n\tit('should throw an error when invoked outside of a component before render', () => {\n\t\tfunction Foo(props) {\n\t\t\tuseEffect(() => {}); // Pretend to use a hook\n\t\t\treturn props.children;\n\t\t}\n\n\t\tconst fn = () =>\n\t\t\tact(() => {\n\t\t\t\tuseState();\n\t\t\t\trender(<Foo>Hello!</Foo>, scratch);\n\t\t\t});\n\t\texpect(fn).to.throw(/Hook can only be invoked from render/);\n\t});\n\n\tit('should throw an error when invoked outside of a component after render', () => {\n\t\tfunction Foo(props) {\n\t\t\tuseEffect(() => {}); // Pretend to use a hook\n\t\t\treturn props.children;\n\t\t}\n\n\t\tconst fn = () =>\n\t\t\tact(() => {\n\t\t\t\trender(<Foo>Hello!</Foo>, scratch);\n\t\t\t\tuseState();\n\t\t\t});\n\t\texpect(fn).to.throw(/Hook can only be invoked from render/);\n\t});\n\n\tit('should throw an error when invoked inside an effect callback', () => {\n\t\tfunction Foo(props) {\n\t\t\tuseEffect(() => {\n\t\t\t\tuseState();\n\t\t\t});\n\t\t\treturn props.children;\n\t\t}\n\n\t\tconst fn = () =>\n\t\t\tact(() => {\n\t\t\t\trender(<Foo>Hello!</Foo>, scratch);\n\t\t\t});\n\t\texpect(fn).to.throw(/Hook can only be invoked from render/);\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/debug-suspense.test.jsx",
    "content": "import { createElement, render, lazy, Suspense } from 'preact/compat';\nimport 'preact/debug';\nimport { setupRerender } from 'preact/test-utils';\nimport {\n\tsetupScratch,\n\tteardown,\n\tserializeHtml\n} from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('debug with suspense', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\tlet rerender;\n\tlet errors = [];\n\tlet warnings = [];\n\n\tbeforeEach(() => {\n\t\terrors = [];\n\t\twarnings = [];\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\tconsole.error.mockRestore();\n\t\tconsole.warn.mockRestore();\n\t\tteardown(scratch);\n\t});\n\n\tit('should throw on missing <Suspense>', () => {\n\t\tfunction Foo() {\n\t\t\tthrow Promise.resolve();\n\t\t}\n\n\t\texpect(() => render(<Foo />, scratch)).to.throw;\n\t});\n\n\tit('should throw an error when using lazy and missing Suspense', () => {\n\t\tconst Foo = () => <div>Foo</div>;\n\t\tconst LazyComp = lazy(\n\t\t\t() => new Promise(resolve => resolve({ default: Foo }))\n\t\t);\n\t\tconst fn = () => {\n\t\t\trender(<LazyComp />, scratch);\n\t\t};\n\n\t\texpect(fn).to.throw(/Missing Suspense/gi);\n\t});\n\n\tdescribe('PropTypes', () => {\n\t\tit('should validate propTypes inside lazy()', () => {\n\t\t\tfunction Baz(props) {\n\t\t\t\treturn <h1>{props.unhappy}</h1>;\n\t\t\t}\n\n\t\t\tBaz.propTypes = {\n\t\t\t\tunhappy: function alwaysThrows(obj, key) {\n\t\t\t\t\tif (obj[key] === 'signal') throw Error('got prop inside lazy()');\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst loader = Promise.resolve({ default: Baz });\n\t\t\tconst LazyBaz = lazy(() => loader);\n\n\t\t\tconst suspense = (\n\t\t\t\t<Suspense fallback={<div>fallback...</div>}>\n\t\t\t\t\t<LazyBaz unhappy=\"signal\" />\n\t\t\t\t</Suspense>\n\t\t\t);\n\t\t\trender(suspense, scratch);\n\t\t\trerender(); // render fallback\n\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t\texpect(serializeHtml(scratch)).to.equal('<div>fallback...</div>');\n\n\t\t\treturn loader.then(() => {\n\t\t\t\trerender();\n\t\t\t\texpect(errors.length).to.equal(1);\n\t\t\t\texpect(errors[0].includes('got prop')).to.equal(true);\n\t\t\t\texpect(serializeHtml(scratch)).to.equal('<h1>signal</h1>');\n\t\t\t});\n\t\t});\n\n\t\tdescribe('warn for PropTypes on lazy()', () => {\n\t\t\tit('should log the function name', () => {\n\t\t\t\tconst loader = Promise.resolve({\n\t\t\t\t\tdefault: function MyLazyLoaded() {\n\t\t\t\t\t\treturn <div>Hi there</div>;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconst FakeLazy = lazy(() => loader);\n\t\t\t\tFakeLazy.propTypes = {};\n\t\t\t\tconst suspense = (\n\t\t\t\t\t<Suspense fallback={<div>fallback...</div>}>\n\t\t\t\t\t\t<FakeLazy />\n\t\t\t\t\t</Suspense>\n\t\t\t\t);\n\t\t\t\trender(suspense, scratch);\n\t\t\t\trerender(); // Render fallback\n\n\t\t\t\texpect(serializeHtml(scratch)).to.equal('<div>fallback...</div>');\n\n\t\t\t\treturn loader.then(() => {\n\t\t\t\t\trerender();\n\t\t\t\t\texpect(console.warn).toHaveBeenCalledTimes(2);\n\t\t\t\t\texpect(warnings[1].includes('MyLazyLoaded')).to.equal(true);\n\t\t\t\t\texpect(serializeHtml(scratch)).to.equal('<div>Hi there</div>');\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tit('should log the displayName', () => {\n\t\t\t\tfunction MyLazyLoadedComponent() {\n\t\t\t\t\treturn <div>Hi there</div>;\n\t\t\t\t}\n\t\t\t\tMyLazyLoadedComponent.displayName = 'HelloLazy';\n\t\t\t\tconst loader = Promise.resolve({ default: MyLazyLoadedComponent });\n\t\t\t\tconst FakeLazy = lazy(() => loader);\n\t\t\t\tFakeLazy.propTypes = {};\n\t\t\t\tconst suspense = (\n\t\t\t\t\t<Suspense fallback={<div>fallback...</div>}>\n\t\t\t\t\t\t<FakeLazy />\n\t\t\t\t\t</Suspense>\n\t\t\t\t);\n\t\t\t\trender(suspense, scratch);\n\t\t\t\trerender(); // Render fallback\n\n\t\t\t\texpect(serializeHtml(scratch)).to.equal('<div>fallback...</div>');\n\n\t\t\t\treturn loader.then(() => {\n\t\t\t\t\trerender();\n\t\t\t\t\texpect(console.warn).toHaveBeenCalledTimes(2);\n\t\t\t\t\texpect(warnings[1].includes('HelloLazy')).to.equal(true);\n\t\t\t\t\texpect(serializeHtml(scratch)).to.equal('<div>Hi there</div>');\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tit(\"should not log a component if lazy loader's Promise rejects\", () => {\n\t\t\t\tconst loader = Promise.reject(new Error('Hey there'));\n\t\t\t\tconst FakeLazy = lazy(() => loader);\n\t\t\t\tFakeLazy.propTypes = {};\n\t\t\t\trender(\n\t\t\t\t\t<Suspense fallback={<div>fallback...</div>}>\n\t\t\t\t\t\t<FakeLazy />\n\t\t\t\t\t</Suspense>,\n\t\t\t\t\tscratch\n\t\t\t\t);\n\t\t\t\trerender(); // Render fallback\n\n\t\t\t\texpect(serializeHtml(scratch)).to.equal('<div>fallback...</div>');\n\n\t\t\t\treturn loader.catch(() => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\trerender();\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Ignore the loader's bubbling error\n\t\t\t\t\t}\n\n\t\t\t\t\t// Called once on initial render, and again when promise rejects\n\t\t\t\t\texpect(console.warn).toHaveBeenCalledTimes(2);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tit(\"should not log a component if lazy's loader throws\", () => {\n\t\t\t\tconst FakeLazy = lazy(() => {\n\t\t\t\t\tthrow new Error('Hello');\n\t\t\t\t});\n\t\t\t\tFakeLazy.propTypes = {};\n\t\t\t\tlet error;\n\t\t\t\ttry {\n\t\t\t\t\trender(\n\t\t\t\t\t\t<Suspense fallback={<div>fallback...</div>}>\n\t\t\t\t\t\t\t<FakeLazy />\n\t\t\t\t\t\t</Suspense>,\n\t\t\t\t\t\tscratch\n\t\t\t\t\t);\n\t\t\t\t} catch (e) {\n\t\t\t\t\terror = e;\n\t\t\t\t}\n\n\t\t\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\t\t\texpect(error).not.to.be.undefined;\n\t\t\t\texpect(error.message).to.eql('Hello');\n\t\t\t});\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/debug.options.test.jsx",
    "content": "import {\n\tvnodeSpy,\n\trootSpy,\n\tbeforeDiffSpy,\n\thookSpy,\n\tafterDiffSpy,\n\tcatchErrorSpy\n} from '../../../test/_util/optionSpies';\n\nimport { createElement, render, Component } from 'preact';\nimport { useState } from 'preact/hooks';\nimport { setupRerender } from 'preact/test-utils';\nimport 'preact/debug';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('debug options', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t/** @type {(count: number) => void} */\n\tlet setCount;\n\n\t/** @type {import('vitest').VitestUtils | undefined} */\n\tlet clock;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\n\t\tvnodeSpy.mockClear();\n\t\trootSpy.mockClear();\n\t\tbeforeDiffSpy.mockClear();\n\t\thookSpy.mockClear();\n\t\tafterDiffSpy.mockClear();\n\t\tcatchErrorSpy.mockClear();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tif (clock) vi.useRealTimers();\n\t});\n\n\tclass ClassApp extends Component {\n\t\tconstructor() {\n\t\t\tsuper();\n\t\t\tthis.state = { count: 0 };\n\t\t\tsetCount = count => this.setState({ count });\n\t\t}\n\n\t\trender() {\n\t\t\treturn <div>{this.state.count}</div>;\n\t\t}\n\t}\n\n\tit('should call old options on mount', () => {\n\t\trender(<ClassApp />, scratch);\n\n\t\texpect(vnodeSpy).toHaveBeenCalled();\n\t\texpect(rootSpy).toHaveBeenCalled();\n\t\texpect(beforeDiffSpy).toHaveBeenCalled();\n\t\texpect(afterDiffSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options on update', () => {\n\t\trender(<ClassApp />, scratch);\n\n\t\tsetCount(1);\n\t\trerender();\n\n\t\texpect(vnodeSpy).toHaveBeenCalled();\n\t\texpect(rootSpy).toHaveBeenCalled();\n\t\texpect(beforeDiffSpy).toHaveBeenCalled();\n\t\texpect(afterDiffSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options on unmount', () => {\n\t\trender(<ClassApp />, scratch);\n\t\trender(null, scratch);\n\n\t\texpect(vnodeSpy).toHaveBeenCalled();\n\t\texpect(rootSpy).toHaveBeenCalled();\n\t\texpect(beforeDiffSpy).toHaveBeenCalled();\n\t\texpect(afterDiffSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old hook options for hook components', () => {\n\t\tfunction HookApp() {\n\t\t\tconst [count, realSetCount] = useState(0);\n\t\t\tsetCount = realSetCount;\n\t\t\treturn <div>{count}</div>;\n\t\t}\n\n\t\trender(<HookApp />, scratch);\n\n\t\texpect(hookSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options on error', () => {\n\t\tconst e = new Error('test');\n\t\tclass ErrorApp extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { error: true };\n\t\t\t}\n\t\t\tcomponentDidCatch() {\n\t\t\t\tthis.setState({ error: false });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <Throw error={this.state.error} />;\n\t\t\t}\n\t\t}\n\n\t\tfunction Throw({ error }) {\n\t\t\tif (error) {\n\t\t\t\tthrow e;\n\t\t\t} else {\n\t\t\t\treturn <div>no error</div>;\n\t\t\t}\n\t\t}\n\n\t\tclock = vi.useFakeTimers();\n\n\t\trender(<ErrorApp />, scratch);\n\t\trerender();\n\n\t\texpect(catchErrorSpy).toHaveBeenCalled();\n\n\t\t// we expect to throw after setTimeout to trigger a window.onerror\n\t\t// this is to ensure react compat (i.e. with next.js' dev overlay)\n\t\texpect(() => clock.advanceTimersByTime(0)).to.throw(e);\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/debug.test.jsx",
    "content": "import {\n\tcreateElement,\n\trender,\n\tcreateRef,\n\tComponent,\n\tFragment,\n\thydrate\n} from 'preact';\nimport { useState } from 'preact/hooks';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport './fakeDevTools';\nimport 'preact/debug';\nimport { setupRerender } from 'preact/test-utils';\nimport { vi } from 'vitest';\n\nconst h = createElement;\n\ndescribe('debug', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\tlet errors = [];\n\tlet warnings = [];\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\terrors = [];\n\t\twarnings = [];\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\t/** @type {*} */\n\t\tconsole.error.mockRestore();\n\t\tconsole.warn.mockRestore();\n\t\tteardown(scratch);\n\t});\n\n\tit('should initialize devtools', () => {\n\t\texpect(window.__PREACT_DEVTOOLS__.attachPreact).toHaveBeenCalled();\n\t});\n\n\tit('should print an error on rendering on undefined parent', () => {\n\t\tlet fn = () => render(<div />, undefined);\n\t\texpect(fn).to.throw(/render/);\n\t});\n\n\tit('should print an error on rendering on invalid parent', () => {\n\t\tlet fn = () => render(<div />, 6);\n\t\texpect(fn).to.throw(/valid HTML node/);\n\t\texpect(fn).to.throw(/<div/);\n\t});\n\n\tit('should print an error with (function) component name when available', () => {\n\t\tconst App = () => <div />;\n\t\tlet fn = () => render(<App />, 6);\n\t\texpect(fn).to.throw(/<App/);\n\t\texpect(fn).to.throw(/6/);\n\n\t\tfn = () => render(<App />, {});\n\t\texpect(fn).to.throw(/<App/);\n\t\texpect(fn).to.throw(/[object Object]/);\n\n\t\tfn = () => render(<Fragment />, 'badroot');\n\t\texpect(fn).to.throw(/<Fragment/);\n\t\texpect(fn).to.throw(/badroot/);\n\t});\n\n\tit('should print an error with (class) component name when available', () => {\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn <div />;\n\t\t\t}\n\t\t}\n\t\tlet fn = () => render(<App />, 6);\n\t\texpect(fn).to.throw(/<App/);\n\t});\n\n\tit('should print an error on undefined component', () => {\n\t\tlet fn = () => render(h(undefined), scratch);\n\t\texpect(fn).to.throw(/createElement/);\n\t});\n\n\tit('should print an error on invalid object component', () => {\n\t\tlet fn = () => render(h({}), scratch);\n\t\texpect(fn).to.throw(/createElement/);\n\t});\n\n\tit('should print an error when component is an array', () => {\n\t\tlet fn = () => render(h([<div />]), scratch);\n\t\texpect(fn).to.throw(/createElement/);\n\t});\n\n\tit('should print an error on double jsx conversion', () => {\n\t\tlet Foo = <div />;\n\t\tlet fn = () => render(h(<Foo />), scratch);\n\t\texpect(fn).to.throw(/JSX twice/);\n\t});\n\n\tit('should add __source to the vnode in debug mode.', () => {\n\t\tconst vnode = h('div', {\n\t\t\t__source: {\n\t\t\t\tfileName: 'div.jsx',\n\t\t\t\tlineNumber: 3\n\t\t\t}\n\t\t});\n\t\texpect(vnode.__source).to.deep.equal({\n\t\t\tfileName: 'div.jsx',\n\t\t\tlineNumber: 3\n\t\t});\n\t\texpect(vnode.props.__source).to.be.undefined;\n\t});\n\n\tit('should add __self to the vnode in debug mode.', () => {\n\t\tconst vnode = h('div', {\n\t\t\t__self: {}\n\t\t});\n\t\texpect(vnode.__self).to.deep.equal({});\n\t\texpect(vnode.props.__self).to.be.undefined;\n\t});\n\n\tit('should warn when accessing certain attributes', () => {\n\t\tconst vnode = h('div', null);\n\n\t\t// Push into an array to avoid empty statements being dead code eliminated\n\t\tconst res = [];\n\t\tres.push(vnode);\n\t\tres.push(vnode.attributes);\n\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\texpect(console.warn.mock.calls[0]).to.match(/use vnode.props/);\n\t\tres.push(vnode.nodeName);\n\t\texpect(console.warn).toHaveBeenCalledTimes(2);\n\t\texpect(console.warn.mock.calls[1]).to.match(/use vnode.type/);\n\t\tres.push(vnode.children);\n\t\texpect(console.warn).toHaveBeenCalledTimes(3);\n\t\texpect(console.warn.mock.calls[2]).to.match(/use vnode.props.children/);\n\n\t\t// Should only warn once\n\t\tres.push(vnode.attributes);\n\t\texpect(console.warn).toHaveBeenCalledTimes(3);\n\t\tres.push(vnode.nodeName);\n\t\texpect(console.warn).toHaveBeenCalledTimes(3);\n\t\tres.push(vnode.children);\n\t\texpect(console.warn).toHaveBeenCalledTimes(3);\n\n\t\tvnode.attributes = {};\n\t\texpect(console.warn.mock.calls[3]).to.match(/use vnode.props/);\n\t\tvnode.nodeName = '';\n\t\texpect(console.warn.mock.calls[4]).to.match(/use vnode.type/);\n\t\tvnode.children = [];\n\t\texpect(console.warn.mock.calls[5]).to.match(/use vnode.props.children/);\n\n\t\t// Should only warn once\n\t\tvnode.attributes = {};\n\t\texpect(console.warn.mock.calls.length).to.equal(6);\n\t\tvnode.nodeName = '';\n\t\texpect(console.warn.mock.calls.length).to.equal(6);\n\t\tvnode.children = [];\n\t\texpect(console.warn.mock.calls.length).to.equal(6);\n\n\t\t// Mark res as used, otherwise it will be dead code eliminated\n\t\texpect(res.length).to.equal(7);\n\t});\n\n\tit('should warn when calling setState inside the constructor', () => {\n\t\tclass Foo extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.setState({ foo: true });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\texpect(console.warn.mock.calls[0]).to.match(/no-op/);\n\t});\n\n\tit('should NOT warn when calling setState inside the cWM', () => {\n\t\tclass Foo extends Component {\n\t\t\tcomponentWillMount() {\n\t\t\t\tthis.setState({ foo: true });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(console.warn).not.toHaveBeenCalled();\n\t});\n\n\tit('should warn when calling forceUpdate inside the constructor', () => {\n\t\tclass Foo extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\texpect(console.warn.mock.calls[0]).to.match(/no-op/);\n\t});\n\n\tit('should warn when calling forceUpdate on an unmounted Component', () => {\n\t\tlet forceUpdate;\n\n\t\tclass Foo extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tforceUpdate = () => this.forceUpdate();\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>foo</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\tforceUpdate();\n\t\texpect(console.warn).not.toHaveBeenCalled();\n\n\t\trender(null, scratch);\n\n\t\tforceUpdate();\n\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\texpect(console.warn.mock.calls[0]).to.match(/no-op/);\n\t});\n\n\tit('should print an error when child is a plain object', () => {\n\t\tlet fn = () => render(<div>{{}}</div>, scratch);\n\t\texpect(fn).to.throw(/not valid/);\n\t});\n\n\tit('should print an error on invalid refs', () => {\n\t\tlet fn = () => render(<div ref=\"a\" />, scratch);\n\t\texpect(fn).to.throw(/createRef/);\n\t});\n\n\tit('should not print for null as a handler', () => {\n\t\tlet fn = () => render(<div onclick={null} />, scratch);\n\t\texpect(fn).not.to.throw();\n\t});\n\n\tit('should not print for undefined as a handler', () => {\n\t\tlet fn = () => render(<div onclick={undefined} />, scratch);\n\t\texpect(fn).not.to.throw();\n\t});\n\n\tit('should not print for attributes starting with on for Components', () => {\n\t\tconst Comp = () => <p>online</p>;\n\t\tlet fn = () => render(<Comp online={false} />, scratch);\n\t\texpect(fn).not.to.throw();\n\t});\n\n\tit('should print an error on invalid handler', () => {\n\t\tlet fn = () => render(<div onclick=\"a\" />, scratch);\n\t\texpect(fn).to.throw(/\"onclick\" property should be a function/);\n\t});\n\n\tit('should NOT print an error on valid refs', () => {\n\t\tlet noop = () => {};\n\t\trender(<div ref={noop} />, scratch);\n\n\t\tlet ref = createRef();\n\t\trender(<div ref={ref} />, scratch);\n\t\texpect(console.error).not.toHaveBeenCalled();\n\t});\n\n\tit('throws an error if a component rerenders too many times', () => {\n\t\tlet rerenderCount = 0;\n\t\tfunction TestComponent({ loop = false }) {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tif (loop) {\n\t\t\t\tsetCount(count + 1);\n\t\t\t}\n\n\t\t\tif (count > 30) {\n\t\t\t\texpect.fail(\n\t\t\t\t\t'Repeated rerenders did not cause the expected error. This test is failing.'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trerenderCount += 1;\n\t\t\treturn <div />;\n\t\t}\n\n\t\texpect(() => {\n\t\t\trender(\n\t\t\t\t<Fragment>\n\t\t\t\t\t<TestComponent />\n\t\t\t\t\t<TestComponent loop />\n\t\t\t\t</Fragment>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t}).to.throw(/Too many re-renders/);\n\t\t// 1 for first TestComponent + 24 for second TestComponent\n\t\texpect(rerenderCount).to.equal(25);\n\t});\n\n\tit('does not throw an error if a component renders many times in different cycles', () => {\n\t\tlet set;\n\t\tfunction TestComponent() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tset = () => setCount(count + 1);\n\t\t\treturn <div>{count}</div>;\n\t\t}\n\n\t\trender(<TestComponent />, scratch);\n\t\tfor (let i = 0; i < 30; i++) {\n\t\t\tset();\n\t\t\trerender();\n\t\t}\n\t\texpect(scratch.innerHTML).to.equal('<div>30</div>');\n\t});\n\n\tdescribe('duplicate keys', () => {\n\t\tconst List = props => <ul>{props.children}</ul>;\n\t\tconst ListItem = props => <li>{props.children}</li>;\n\n\t\tit('should print an error on duplicate keys with DOM nodes', () => {\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\t<span key=\"a\" />\n\t\t\t\t\t<span key=\"a\" />\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should allow distinct object keys', () => {\n\t\t\tconst A = { is: 'A' };\n\t\t\tconst B = { is: 'B' };\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\t<span key={A} />\n\t\t\t\t\t<span key={B} />\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should print an error for duplicate object keys', () => {\n\t\t\tconst A = { is: 'A' };\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\t<span key={A} />\n\t\t\t\t\t<span key={A} />\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should print an error on duplicate keys with Components', () => {\n\t\t\tfunction App() {\n\t\t\t\treturn (\n\t\t\t\t\t<List>\n\t\t\t\t\t\t<ListItem key=\"a\">a</ListItem>\n\t\t\t\t\t\t<ListItem key=\"b\">b</ListItem>\n\t\t\t\t\t\t<ListItem key=\"b\">d</ListItem>\n\t\t\t\t\t\t<ListItem key=\"d\">d</ListItem>\n\t\t\t\t\t</List>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should print an error on duplicate keys with Fragments', () => {\n\t\t\tfunction App() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<List key=\"list\">\n\t\t\t\t\t\t\t<ListItem key=\"a\">a</ListItem>\n\t\t\t\t\t\t\t<ListItem key=\"b\">b</ListItem>\n\t\t\t\t\t\t\t<Fragment key=\"b\">\n\t\t\t\t\t\t\t\t{/* Should be okay to duplicate keys since these are inside a Fragment */}\n\t\t\t\t\t\t\t\t<ListItem key=\"a\">c</ListItem>\n\t\t\t\t\t\t\t\t<ListItem key=\"b\">d</ListItem>\n\t\t\t\t\t\t\t\t<ListItem key=\"c\">e</ListItem>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t<ListItem key=\"f\">f</ListItem>\n\t\t\t\t\t\t</List>\n\t\t\t\t\t\t<div key=\"list\">sibling</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledTimes(2);\n\t\t});\n\t});\n\n\tdescribe('table markup', () => {\n\t\tit('missing <tbody>/<thead>/<tfoot>/<table>', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td>hi</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</div>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('missing <table> with <thead>', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>hi</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t</div>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('missing <table> with <tbody>', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>hi</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tbody>\n\t\t\t\t</div>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('missing <table> with <tfoot>', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<tfoot>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>hi</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tfoot>\n\t\t\t\t</div>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('missing <tr>', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<td>Hi</td>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('missing <tr> with td component', () => {\n\t\t\tconst Cell = ({ children }) => <td>{children}</td>;\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<Cell>Hi</Cell>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('missing <tr> with th component', () => {\n\t\t\tconst Cell = ({ children }) => <th>{children}</th>;\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<Cell>Hi</Cell>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('Should accept <td> instead of <th> in <thead>', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>Hi</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('Accepts well formed table with TD components', () => {\n\t\t\tconst Cell = ({ children }) => <td>{children}</td>;\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Head</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>Body</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tbody>\n\t\t\t\t\t<tfoot>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<Cell>Body</Cell>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tfoot>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('Accepts well formed table', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<thead>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Head</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>Body</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tbody>\n\t\t\t\t\t<tfoot>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>Body</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tfoot>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('Accepts minimal well formed table', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>Head</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>Body</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t);\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should include DOM parents outside of root node', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<tr>\n\t\t\t\t\t<td>Head</td>\n\t\t\t\t</tr>\n\t\t\t);\n\n\t\t\tconst table = document.createElement('table');\n\t\t\tscratch.appendChild(table);\n\t\t\trender(<Table />, table);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should warn for improper nested table', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<table />\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t);\n\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('accepts valid nested tables', () => {\n\t\t\tconst Table = () => (\n\t\t\t\t<table>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<th>foo</th>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td id=\"nested\">\n\t\t\t\t\t\t\t\t<table>\n\t\t\t\t\t\t\t\t\t<tbody>\n\t\t\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t\t\t<td>cell1</td>\n\t\t\t\t\t\t\t\t\t\t\t<td>cell2</td>\n\t\t\t\t\t\t\t\t\t\t\t<td>cell3</td>\n\t\t\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t\t\t</tbody>\n\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t<td>bar</td>\n\t\t\t\t\t\t</tr>\n\t\t\t\t\t</tbody>\n\t\t\t\t</table>\n\t\t\t);\n\n\t\t\trender(<Table />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tdescribe('paragraph nesting', () => {\n\t\tit('should not warn a regular text paragraph', () => {\n\t\t\tconst Paragraph = () => <p>Hello world</p>;\n\n\t\t\trender(<Paragraph />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should not crash for an empty pragraph', () => {\n\t\t\tconst Paragraph = () => <p />;\n\n\t\t\trender(<Paragraph />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under a paragraph', () => {\n\t\t\tconst Paragraph = () => (\n\t\t\t\t<p>\n\t\t\t\t\t<h1>Hello world</h1>\n\t\t\t\t</p>\n\t\t\t);\n\n\t\t\trender(<Paragraph />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under a paragraph with a parent', () => {\n\t\t\tconst Paragraph = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<p>\n\t\t\t\t\t\t<div>Hello world</div>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t);\n\n\t\t\trender(<Paragraph />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under a paragraph as func', () => {\n\t\t\tconst Title = ({ children }) => <h1>{children}</h1>;\n\t\t\tconst Paragraph = () => (\n\t\t\t\t<p>\n\t\t\t\t\t<Title>Hello world</Title>\n\t\t\t\t</p>\n\t\t\t);\n\n\t\t\trender(<Paragraph />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should not warn for nesting span under a paragraph', () => {\n\t\t\tconst Paragraph = () => (\n\t\t\t\t<p>\n\t\t\t\t\t<span>Hello world</span>\n\t\t\t\t</p>\n\t\t\t);\n\n\t\t\trender(<Paragraph />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tdescribe('button nesting', () => {\n\t\tit('should not warn on a regular button', () => {\n\t\t\tconst Button = () => <button>Hello world</button>;\n\n\t\t\trender(<Button />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under a button', () => {\n\t\t\tconst Button = () => (\n\t\t\t\t<button>\n\t\t\t\t\t<button>Hello world</button>\n\t\t\t\t</button>\n\t\t\t);\n\n\t\t\trender(<Button />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under a button as func', () => {\n\t\t\tconst ButtonChild = ({ children }) => <button>{children}</button>;\n\t\t\tconst Button = () => (\n\t\t\t\t<button>\n\t\t\t\t\t<ButtonChild>Hello world</ButtonChild>\n\t\t\t\t</button>\n\t\t\t);\n\n\t\t\trender(<Button />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should not warn for nesting non-interactive content under a button', () => {\n\t\t\tconst Button = () => (\n\t\t\t\t<button>\n\t\t\t\t\t<span>Hello </span>\n\t\t\t\t\t<a>World</a>\n\t\t\t\t</button>\n\t\t\t);\n\n\t\t\trender(<Button />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tdescribe('anchor nesting', () => {\n\t\tit('should not warn a regular anchor', () => {\n\t\t\tconst Anchor = () => <a>Hello world</a>;\n\n\t\t\trender(<Anchor />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under an anchor', () => {\n\t\t\tconst Anchor = () => (\n\t\t\t\t<a>\n\t\t\t\t\t<a>Hello world</a>\n\t\t\t\t</a>\n\t\t\t);\n\n\t\t\trender(<Anchor />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should warn for nesting illegal dom-nodes under an anchor as func', () => {\n\t\t\tconst AnchorChild = ({ children }) => <a>{children}</a>;\n\t\t\tconst Anchor = () => (\n\t\t\t\t<a>\n\t\t\t\t\t<AnchorChild>Hello world</AnchorChild>\n\t\t\t\t</a>\n\t\t\t);\n\n\t\t\trender(<Anchor />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should not warn for nesting non-interactive content under an anchor', () => {\n\t\t\tconst Anchor = () => (\n\t\t\t\t<a>\n\t\t\t\t\t<span>Hello </span>\n\t\t\t\t\t<button>World</button>\n\t\t\t\t</a>\n\t\t\t);\n\n\t\t\trender(<Anchor />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tdescribe('Hydration mismatches', () => {\n\t\tit('Should warn us for a node mismatch', () => {\n\t\t\tscratch.innerHTML = '<div><span>foo</span>/div>';\n\t\t\tconst App = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<p>foo</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t\thydrate(<App />, scratch);\n\t\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\t\texpect(console.error).toHaveBeenCalledWith(\n\t\t\t\texpect.objectContaining(\n\t\t\t\t\t/Expected a DOM node of type \"p\" but found \"span\"/\n\t\t\t\t)\n\t\t\t);\n\t\t});\n\n\t\tit('Should not warn for a text-node mismatch', () => {\n\t\t\tscratch.innerHTML = '<div>foo bar baz/div>';\n\t\t\tconst App = () => (\n\t\t\t\t<div>\n\t\t\t\t\tfoo {'bar'} {'baz'}\n\t\t\t\t</div>\n\t\t\t);\n\t\t\thydrate(<App />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('Should not warn for a well-formed tree', () => {\n\t\t\tscratch.innerHTML = '<div><span>foo</span><span>bar</span></div>';\n\t\t\tconst App = () => (\n\t\t\t\t<div>\n\t\t\t\t\t<span>foo</span>\n\t\t\t\t\t<span>bar</span>\n\t\t\t\t</div>\n\t\t\t);\n\t\t\thydrate(<App />, scratch);\n\t\t\texpect(console.error).not.toHaveBeenCalled();\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/fakeDevTools.js",
    "content": "window.__PREACT_DEVTOOLS__ = { attachPreact: vi.fn() };\n"
  },
  {
    "path": "debug/test/browser/prop-types.test.js",
    "content": "import { createElement, render } from 'preact';\nimport {\n\tsetupScratch,\n\tteardown,\n\tserializeHtml\n} from '../../../test/_util/helpers';\nimport './fakeDevTools';\nimport { resetPropWarnings } from 'preact/debug';\nimport * as PropTypes from 'prop-types';\nimport { jsxDEV as jsxDev } from 'preact/jsx-runtime';\nimport { vi } from 'vitest';\n\ndescribe('PropTypes', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\tlet errors = [];\n\tlet warnings = [];\n\n\tbeforeEach(() => {\n\t\terrors = [];\n\t\twarnings = [];\n\t\tscratch = setupScratch();\n\t\tvi.spyOn(console, 'error').mockImplementation(e => errors.push(e));\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\t/** @type {*} */\n\t\tconsole.error.mockRestore();\n\t\tconsole.warn.mockRestore();\n\t\tteardown(scratch);\n\t});\n\n\tbeforeEach(() => {\n\t\tresetPropWarnings();\n\t});\n\n\tit(\"should fail if props don't match prop-types\", () => {\n\t\tfunction Foo(props) {\n\t\t\treturn jsxDev('h1', { children: props.text });\n\t\t}\n\n\t\tFoo.propTypes = {\n\t\t\ttext: PropTypes.string.isRequired\n\t\t};\n\n\t\trender(\n\t\t\tjsxDev(\n\t\t\t\tFoo,\n\t\t\t\t{ text: 123 },\n\t\t\t\tnull,\n\t\t\t\t// @ts-ignore\n\t\t\t\tfalse,\n\t\t\t\t// @ts-ignore\n\t\t\t\t{ fileName: './debug/test/browser/debug.test.js', lineNumber: 41 },\n\t\t\t\t// @ts-ignore\n\t\t\t\t'self'\n\t\t\t),\n\t\t\tscratch\n\t\t);\n\n\t\texpect(console.error).toHaveBeenCalledOnce();\n\n\t\t// The message here may change when the \"prop-types\" library is updated,\n\t\t// but we check it exactly to make sure all parameters were supplied\n\t\t// correctly.\n\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\texpect(console.error).toHaveBeenCalledWith(\n\t\t\texpect.stringMatching(\n\t\t\t\t/^Failed prop type: Invalid prop `text` of type `number` supplied to `Foo`, expected `string`\\.\\n {2}in Foo \\(at (.*)[/\\\\]debug[/\\\\]test[/\\\\]browser[/\\\\]debug\\.test\\.js:[0-9]+\\)$/m\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should only log a given prop type error once', () => {\n\t\tfunction Foo(props) {\n\t\t\treturn jsxDev('h1', { children: props.text });\n\t\t}\n\n\t\tFoo.propTypes = {\n\t\t\ttext: PropTypes.string.isRequired,\n\t\t\tcount: PropTypes.number\n\t\t};\n\n\t\t// Trigger the same error twice. The error should only be logged\n\t\t// once.\n\t\trender(jsxDev(Foo, { text: 123 }), scratch);\n\t\trender(jsxDev(Foo, { text: 123 }), scratch);\n\n\t\texpect(console.error).toHaveBeenCalledOnce();\n\n\t\t// Trigger a different error. This should result in a new log\n\t\t// message.\n\t\tconsole.error.mockClear();\n\t\trender(jsxDev(Foo, { text: 'ok', count: '123' }), scratch);\n\t\texpect(console.error).toHaveBeenCalledOnce();\n\t});\n\n\tit('should render with error logged when validator gets signal and throws exception', () => {\n\t\tfunction Baz(props) {\n\t\t\treturn jsxDev('h1', { children: props.unhappy });\n\t\t}\n\n\t\tBaz.propTypes = {\n\t\t\tunhappy: function alwaysThrows(obj, key) {\n\t\t\t\tif (obj[key] === 'signal') throw Error('got prop');\n\t\t\t}\n\t\t};\n\n\t\trender(jsxDev(Baz, { unhappy: 'signal' }), scratch);\n\n\t\texpect(console.error).toHaveBeenCalledOnce();\n\t\texpect(errors[0].includes('got prop')).to.equal(true);\n\t\texpect(serializeHtml(scratch)).to.equal('<h1>signal</h1>');\n\t});\n\n\tit('should not print to console when types are correct', () => {\n\t\tfunction Bar(props) {\n\t\t\treturn jsxDev('h1', { children: props.text });\n\t\t}\n\n\t\tBar.propTypes = {\n\t\t\ttext: PropTypes.string.isRequired\n\t\t};\n\n\t\trender(jsxDev(Bar, { text: 'foo' }), scratch);\n\t\texpect(console.error).not.toHaveBeenCalled();\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/serializeVNode.test.jsx",
    "content": "import { createElement, Component } from 'preact';\nimport { serializeVNode } from '../../src/debug';\n\ndescribe('serializeVNode', () => {\n\tit(\"should prefer a function component's displayName\", () => {\n\t\tfunction Foo() {\n\t\t\treturn <div />;\n\t\t}\n\t\tFoo.displayName = 'Bar';\n\n\t\texpect(serializeVNode(<Foo />)).to.equal('<Bar />');\n\t});\n\n\tit(\"should prefer a class component's displayName\", () => {\n\t\tclass Bar extends Component {\n\t\t\trender() {\n\t\t\t\treturn <div />;\n\t\t\t}\n\t\t}\n\t\tBar.displayName = 'Foo';\n\n\t\texpect(serializeVNode(<Bar />)).to.equal('<Foo />');\n\t});\n\n\tit('should serialize vnodes without children', () => {\n\t\texpect(serializeVNode(<br />)).to.equal('<br />');\n\t});\n\n\tit('should serialize vnodes with children', () => {\n\t\texpect(serializeVNode(<div>Hello World</div>)).to.equal('<div>..</div>');\n\t});\n\n\tit('should serialize components', () => {\n\t\tfunction Foo() {\n\t\t\treturn <div />;\n\t\t}\n\t\texpect(serializeVNode(<Foo />)).to.equal('<Foo />');\n\t});\n\n\tit('should serialize props', () => {\n\t\texpect(serializeVNode(<div class=\"foo\" />)).to.equal('<div class=\"foo\" />');\n\n\t\t// Ensure that we have a predictable function name. Our test runner\n\t\t// creates an all inclusive bundle per file and the identifier\n\t\t// \"noop\" may have already been used.\n\t\t// eslint-disable-next-line func-style\n\t\tlet noop = function noopFn() {};\n\t\texpect(serializeVNode(<div onClick={noop} />)).to.equal(\n\t\t\t'<div onClick=\"function noopFn() {}\" />'\n\t\t);\n\n\t\tfunction Foo(props) {\n\t\t\treturn props.foo;\n\t\t}\n\n\t\texpect(serializeVNode(<Foo foo={[1, 2, 3]} />)).to.equal(\n\t\t\t'<Foo foo=\"1,2,3\" />'\n\t\t);\n\n\t\texpect(serializeVNode(<div prop={Object.create(null)} />)).to.equal(\n\t\t\t'<div prop=\"[object Object]\" />'\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "debug/test/browser/validateHookArgs.test.jsx",
    "content": "import { createElement, render, createRef } from 'preact';\nimport {\n\tuseState,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseCallback,\n\tuseMemo,\n\tuseImperativeHandle\n} from 'preact/hooks';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport 'preact/debug';\nimport { vi } from 'vitest';\n\ndescribe('Hook argument validation', () => {\n\t/**\n\t * @param {string} name\n\t * @param {(arg: number) => void} hook\n\t */\n\tfunction validateHook(name, hook) {\n\t\tconst TestComponent = ({ initialValue }) => {\n\t\t\tconst [value, setValue] = useState(initialValue);\n\t\t\thook(value);\n\n\t\t\treturn (\n\t\t\t\t<button type=\"button\" onClick={() => setValue(NaN)}>\n\t\t\t\t\tSet to NaN\n\t\t\t\t</button>\n\t\t\t);\n\t\t};\n\n\t\tit(`should error if ${name} is mounted with NaN as an argument`, async () => {\n\t\t\trender(<TestComponent initialValue={NaN} />, scratch);\n\t\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\t\texpect(console.warn.mock.calls[0]).to.match(\n\t\t\t\t/Hooks should not be called with NaN in the dependency array/\n\t\t\t);\n\t\t});\n\n\t\tit(`should error if ${name} is updated with NaN as an argument`, async () => {\n\t\t\trender(<TestComponent initialValue={0} />, scratch);\n\n\t\t\tscratch.querySelector('button').click();\n\t\t\trerender();\n\n\t\t\texpect(console.warn).toHaveBeenCalledOnce();\n\t\t\texpect(console.warn.mock.calls[0]).to.match(\n\t\t\t\t/Hooks should not be called with NaN in the dependency array/\n\t\t\t);\n\t\t});\n\t}\n\n\t/** @type {HTMLElement} */\n\tlet scratch;\n\t/** @type {() => void} */\n\tlet rerender;\n\tlet warnings = [];\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t\twarnings = [];\n\t\tvi.spyOn(console, 'warn').mockImplementation(w => warnings.push(w));\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tconsole.warn.mockRestore();\n\t});\n\n\tvalidateHook('useEffect', arg => useEffect(() => {}, [arg]));\n\tvalidateHook('useLayoutEffect', arg => useLayoutEffect(() => {}, [arg]));\n\tvalidateHook('useCallback', arg => useCallback(() => {}, [arg]));\n\tvalidateHook('useMemo', arg => useMemo(() => {}, [arg]));\n\n\tconst ref = createRef();\n\tvalidateHook('useImperativeHandle', arg => {\n\t\tuseImperativeHandle(ref, () => undefined, [arg]);\n\t});\n});\n"
  },
  {
    "path": "demo/contenteditable.jsx",
    "content": "import { useState } from 'preact/hooks';\n\nexport default function Contenteditable() {\n\tconst [value, setValue] = useState(\"Hey there<br />I'm editable!\");\n\n\treturn (\n\t\t<div>\n\t\t\t<div>\n\t\t\t\t<button onClick={() => setValue('')}>Clear!</button>\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tborder: '1px solid gray',\n\t\t\t\t\tpadding: '8px',\n\t\t\t\t\tmargin: '8px 0',\n\t\t\t\t\tbackground: 'white'\n\t\t\t\t}}\n\t\t\t\tcontentEditable\n\t\t\t\tonInput={e => setValue(e.currentTarget.innerHTML)}\n\t\t\t\tdangerouslySetInnerHTML={{ __html: value }}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "demo/context.jsx",
    "content": "// eslint-disable-next-line no-unused-vars\nimport { Component, createContext } from 'preact';\nconst { Provider, Consumer } = createContext();\n\nclass ThemeProvider extends Component {\n\tstate = {\n\t\tvalue: this.props.value\n\t};\n\n\tonClick = () => {\n\t\tthis.setState(prev => ({\n\t\t\tvalue:\n\t\t\t\tprev.value === this.props.value ? this.props.next : this.props.value\n\t\t}));\n\t};\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<button onClick={this.onClick}>Toggle</button>\n\t\t\t\t<Provider value={this.state.value}>{this.props.children}</Provider>\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nclass Child extends Component {\n\tshouldComponentUpdate() {\n\t\treturn false;\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<p>(blocked update)</p>\n\t\t\t\t{this.props.children}\n\t\t\t</>\n\t\t);\n\t}\n}\n\nexport default class ContextDemo extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<ThemeProvider value=\"blue\" next=\"red\">\n\t\t\t\t<Child>\n\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t{data => (\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\tcurrent theme: <b>{data}</b>\n\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t<ThemeProvider value=\"black\" next=\"white\">\n\t\t\t\t\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t\t\t\t\t{data => (\n\t\t\t\t\t\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t\t\t\t\t\tcurrent sub theme: <b>{data}</b>\n\t\t\t\t\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</Consumer>\n\t\t\t\t\t\t\t\t</ThemeProvider>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Consumer>\n\t\t\t\t</Child>\n\t\t\t</ThemeProvider>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/devtools.jsx",
    "content": "import { Component, memo, Suspense, lazy } from 'react';\n\nfunction Foo() {\n\treturn <div>I'm memoed</div>;\n}\n\nfunction LazyComp() {\n\treturn <div>I'm (fake) lazy loaded</div>;\n}\n\nconst Lazy = lazy(() => Promise.resolve({ default: LazyComp }));\n\nconst Memoed = memo(Foo);\n\nexport default class DevtoolsDemo extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<h1>memo()</h1>\n\t\t\t\t<p>\n\t\t\t\t\t<b>functional component:</b>\n\t\t\t\t</p>\n\t\t\t\t<Memoed />\n\t\t\t\t<h1>lazy()</h1>\n\t\t\t\t<p>\n\t\t\t\t\t<b>functional component:</b>\n\t\t\t\t</p>\n\t\t\t\t<Suspense fallback={<div>Loading (fake) lazy loaded component...</div>}>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/fragments.jsx",
    "content": "import { Component } from 'preact';\n\nexport default class FragmentComp extends Component {\n\tstate = { number: 0 };\n\n\tcomponentDidMount() {\n\t\tsetInterval(_ => this.updateChildren(), 1000);\n\t}\n\n\tupdateChildren() {\n\t\tthis.setState(state => ({ number: state.number + 1 }));\n\t}\n\n\trender(props, state) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<div>{state.number}</div>\n\t\t\t\t<>\n\t\t\t\t\t<div>one</div>\n\t\t\t\t\t<div>{state.number}</div>\n\t\t\t\t\t<div>three</div>\n\t\t\t\t</>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"UTF-8\" />\n\t\t<link rel=\"icon\" type=\"image/svg+xml\" href=\"/vite.svg\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n\t\t<title>Preact Demo</title>\n\t</head>\n\t<body>\n\t\t<div id=\"app\"></div>\n\t\t<script type=\"module\" src=\"/index.jsx\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "demo/index.jsx",
    "content": "import { render, Component, Fragment } from 'preact';\n// import renderToString from 'preact-render-to-string';\nimport './style.scss';\nimport { Router, Link } from 'preact-router';\nimport Pythagoras from './pythagoras';\nimport Spiral from './spiral';\nimport Reorder from './reorder';\nimport Todo from './todo';\nimport Fragments from './fragments';\nimport Context from './context';\nimport installLogger from './logger';\nimport ProfilerDemo from './profiler';\nimport KeyBug from './key_bug';\nimport StateOrderBug from './stateOrderBug';\nimport PeopleBrowser from './people';\nimport StyledComp from './styled-components';\nimport { initDevTools } from 'preact/devtools/src/devtools';\nimport { initDebug } from 'preact/debug/src/debug';\nimport DevtoolsDemo from './devtools';\nimport SuspenseDemo from './suspense';\nimport Redux from './redux';\nimport TextFields from './textFields';\nimport ReduxBug from './reduxUpdate';\nimport SuspenseRouterBug from './suspense-router';\nimport NestedSuspenseBug from './nested-suspense';\nimport Contenteditable from './contenteditable';\nimport { MobXDemo } from './mobx';\nimport Zustand from './zustand';\nimport ReduxToolkit from './redux-toolkit';\n\nlet isBenchmark = /(\\/spiral|\\/pythagoras|[#&]bench)/g.test(\n\twindow.location.href\n);\nif (!isBenchmark) {\n\t// eslint-disable-next-line no-console\n\tconsole.log('Enabling devtools and debug');\n\tinitDevTools();\n\tinitDebug();\n}\n\n// mobx-state-tree fix\nwindow.setImmediate = setTimeout;\n\nclass Home extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<h1>Hello</h1>\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nclass DevtoolsWarning extends Component {\n\tonClick = () => {\n\t\twindow.location.reload();\n\t};\n\n\trender() {\n\t\treturn (\n\t\t\t<button onClick={this.onClick}>\n\t\t\t\tStart Benchmark (disables devtools)\n\t\t\t</button>\n\t\t);\n\t}\n}\n\nclass App extends Component {\n\trender({ url }) {\n\t\treturn (\n\t\t\t<div class=\"app\">\n\t\t\t\t<header>\n\t\t\t\t\t<nav>\n\t\t\t\t\t\t<Link href=\"/\" activeClassName=\"active\">\n\t\t\t\t\t\t\tHome\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/reorder\" activeClassName=\"active\">\n\t\t\t\t\t\t\tReorder\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/spiral\" activeClassName=\"active\">\n\t\t\t\t\t\t\tSpiral\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/pythagoras\" activeClassName=\"active\">\n\t\t\t\t\t\t\tPythagoras\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/todo\" activeClassName=\"active\">\n\t\t\t\t\t\t\tToDo\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/fragments\" activeClassName=\"active\">\n\t\t\t\t\t\t\tFragments\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/key_bug\" activeClassName=\"active\">\n\t\t\t\t\t\t\tKey Bug\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/profiler\" activeClassName=\"active\">\n\t\t\t\t\t\t\tProfiler\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/context\" activeClassName=\"active\">\n\t\t\t\t\t\t\tContext\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/devtools\" activeClassName=\"active\">\n\t\t\t\t\t\t\tDevtools\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/empty-fragment\" activeClassName=\"active\">\n\t\t\t\t\t\t\tEmpty Fragment\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/people\" activeClassName=\"active\">\n\t\t\t\t\t\t\tPeople Browser\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/state-order\" activeClassName=\"active\">\n\t\t\t\t\t\t\tState Order\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/styled-components\" activeClassName=\"active\">\n\t\t\t\t\t\t\tStyled Components\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/redux\" activeClassName=\"active\">\n\t\t\t\t\t\t\tRedux\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/mobx\" activeClassName=\"active\">\n\t\t\t\t\t\t\tMobX\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/suspense\" activeClassName=\"active\">\n\t\t\t\t\t\t\tSuspense / lazy\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/textfields\" activeClassName=\"active\">\n\t\t\t\t\t\t\tTextfields\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/reduxBug/1\" activeClassName=\"active\">\n\t\t\t\t\t\t\tRedux Bug\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/suspense-router\" activeClassName=\"active\">\n\t\t\t\t\t\t\tSuspense Router Bug\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/nested-suspense\" activeClassName=\"active\">\n\t\t\t\t\t\t\tNested Suspense Bug\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/contenteditable\" activeClassName=\"active\">\n\t\t\t\t\t\t\tcontenteditable\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/zustand\" activeClassName=\"active\">\n\t\t\t\t\t\t\tzustand\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t<Link href=\"/redux-toolkit\" activeClassName=\"active\">\n\t\t\t\t\t\t\tredux-toolkit\n\t\t\t\t\t\t</Link>\n\t\t\t\t\t</nav>\n\t\t\t\t</header>\n\t\t\t\t<main>\n\t\t\t\t\t<Router url={url}>\n\t\t\t\t\t\t<Home path=\"/\" />\n\t\t\t\t\t\t<StateOrderBug path=\"/state-order\" />\n\t\t\t\t\t\t<Reorder path=\"/reorder\" />\n\t\t\t\t\t\t<div path=\"/spiral\">\n\t\t\t\t\t\t\t{!isBenchmark ? <DevtoolsWarning /> : <Spiral />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div path=\"/pythagoras\">\n\t\t\t\t\t\t\t{!isBenchmark ? <DevtoolsWarning /> : <Pythagoras />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<Todo path=\"/todo\" />\n\t\t\t\t\t\t<Fragments path=\"/fragments\" />\n\t\t\t\t\t\t<ProfilerDemo path=\"/profiler\" />\n\t\t\t\t\t\t<KeyBug path=\"/key_bug\" />\n\t\t\t\t\t\t<Context path=\"/context\" />\n\t\t\t\t\t\t<DevtoolsDemo path=\"/devtools\" />\n\t\t\t\t\t\t<SuspenseDemo path=\"/suspense\" />\n\t\t\t\t\t\t<EmptyFragment path=\"/empty-fragment\" />\n\t\t\t\t\t\t<PeopleBrowser path=\"/people/:user?\" />\n\t\t\t\t\t\t<StyledComp path=\"/styled-components\" />\n\t\t\t\t\t\t<Redux path=\"/redux\" />\n\t\t\t\t\t\t<MobXDemo path=\"/mobx\" />\n\t\t\t\t\t\t<TextFields path=\"/textfields\" />\n\t\t\t\t\t\t<ReduxBug path=\"/reduxBug/:start\" />\n\t\t\t\t\t\t<SuspenseRouterBug path=\"/suspense-router\" />\n\t\t\t\t\t\t<NestedSuspenseBug path=\"/nested-suspense\" />\n\t\t\t\t\t\t<Contenteditable path=\"/contenteditable\" />\n\t\t\t\t\t\t<Zustand path=\"/zustand\" />\n\t\t\t\t\t\t<ReduxToolkit path=\"/redux-toolkit\" />\n\t\t\t\t\t</Router>\n\t\t\t\t</main>\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nfunction EmptyFragment() {\n\treturn <Fragment />;\n}\n\n// document.body.innerHTML = renderToString(<App url={location.href.match(/[#&]ssr/) ? undefined : '/'} />);\n// document.body.firstChild.setAttribute('is-ssr', 'true');\n\ninstallLogger(\n\tString(localStorage.LOG) === 'true' || location.href.match(/logger/),\n\tString(localStorage.CONSOLE) === 'true' || location.href.match(/console/)\n);\n\nrender(<App />, document.body);\n"
  },
  {
    "path": "demo/key_bug.jsx",
    "content": "import { Component } from 'preact';\n\nfunction Foo(props) {\n\treturn <div>This is: {props.children}</div>;\n}\n\nexport default class KeyBug extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.onClick = this.onClick.bind(this);\n\t\tthis.state = { active: false };\n\t}\n\n\tonClick() {\n\t\tthis.setState(prev => ({ active: !prev.active }));\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t{this.state.active && <Foo>foo</Foo>}\n\t\t\t\t<h1>Hello World</h1>\n\t\t\t\t<br />\n\t\t\t\t<Foo>\n\t\t\t\t\tbar <Foo>bar</Foo>\n\t\t\t\t</Foo>\n\t\t\t\t<br />\n\t\t\t\t<button onClick={this.onClick}>Toggle</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/list.jsx",
    "content": "import { h, render } from 'preact';\nimport htm from 'htm';\nimport './style.css';\n\nconst html = htm.bind(h);\nconst createRoot = parent => ({\n\trender: v => render(v, parent)\n});\n\nfunction List({ items, renders, useKeys, useCounts, update }) {\n\tconst toggleKeys = () => update({ useKeys: !useKeys });\n\tconst toggleCounts = () => update({ useCounts: !useCounts });\n\tconst swap = () => {\n\t\tconst u = { items: items.slice() };\n\t\tu.items[1] = items[8];\n\t\tu.items[8] = items[1];\n\t\tupdate(u);\n\t};\n\treturn html`\n\t\t<div>\n\t\t\t<button onClick=${update}>Re-render</button>\n\t\t\t<button onClick=${swap}>Swap 2 & 8</button>\n\t\t\t<label>\n\t\t\t\t<input type=\"checkbox\" checked=${useKeys} onClick=${toggleKeys} />\n\t\t\t\tUse Keys\n\t\t\t</label>\n\t\t\t<label>\n\t\t\t\t<input type=\"checkbox\" checked=${useCounts} onClick=${toggleCounts} />\n\t\t\t\tCounts\n\t\t\t</label>\n\t\t\t<ul class=\"list\">\n\t\t\t\t${items.map(\n\t\t\t\t\t(item, i) => html`\n\t\t\t\t\t\t<li\n\t\t\t\t\t\t\tclass=${i % 2 ? 'odd' : 'even'}\n\t\t\t\t\t\t\tkey=${useKeys ? item.name : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t${item.name} ${useCounts ? ` (${renders} renders)` : ''}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t`\n\t\t\t\t)}\n\t\t\t</ul>\n\t\t</div>\n\t`;\n}\n\nconst root = createRoot(document.body);\n\nlet data = {\n\titems: new Array(1000).fill(null).map((x, i) => ({ name: `Item ${i + 1}` })),\n\trenders: 0,\n\tuseKeys: false,\n\tuseCounts: false\n};\n\nfunction update(partial) {\n\tif (partial) Object.assign(data, partial);\n\tdata.renders++;\n\tdata.update = update;\n\troot.render(List(data));\n}\n\nupdate();\n"
  },
  {
    "path": "demo/logger.jsx",
    "content": "export default function logger(logStats, logConsole) {\n\tif (!logStats && !logConsole) {\n\t\treturn;\n\t}\n\n\tconst consoleBuffer = new ConsoleBuffer();\n\n\tlet calls = {};\n\tlet lock = true;\n\n\tfunction serialize(obj) {\n\t\tif (obj instanceof Text) return '#text';\n\t\tif (obj instanceof Element) return `<${obj.localName}>`;\n\t\tif (obj === document) return 'document';\n\t\treturn Object.prototype.toString.call(obj).replace(/(^\\[object |\\]$)/g, '');\n\t}\n\n\tfunction count(key) {\n\t\tif (lock === true) return;\n\t\tcalls[key] = (calls[key] || 0) + 1;\n\n\t\tif (logConsole) {\n\t\t\tconsoleBuffer.log(key);\n\t\t}\n\t}\n\n\tfunction logCall(obj, method, name) {\n\t\tlet old = obj[method];\n\t\tobj[method] = function () {\n\t\t\tlet c = '';\n\t\t\tfor (let i = 0; i < arguments.length; i++) {\n\t\t\t\tif (c) c += ', ';\n\t\t\t\tc += serialize(arguments[i]);\n\t\t\t}\n\t\t\tcount(`${serialize(this)}.${method}(${c})`);\n\t\t\treturn old.apply(this, arguments);\n\t\t};\n\t}\n\n\tlogCall(document, 'createElement');\n\tlogCall(document, 'createElementNS');\n\tlogCall(Element.prototype, 'remove');\n\tlogCall(Element.prototype, 'appendChild');\n\tlogCall(Element.prototype, 'removeChild');\n\tlogCall(Element.prototype, 'insertBefore');\n\tlogCall(Element.prototype, 'replaceChild');\n\tlogCall(Element.prototype, 'setAttribute');\n\tlogCall(Element.prototype, 'setAttributeNS');\n\tlogCall(Element.prototype, 'removeAttribute');\n\tlogCall(Element.prototype, 'removeAttributeNS');\n\tlet d =\n\t\tObject.getOwnPropertyDescriptor(CharacterData.prototype, 'data') ||\n\t\tObject.getOwnPropertyDescriptor(Node.prototype, 'data');\n\tObject.defineProperty(Text.prototype, 'data', {\n\t\tget() {\n\t\t\tlet value = d.get.call(this);\n\t\t\tcount(`get #text.data`);\n\t\t\treturn value;\n\t\t},\n\t\tset(v) {\n\t\t\tcount(`set #text.data`);\n\t\t\treturn d.set.call(this, v);\n\t\t}\n\t});\n\n\tlet root;\n\tfunction setup() {\n\t\tif (!logStats) return;\n\n\t\tlock = true;\n\t\troot = document.createElement('table');\n\t\troot.style.cssText =\n\t\t\t'position: fixed; right: 0; top: 0; z-index:999; background: #000; font-size: 12px; color: #FFF; opacity: 0.9; white-space: nowrap;';\n\t\tlet header = document.createElement('thead');\n\t\theader.innerHTML =\n\t\t\t'<tr><td colspan=\"2\">Stats <button id=\"clear-logs\">clear</button></td></tr>';\n\t\troot.tableBody = document.createElement('tbody');\n\t\troot.appendChild(root.tableBody);\n\t\troot.appendChild(header);\n\t\tdocument.documentElement.appendChild(root);\n\t\tlet btn = document.getElementById('clear-logs');\n\t\tbtn.addEventListener('click', () => {\n\t\t\tfor (let key in calls) {\n\t\t\t\tcalls[key] = 0;\n\t\t\t}\n\t\t});\n\t\tlock = false;\n\t}\n\n\tlet rows = {};\n\tfunction createRow(id) {\n\t\tlet row = document.createElement('tr');\n\t\trow.key = document.createElement('td');\n\t\trow.key.textContent = id;\n\t\trow.appendChild(row.key);\n\t\trow.value = document.createElement('td');\n\t\trow.value.textContent = ' ';\n\t\trow.appendChild(row.value);\n\t\troot.tableBody.appendChild(row);\n\t\treturn (rows[id] = row);\n\t}\n\n\tfunction insertInto(parent) {\n\t\tparent.appendChild(root);\n\t}\n\n\tfunction remove() {\n\t\tclearInterval(updateTimer);\n\t}\n\n\tfunction update() {\n\t\tif (!logStats) return;\n\n\t\tlock = true;\n\t\tfor (let i in calls) {\n\t\t\tif (calls.hasOwnProperty(i)) {\n\t\t\t\tlet row = rows[i] || createRow(i);\n\t\t\t\trow.value.firstChild.nodeValue = calls[i];\n\t\t\t}\n\t\t}\n\t\tlock = false;\n\t}\n\n\tlet updateTimer = setInterval(update, 50);\n\n\tsetup();\n\tlock = false;\n\treturn { insertInto, update, remove };\n}\n\n/**\n * Logging to the console significantly affects performance.\n * Buffer calls to console and replay them at the end of the\n * current stack\n * @extends {Console}\n */\nclass ConsoleBuffer {\n\tconstructor() {\n\t\t/** @type {Array<[string, any[]]>} */\n\t\tthis.buffer = [];\n\t\tthis.deferred = null;\n\n\t\tfor (let methodName of Object.keys(console)) {\n\t\t\tthis[methodName] = this.proxy(methodName);\n\t\t}\n\t}\n\n\tproxy(methodName) {\n\t\treturn (...args) => {\n\t\t\tthis.buffer.push([methodName, args]);\n\t\t\tthis.deferFlush();\n\t\t};\n\t}\n\n\tdeferFlush() {\n\t\tif (this.deferred == null) {\n\t\t\tthis.deferred = Promise.resolve()\n\t\t\t\t.then(() => this.flush())\n\t\t\t\t.then(() => (this.deferred = null));\n\t\t}\n\t}\n\n\tflush() {\n\t\tlet method;\n\t\twhile ((method = this.buffer.shift())) {\n\t\t\tlet [name, args] = method;\n\t\t\tconsole[name](...args);\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "demo/mobx.jsx",
    "content": "import React, { forwardRef, useRef, useState } from 'react';\nimport { decorate, observable } from 'mobx';\nimport { observer, useObserver } from 'mobx-react';\n\nclass Todo {\n\tconstructor() {\n\t\tthis.id = Math.random();\n\t\tthis.title = 'initial';\n\t\tthis.finished = false;\n\t}\n}\ndecorate(Todo, {\n\ttitle: observable,\n\tfinished: observable\n});\n\nconst Forward = observer(\n\t// eslint-disable-next-line react/display-name\n\tforwardRef(({ todo }, ref) => {\n\t\treturn (\n\t\t\t<p ref={ref}>\n\t\t\t\tForward: \"{todo.title}\" {'' + todo.finished}\n\t\t\t</p>\n\t\t);\n\t})\n);\n\nconst todo = new Todo();\n\nconst TodoView = observer(({ todo }) => {\n\treturn (\n\t\t<p>\n\t\t\tTodo View: \"{todo.title}\" {'' + todo.finished}\n\t\t</p>\n\t);\n});\n\nconst HookView = ({ todo }) => {\n\treturn useObserver(() => {\n\t\treturn (\n\t\t\t<p>\n\t\t\t\tTodo View: \"{todo.title}\" {'' + todo.finished}\n\t\t\t</p>\n\t\t);\n\t});\n};\n\nexport function MobXDemo() {\n\tconst ref = useRef(null);\n\tlet [v, set] = useState(0);\n\n\tconst success = ref.current && ref.current.nodeName === 'P';\n\n\treturn (\n\t\t<div>\n\t\t\t<input\n\t\t\t\ttype=\"text\"\n\t\t\t\tplaceholder=\"type here...\"\n\t\t\t\tonInput={e => {\n\t\t\t\t\ttodo.title = e.target.value;\n\t\t\t\t\tset(v + 1);\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<p>\n\t\t\t\t<b style={`color: ${success ? 'green' : 'red'}`}>\n\t\t\t\t\t{success ? 'SUCCESS' : 'FAIL'}\n\t\t\t\t</b>\n\t\t\t</p>\n\t\t\t<TodoView todo={todo} />\n\t\t\t<Forward todo={todo} ref={ref} />\n\t\t\t<HookView todo={todo} />\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "demo/nested-suspense/addnewcomponent.jsx",
    "content": "import { createElement } from 'react';\n\nexport default function AddNewComponent({ appearance }) {\n\treturn <div>AddNewComponent (component #{appearance})</div>;\n}\n"
  },
  {
    "path": "demo/nested-suspense/component-container.jsx",
    "content": "import { lazy } from 'react';\n\nconst pause = timeout =>\n\tnew Promise(d => setTimeout(d, timeout), console.log(timeout));\n\nconst SubComponent = lazy(() =>\n\tpause(Math.random() * 1000).then(() => import('./subcomponent.jsx'))\n);\n\nexport default function ComponentContainer({ appearance }) {\n\treturn (\n\t\t<div>\n\t\t\tGenerateComponents (component #{appearance})\n\t\t\t<SubComponent />\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "demo/nested-suspense/dropzone.jsx",
    "content": "import { createElement } from 'react';\n\nexport default function DropZone({ appearance }) {\n\treturn <div>DropZone (component #{appearance})</div>;\n}\n"
  },
  {
    "path": "demo/nested-suspense/editor.jsx",
    "content": "import { createElement } from 'react';\n\nexport default function Editor({ children }) {\n\treturn <div className=\"Editor\">{children}</div>;\n}\n"
  },
  {
    "path": "demo/nested-suspense/index.jsx",
    "content": "import { createElement, Suspense, lazy, Component } from 'react';\n\nconst Loading = function () {\n\treturn <div>Loading...</div>;\n};\nconst Error = function ({ resetState }) {\n\treturn (\n\t\t<div>\n\t\t\tError!&nbsp;\n\t\t\t<a onClick={resetState} href=\"#\">\n\t\t\t\tReset app\n\t\t\t</a>\n\t\t</div>\n\t);\n};\n\nconst pause = timeout =>\n\tnew Promise(d => setTimeout(d, timeout), console.log(timeout));\n\nconst DropZone = lazy(() =>\n\tpause(Math.random() * 1000).then(() => import('./dropzone.jsx'))\n);\nconst Editor = lazy(() =>\n\tpause(Math.random() * 1000).then(() => import('./editor.jsx'))\n);\nconst AddNewComponent = lazy(() =>\n\tpause(Math.random() * 1000).then(() => import('./addnewcomponent.jsx'))\n);\nconst GenerateComponents = lazy(() =>\n\tpause(Math.random() * 1000).then(() => import('./component-container.jsx'))\n);\n\nexport default class App extends Component {\n\tstate = { hasError: false };\n\n\tstatic getDerivedStateFromError(error) {\n\t\t// Update state so the next render will show the fallback UI.\n\t\tconsole.warn(error);\n\t\treturn { hasError: true };\n\t}\n\n\trender() {\n\t\treturn this.state.hasError ? (\n\t\t\t<Error resetState={() => this.setState({ hasError: false })} />\n\t\t) : (\n\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t<DropZone appearance={0} />\n\t\t\t\t<Editor title=\"APP_TITLE\">\n\t\t\t\t\t<main>\n\t\t\t\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t\t\t\t<GenerateComponents appearance={1} />\n\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t<AddNewComponent appearance={2} />\n\t\t\t\t\t</main>\n\t\t\t\t\t<aside>\n\t\t\t\t\t\t<section>\n\t\t\t\t\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t\t\t\t\t<GenerateComponents appearance={3} />\n\t\t\t\t\t\t\t</Suspense>\n\t\t\t\t\t\t\t<AddNewComponent appearance={4} />\n\t\t\t\t\t\t</section>\n\t\t\t\t\t</aside>\n\t\t\t\t</Editor>\n\n\t\t\t\t<footer>Footer here</footer>\n\t\t\t</Suspense>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/nested-suspense/subcomponent.jsx",
    "content": "import { createElement } from 'react';\n\nexport default function SubComponent({ onClick }) {\n\treturn <div>Lazy loaded sub component</div>;\n}\n"
  },
  {
    "path": "demo/old.js.bak",
    "content": "\n// function createRoot(title) {\n// \tlet div = document.createElement('div');\n// \tlet h2 = document.createElement('h2');\n// \th2.textContent = title;\n// \tdiv.appendChild(h2);\n// \tdocument.body.appendChild(div);\n// \treturn div;\n// }\n\n\n/*\nfunction logCall(obj, method, name) {\n\tlet old = obj[method];\n\tobj[method] = function(...args) {\n\t\tconsole.log(`<${this.localName}>.`+(name || `${method}(${args})`));\n\t\treturn old.apply(this, args);\n\t};\n}\n\nlogCall(HTMLElement.prototype, 'appendChild');\nlogCall(HTMLElement.prototype, 'removeChild');\nlogCall(HTMLElement.prototype, 'insertBefore');\nlogCall(HTMLElement.prototype, 'replaceChild');\nlogCall(HTMLElement.prototype, 'setAttribute');\nlogCall(HTMLElement.prototype, 'removeAttribute');\nlet d = Object.getOwnPropertyDescriptor(Node.prototype, 'nodeValue');\nObject.defineProperty(Text.prototype, 'nodeValue', {\n\tget() {\n\t\tlet value = d.get.call(this);\n\t\tconsole.log('get Text#nodeValue: ', value);\n\t\treturn value;\n\t},\n\tset(v) {\n\t\tconsole.log('set Text#nodeValue', v);\n\t\treturn d.set.call(this, v);\n\t}\n});\n\n\nrender((\n\t<div>\n\t\t<h4>This is a test.</h4>\n\t\t<Foo />\n\t\t<time>...</time>\n\t</div>\n), createRoot('Stateful component update demo:'));\n\n\nclass Foo extends Component {\n\tcomponentDidMount() {\n\t\tconsole.log('mounted');\n\t\tthis.timer = setInterval( () => {\n\t\t\tthis.setState({ time: Date.now() });\n\t\t}, 5000);\n\t}\n\tcomponentWillUnmount() {\n\t\tclearInterval(this.timer);\n\t}\n\trender(props, state, context) {\n\t\t// console.log('rendering', props, state, context);\n\t\treturn <time>test: {state.time}</time>\n\t}\n}\n\n\nrender((\n\t<div>\n\t\t<h4>This is a test.</h4>\n\t\t<Foo />\n\t\t<time>...</time>\n\t</div>\n), createRoot('Stateful component update demo:'));\n\n\nlet items = [];\nlet count = 0;\nlet three = createRoot('Top-level render demo:');\n\nsetInterval( () => {\n\tif (count++ %20 < 10 ) {\n\t\titems.push(<li key={count} style={{\n\t\t\tposition: 'relative',\n\t\t\ttransition: 'all 200ms ease',\n\t\t\tpaddingLeft: items.length*20 +'px'\n\t\t}}>item #{items.length}</li>);\n\t}\n\telse {\n\t\titems.shift();\n\t}\n\n\trender((\n\t\t<div>\n\t\t\t<h4>This is a test.</h4>\n\t\t\t<time>{Date.now()}</time>\n\t\t\t<ul>{items}</ul>\n\t\t</div>\n\t), three);\n}, 5000);\n\n// Mount the top-level component to the DOM:\nrender(<Main />, document.body);\n*/\n"
  },
  {
    "path": "demo/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"vite\",\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@babel/plugin-proposal-class-properties\": \"^7.0.0-beta.55\",\n    \"@babel/plugin-proposal-decorators\": \"^7.4.0\",\n    \"vite\": \"^5.4.10\"\n  },\n  \"dependencies\": {\n    \"@material-ui/core\": \"4.9.5\",\n    \"@reduxjs/toolkit\": \"^2.2.3\",\n    \"d3-scale\": \"^1.0.7\",\n    \"d3-selection\": \"^1.2.0\",\n    \"htm\": \"2.1.1\",\n    \"mobx\": \"^5.15.4\",\n    \"mobx-react\": \"^6.2.2\",\n    \"mobx-state-tree\": \"^3.16.0\",\n    \"preact-render-to-string\": \"^5.0.2\",\n    \"preact-router\": \"^3.0.0\",\n    \"react-redux\": \"^7.1.0\",\n    \"react-router\": \"^5.0.1\",\n    \"react-router-dom\": \"^5.0.1\",\n    \"redux\": \"^4.0.1\",\n    \"styled-components\": \"^4.2.0\",\n    \"zustand\": \"^4.5.2\"\n  },\n  \"volta\": {\n    \"extends\": \"../package.json\"\n  }\n}\n"
  },
  {
    "path": "demo/people/Readme.md",
    "content": "# People demo page\n\nThis section of our demo was originally made by [phaux](https://github.com/phaux) in the [web-app-boilerplate](https://github.com/phaux/web-app-boilerplate) repo. It has been slightly modified from it's original to better work inside of our demo app\n"
  },
  {
    "path": "demo/people/index.tsx",
    "content": "import { observer } from 'mobx-react';\nimport { Component } from 'preact';\nimport { Profile } from './profile';\nimport { Link, Route, Router } from './router';\nimport { store } from './store';\n\nimport './styles/index.scss';\n\n@observer\nexport default class App extends Component {\n\tcomponentDidMount() {\n\t\tstore.loadUsers().catch(console.error);\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<Router>\n\t\t\t\t<div id=\"people-app\">\n\t\t\t\t\t<nav>\n\t\t\t\t\t\t<div style={{ margin: 16, textAlign: 'center' }}>\n\t\t\t\t\t\t\tSort by{' '}\n\t\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t\tvalue={store.usersOrder}\n\t\t\t\t\t\t\t\tonChange={(ev: any) => {\n\t\t\t\t\t\t\t\t\tstore.setUsersOrder(ev.target.value);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<option value=\"name\">Name</option>\n\t\t\t\t\t\t\t\t<option value=\"id\">ID</option>\n\t\t\t\t\t\t\t</select>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<ul>\n\t\t\t\t\t\t\t{store.getSortedUsers().map((user, i) => (\n\t\t\t\t\t\t\t\t<li\n\t\t\t\t\t\t\t\t\tkey={user.id}\n\t\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t\tanimationDelay: `${i * 20}ms`,\n\t\t\t\t\t\t\t\t\t\ttop: `calc(var(--menu-item-height) * ${i})`,\n\t\t\t\t\t\t\t\t\t\ttransitionDelay: `${i * 20}ms`\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Link href={`people/${user.id}`} active>\n\t\t\t\t\t\t\t\t\t\t<img class=\"avatar\" src={user.picture.large} />\n\t\t\t\t\t\t\t\t\t\t{user.name.first} {user.name.last}\n\t\t\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</nav>\n\t\t\t\t\t<section id=\"people-main\">\n\t\t\t\t\t\t<Route match=\"people\">\n\t\t\t\t\t\t\t<Route match=\"*\" component={Profile} />\n\t\t\t\t\t\t</Route>\n\t\t\t\t\t</section>\n\t\t\t\t</div>\n\t\t\t</Router>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/people/profile.tsx",
    "content": "import { computed, observable } from 'mobx';\nimport { observer } from 'mobx-react';\nimport { Component } from 'preact';\nimport { RouteChildProps } from './router';\nimport { store } from './store';\n\nexport type ProfileProps = RouteChildProps;\n@observer\nexport class Profile extends Component<ProfileProps> {\n\t@observable id = '';\n\t@observable busy = false;\n\n\tcomponentDidMount() {\n\t\tthis.id = this.props.route;\n\t}\n\n\tcomponentWillReceiveProps(props: ProfileProps) {\n\t\tthis.id = props.route;\n\t}\n\n\trender() {\n\t\tconst user = this.user;\n\t\tif (user == null) return null;\n\t\treturn (\n\t\t\t<div class=\"profile\">\n\t\t\t\t<img class=\"avatar\" src={user.picture.large} />\n\t\t\t\t<h2>\n\t\t\t\t\t{user.name.first} {user.name.last}\n\t\t\t\t</h2>\n\t\t\t\t<div class=\"details\">\n\t\t\t\t\t<p>\n\t\t\t\t\t\t{user.gender === 'female' ? '👩' : '👨'} {user.id}\n\t\t\t\t\t</p>\n\t\t\t\t\t<p>🖂 {user.email}</p>\n\t\t\t\t</div>\n\t\t\t\t<p>\n\t\t\t\t\t<button\n\t\t\t\t\t\tclass={this.busy ? 'secondary busy' : 'secondary'}\n\t\t\t\t\t\tdisabled={this.busy}\n\t\t\t\t\t\tonClick={this.remove}\n\t\t\t\t\t>\n\t\t\t\t\t\tRemove contact\n\t\t\t\t\t</button>\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t);\n\t}\n\n\t@computed get user() {\n\t\treturn store.users.find(u => u.id === this.id);\n\t}\n\n\tremove = async () => {\n\t\tthis.busy = true;\n\t\tawait new Promise<void>(cb => setTimeout(cb, 1500));\n\t\tstore.deleteUser(this.id);\n\t\tthis.busy = false;\n\t};\n}\n"
  },
  {
    "path": "demo/people/router.tsx",
    "content": "import {\n\tComponentChild,\n\tComponentFactory,\n\tcreateContext,\n\tFunctionalComponent,\n\th,\n\tJSX\n} from 'preact';\nimport {\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseState\n} from 'preact/hooks';\n\nexport type RouterData = {\n\tmatch: string[];\n\tpath: string[];\n\tnavigate(path: string): void;\n};\n\nconst RouterContext = createContext<RouterData>({\n\tmatch: [],\n\tpath: [],\n\tnavigate() {}\n});\nexport const useRouter = () => useContext(RouterContext);\n\nconst useLocation = (cb: () => void) => {\n\tuseEffect(() => {\n\t\twindow.addEventListener('popstate', cb);\n\t\treturn () => {\n\t\t\twindow.removeEventListener('popstate', cb);\n\t\t};\n\t}, [cb]);\n};\n\nexport const Router: FunctionalComponent = props => {\n\tconst [path, setPath] = useState(location.pathname);\n\n\tconst update = useCallback(() => {\n\t\tsetPath(location.pathname);\n\t}, [setPath]);\n\n\tuseLocation(update);\n\n\tconst navigate = useCallback(\n\t\t(path: string) => {\n\t\t\thistory.pushState(null, '', path);\n\t\t\tupdate();\n\t\t},\n\t\t[update]\n\t);\n\n\tconst router = useMemo<RouterData>(\n\t\t() => ({\n\t\t\tmatch: [],\n\t\t\tnavigate,\n\t\t\tpath: path.split('/').filter(Boolean)\n\t\t}),\n\t\t[navigate, path]\n\t);\n\n\treturn <RouterContext.Provider children={props.children} value={router} />;\n};\n\nexport type RouteChildProps = { route: string };\nexport type RouteProps = {\n\tcomponent?: ComponentFactory<RouteChildProps>;\n\tmatch: string;\n\trender?(route: string): ComponentChild;\n};\nexport const Route: FunctionalComponent<RouteProps> = props => {\n\tconst router = useRouter();\n\tconst [dir, ...subpath] = router.path;\n\n\tif (dir == null) return null;\n\tif (props.match !== '*' && dir !== props.match) return null;\n\n\tconst children = useMemo(() => {\n\t\tif (props.component) return <props.component key={dir} route={dir} />;\n\t\tif (props.render) return props.render(dir);\n\t\treturn props.children;\n\t}, [props.component, props.render, props.children, dir]);\n\n\tconst innerRouter = useMemo<RouterData>(\n\t\t() => ({\n\t\t\t...router,\n\t\t\tmatch: [...router.match, dir],\n\t\t\tpath: subpath\n\t\t}),\n\t\t[router.match, dir, subpath.join('/')]\n\t);\n\n\treturn <RouterContext.Provider children={children} value={innerRouter} />;\n};\n\nexport type LinkProps = JSX.HTMLAttributes & {\n\tactive?: boolean | string;\n};\nexport const Link: FunctionalComponent<LinkProps> = props => {\n\tconst router = useRouter();\n\n\tconst classProps = [props.class, props.className];\n\tconst originalClasses = useMemo(() => {\n\t\tconst classes = [];\n\t\tfor (const prop of classProps) if (prop) classes.push(...prop.split(/\\s+/));\n\t\treturn classes;\n\t}, classProps);\n\n\tconst activeClass = useMemo(() => {\n\t\tif (!props.active || props.href == null) return undefined;\n\t\tconst href = props.href.split('/').filter(Boolean);\n\t\tconst path =\n\t\t\tprops.href[0] === '/' ? [...router.match, ...router.path] : router.path;\n\t\tconst isMatch = href.every((dir, i) => dir === path[i]);\n\t\tif (isMatch) return props.active === true ? 'active' : props.active;\n\t}, [originalClasses, props.active, props.href, router.match, router.path]);\n\n\tconst classes =\n\t\tactiveClass == null ? originalClasses : [...originalClasses, activeClass];\n\n\tconst getHref = useCallback(() => {\n\t\tif (props.href == null || props.href[0] === '/') return props.href;\n\t\tconst path = props.href.split('/').filter(Boolean);\n\t\treturn '/' + [...router.match, ...path].join('/');\n\t}, [router.match, props.href]);\n\n\tconst handleClick = useCallback(\n\t\t(ev: MouseEvent) => {\n\t\t\tconst href = getHref();\n\t\t\tif (props.onClick != null) props.onClick(ev);\n\t\t\tif (ev.defaultPrevented) return;\n\t\t\tif (href == null) return;\n\t\t\tif (ev.button !== 0) return;\n\t\t\tif (props.target != null && props.target !== '_self') return;\n\t\t\tif (ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey) return;\n\t\t\tev.preventDefault();\n\t\t\trouter.navigate(href);\n\t\t},\n\t\t[getHref, router.navigate, props.onClick, props.target]\n\t);\n\n\treturn (\n\t\t<a\n\t\t\t{...props}\n\t\t\tclass={classes.join(' ')}\n\t\t\thref={getHref()}\n\t\t\tonClick={handleClick}\n\t\t/>\n\t);\n};\n"
  },
  {
    "path": "demo/people/store.ts",
    "content": "import { flow, Instance, types } from 'mobx-state-tree';\n\nconst cmp =\n\t<T, U>(fn: (x: T) => U) =>\n\t(a: T, b: T): number =>\n\t\tfn(a) > fn(b) ? 1 : -1;\n\nconst User = types.model({\n\temail: types.string,\n\tgender: types.enumeration(['male', 'female']),\n\tid: types.identifier,\n\tname: types.model({\n\t\tfirst: types.string,\n\t\tlast: types.string\n\t}),\n\tpicture: types.model({\n\t\tlarge: types.string\n\t})\n});\n\nconst Store = types\n\t.model({\n\t\tusers: types.array(User),\n\t\tusersOrder: types.enumeration(['name', 'id'])\n\t})\n\t.views(self => ({\n\t\tgetSortedUsers() {\n\t\t\tif (self.usersOrder === 'name')\n\t\t\t\treturn self.users.slice().sort(cmp(x => x.name.first));\n\t\t\tif (self.usersOrder === 'id')\n\t\t\t\treturn self.users.slice().sort(cmp(x => x.id));\n\t\t\tthrow Error(`Unknown ordering ${self.usersOrder}`);\n\t\t}\n\t}))\n\t.actions(self => ({\n\t\taddUser: flow<unknown, []>(function* () {\n\t\t\tconst data = yield fetch('https://randomuser.me/api?results=1')\n\t\t\t\t.then(res => res.json())\n\t\t\t\t.then(data =>\n\t\t\t\t\tdata.results.map((user: any) => ({\n\t\t\t\t\t\t...user,\n\t\t\t\t\t\tid: user.login.username\n\t\t\t\t\t}))\n\t\t\t\t);\n\t\t\tself.users.push(...data);\n\t\t}),\n\t\tloadUsers: flow<unknown, []>(function* () {\n\t\t\tconst data = yield fetch(\n\t\t\t\t`https://randomuser.me/api?seed=${12321}&results=12`\n\t\t\t)\n\t\t\t\t.then(res => res.json())\n\t\t\t\t.then(data =>\n\t\t\t\t\tdata.results.map((user: any) => ({\n\t\t\t\t\t\t...user,\n\t\t\t\t\t\tid: user.login.username\n\t\t\t\t\t}))\n\t\t\t\t);\n\t\t\tself.users.replace(data);\n\t\t}),\n\t\tdeleteUser(id: string) {\n\t\t\tconst user = self.users.find(u => u.id === id);\n\t\t\tif (user != null) self.users.remove(user);\n\t\t},\n\t\tsetUsersOrder(order: 'name' | 'id') {\n\t\t\tself.usersOrder = order;\n\t\t}\n\t}));\n\nexport type StoreType = Instance<typeof Store>;\nexport const store = Store.create({\n\tusersOrder: 'name',\n\tusers: []\n});\n\n// const { Provider, Consumer } = createContext<StoreType>(undefined as any)\n\n// export const StoreProvider: FunctionalComponent = props => {\n//   const store = Store.create({})\n//   return <Provider value={store} children={props.children} />\n// }\n\n// export type StoreProps = {store: StoreType}\n// export function injectStore<T>(Child: AnyComponent<T & StoreProps>): FunctionalComponent<T> {\n//   return props => <Consumer render={store => <Child {...props} store={store}/>}/>\n// }\n"
  },
  {
    "path": "demo/people/styles/animations.scss",
    "content": "@keyframes popup {\n\tfrom {\n\t\tbox-shadow: 0 0 0 black;\n\t\topacity: 0;\n\t\ttransform: scale(0.9);\n\t}\n\tto {\n\t\tbox-shadow: 0 30px 70px rgba(0, 0, 0, 0.5);\n\t\topacity: 1;\n\t\ttransform: none;\n\t}\n}\n\n@keyframes zoom {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: scale(0.8);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: none;\n\t}\n}\n\n@keyframes appear-from-left {\n\tfrom {\n\t\topacity: 0;\n\t\ttransform: translateX(-25px);\n\t}\n\tto {\n\t\topacity: 1;\n\t\ttransform: none;\n\t}\n}\n"
  },
  {
    "path": "demo/people/styles/app.scss",
    "content": "#people-app {\n\tposition: relative;\n\toverflow: hidden;\n\tmin-height: 100vh;\n\tanimation: popup 300ms cubic-bezier(0.3, 0.7, 0.3, 1) forwards;\n\tbackground: var(--app-background);\n\t--menu-width: 260px;\n\t--menu-item-height: 50px;\n\n\t@media (min-width: 1280px) {\n\t\tmax-width: 1280px;\n\t\tmin-height: calc(100vh - 64px);\n\t\tmargin: 32px auto;\n\t\tborder-radius: 10px;\n\t}\n\n\t> nav {\n\t\tposition: absolute;\n\t\tdisplay: flow-root;\n\t\twidth: var(--menu-width);\n\t\theight: 100%;\n\t\tbackground-color: var(--app-background-secondary);\n\t\toverflow-x: hidden;\n\t\toverflow-y: auto;\n\t}\n\n\t> nav h4 {\n\t\tpadding-left: 16px;\n\t\tfont-weight: normal;\n\t\ttext-transform: uppercase;\n\t}\n\n\t> nav ul {\n\t\tposition: relative;\n\t}\n\n\t> nav li {\n\t\tposition: absolute;\n\t\twidth: 100%;\n\t\tanimation: zoom 200ms forwards;\n\t\topacity: 0;\n\t\ttransition: top 200ms;\n\t}\n\n\t> nav li > a {\n\t\tposition: relative;\n\t\tdisplay: flex;\n\t\toverflow: hidden;\n\t\tflex-flow: row;\n\t\talign-items: center;\n\t\tmargin-left: 16px;\n\t\tborder-right: 2px solid transparent;\n\t\tborder-bottom-left-radius: 48px;\n\t\tborder-top-left-radius: 48px;\n\t\ttext-transform: capitalize;\n\t\ttransition: border 500ms;\n\t}\n\n\t> nav li > a:hover {\n\t\tbackground-color: var(--app-highlight);\n\t}\n\n\t> nav li > a::after {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tright: -2px;\n\t\tbottom: 0;\n\t\tleft: 0;\n\t\tbackground-image: radial-gradient(\n\t\t\tcircle,\n\t\t\tvar(--app-ripple) 1%,\n\t\t\ttransparent 1%\n\t\t);\n\t\tbackground-position: center;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-size: 10000%;\n\t\tcontent: '';\n\t\topacity: 0;\n\t\ttransition: opacity 700ms, background 300ms;\n\t}\n\n\t> nav li > a:active::after {\n\t\tbackground-size: 100%;\n\t\topacity: 0.5;\n\t\ttransition: none;\n\t}\n\n\t> nav li > a.active {\n\t\tborder-color: var(--app-primary);\n\t\tbackground-color: var(--app-highlight);\n\t}\n\n\t> nav li > a > * {\n\t\tmargin: 8px;\n\t}\n\n\t#people-main {\n\t\tpadding-left: var(--menu-width);\n\t}\n}\n"
  },
  {
    "path": "demo/people/styles/avatar.scss",
    "content": "#people-app {\n\t.avatar {\n\t\tdisplay: inline-block;\n\t\toverflow: hidden;\n\t\twidth: var(--avatar-size, 32px);\n\t\theight: var(--avatar-size, 32px);\n\t\tbackground-color: var(--avatar-color, var(--app-primary));\n\t\tborder-radius: 50%;\n\t\tfont-size: calc(var(--avatar-size, 32px) * 0.5);\n\t\tline-height: var(--avatar-size, 32px);\n\t\tobject-fit: cover;\n\t\ttext-align: center;\n\t\ttext-transform: uppercase;\n\t\twhite-space: nowrap;\n\t}\n}\n"
  },
  {
    "path": "demo/people/styles/button.scss",
    "content": "#people-app {\n\tbutton {\n\t\tposition: relative;\n\t\toverflow: hidden;\n\t\tmin-width: 36px;\n\t\theight: 36px;\n\t\tpadding: 0 16px;\n\t\tborder: none;\n\t\tbackground-color: transparent;\n\t\tborder-radius: 4px;\n\t\tcolor: var(--app-text);\n\t\tfont-family: 'Montserrat', sans-serif;\n\t\tfont-size: 14px;\n\t\tfont-weight: 600;\n\t\tletter-spacing: 0.08em;\n\t\ttext-transform: uppercase;\n\t\ttransition: background 300ms, color 200ms;\n\t\twhite-space: nowrap;\n\t}\n\n\tbutton::before {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tleft: 0;\n\t\tbackground-color: var(--app-ripple);\n\t\tcontent: '';\n\t\topacity: 0;\n\t\ttransition: opacity 200ms;\n\t}\n\n\tbutton:hover:not(:disabled)::before {\n\t\topacity: 0.3;\n\t\ttransition: opacity 100ms;\n\t}\n\n\tbutton:active:not(:disabled)::before {\n\t\topacity: 0.7;\n\t\ttransition: none;\n\t}\n\n\tbutton::after {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tleft: 0;\n\t\tbackground-image: radial-gradient(\n\t\t\tcircle,\n\t\t\tvar(--app-ripple) 1%,\n\t\t\ttransparent 1%\n\t\t);\n\t\tbackground-position: center;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-size: 20000%;\n\t\tcontent: '';\n\t\topacity: 0;\n\t\ttransition: opacity 700ms, background 400ms;\n\t}\n\n\tbutton:active:not(:disabled)::after {\n\t\tbackground-size: 100%;\n\t\topacity: 1;\n\t\ttransition: none;\n\t}\n\n\tbutton.primary {\n\t\tbackground-color: var(--app-primary);\n\t\tbox-shadow: 0 2px 6px var(--app-shadow);\n\t}\n\n\tbutton.secondary {\n\t\tbackground-color: var(--app-secondary);\n\t\tbox-shadow: 0 2px 6px var(--app-shadow);\n\t}\n\n\tbutton:disabled {\n\t\tcolor: var(--app-text-secondary);\n\t}\n\n\tbutton.busy {\n\t\tanimation: stripes 500ms linear infinite;\n\t\tbackground-image: repeating-linear-gradient(\n\t\t\t45deg,\n\t\t\tvar(--app-shadow) 0%,\n\t\t\tvar(--app-shadow) 25%,\n\t\t\ttransparent 25%,\n\t\t\ttransparent 50%,\n\t\t\tvar(--app-shadow) 50%,\n\t\t\tvar(--app-shadow) 75%,\n\t\t\ttransparent 75%,\n\t\t\ttransparent 100%\n\t\t);\n\t\tcolor: var(--app-text);\n\t\t/* letter-spacing: -.7em; */\n\t}\n\n\tbutton:disabled:not(.primary):not(.secondary).busy,\n\tbutton:disabled.primary:not(.busy),\n\tbutton:disabled.secondary:not(.busy) {\n\t\tbackground-color: var(--app-background-disabled);\n\t}\n\n\t@keyframes stripes {\n\t\tfrom {\n\t\t\tbackground-position-x: 0;\n\t\t\tbackground-size: 16px 16px;\n\t\t}\n\t\tto {\n\t\t\tbackground-position-x: 16px;\n\t\t\tbackground-size: 16px 16px;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "demo/people/styles/index.scss",
    "content": "@import 'app.scss';\n@import 'animations.scss';\n@import 'avatar.scss';\n@import 'profile.scss';\n@import 'button.scss';\n\n// :root {\n#people-app {\n\t--app-background: #2f2b43;\n\t--app-background-secondary: #353249;\n\t--app-background-disabled: #555366;\n\t--app-highlight: rgba(255, 255, 255, 0.1);\n\t--app-ripple: rgba(255, 255, 255, 0.5);\n\t--app-shadow: rgba(0, 0, 0, 0.15);\n\t--app-text: #fff;\n\t--app-text-secondary: #807e97;\n\t--app-primary: #ff0087;\n\t--app-secondary: #4d7cfe;\n\t--app-tertiary: #00ec97;\n\t--app-danger: #f3c835;\n\t--spinner-size: 200px;\n}\n\n* {\n\tbox-sizing: border-box;\n}\n\n// body {\n#people-app {\n\t// display: flow-root;\n\t// overflow: auto;\n\t// min-height: 100vh;\n\t// margin: 0;\n\t// animation: background-light 5s ease-out forwards;\n\t// /* very fancy background */\n\t// background: radial-gradient(\n\t// \t\tcircle 15px at 150px 90vh,\n\t// \t\trgba(255, 255, 255, 0.35),\n\t// \t\trgba(255, 255, 255, 0.35) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 9px at 60px 50vh,\n\t// \t\trgba(255, 255, 255, 0.55),\n\t// \t\trgba(255, 255, 255, 0.55) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 19px at 40vw 70px,\n\t// \t\trgba(255, 255, 255, 0.3),\n\t// \t\trgba(255, 255, 255, 0.3) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 12px at 80vw 80px,\n\t// \t\trgba(255, 255, 255, 0.4),\n\t// \t\trgba(255, 255, 255, 0.4) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 7px at 55vw calc(100vh - 95px),\n\t// \t\trgba(255, 255, 255, 0.6),\n\t// \t\trgba(255, 255, 255, 0.6) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 14px at 25vw calc(100vh - 35px),\n\t// \t\trgba(255, 255, 255, 0.4),\n\t// \t\trgba(255, 255, 255, 0.4) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 11px at calc(100vw - 95px) 55vh,\n\t// \t\trgba(255, 255, 255, 0.45),\n\t// \t\trgba(255, 255, 255, 0.45) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 13px at calc(100vw - 35px) 85vh,\n\t// \t\trgba(255, 255, 255, 0.4),\n\t// \t\trgba(255, 255, 255, 0.4) 90%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 50vw at 0 -25%,\n\t// \t\trgba(255, 255, 255, 0.07),\n\t// \t\trgba(255, 255, 255, 0.07) 100%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(\n\t// \t\tcircle 80vw at top left,\n\t// \t\trgba(255, 255, 255, 0.07),\n\t// \t\trgba(255, 255, 255, 0.07) 100%,\n\t// \t\ttransparent\n\t// \t),\n\t// \tradial-gradient(circle at bottom right, #ef2fb8, transparent),\n\t// \tradial-gradient(circle at top right, #c45af3, transparent),\n\t// \tlinear-gradient(#ee66ca, #ff47a6);\n\tcolor: var(--app-text);\n\tfont-family: 'Montserrat', sans-serif;\n}\n\n#people-app {\n\t.spinner {\n\t\tposition: absolute;\n\t\ttop: 200px;\n\t\tleft: calc(50% - var(--spinner-size) / 2);\n\t\twidth: var(--spinner-size);\n\t\theight: var(--spinner-size);\n\t\tanimation: zoom 250ms 500ms forwards ease-out;\n\t\topacity: 0;\n\t\ttransition: opacity 200ms, transform 200ms ease-in;\n\t}\n\n\t.spinner.exit {\n\t\topacity: 0;\n\t\ttransform: scale(0.5);\n\t}\n\n\t.spinner::before,\n\t.spinner::after {\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\twidth: calc(var(--spinner-size) / 3);\n\t\theight: calc(var(--spinner-size) / 3);\n\t\tanimation: spinner 2s infinite ease-in-out;\n\t\tbackground-color: rgba(255, 255, 255, 0.6);\n\t\tcontent: '';\n\t}\n\n\t.spinner::after {\n\t\tanimation-delay: -1s;\n\t}\n\n\t@keyframes spinner {\n\t\t25% {\n\t\t\ttransform: translateX(calc(var(--spinner-size) / 3 * 2 - 1px))\n\t\t\t\trotate(-90deg) scale(0.5);\n\t\t}\n\t\t50% {\n\t\t\ttransform: translateX(calc(var(--spinner-size) / 3 * 2 - 1px))\n\t\t\t\ttranslateY(calc(var(--spinner-size) / 3 * 2 - 1px)) rotate(-179deg);\n\t\t}\n\t\t50.1% {\n\t\t\ttransform: translateX(calc(var(--spinner-size) / 3 * 2 - 1px))\n\t\t\t\ttranslateY(calc(var(--spinner-size) / 3 * 2 - 1px)) rotate(-180deg);\n\t\t}\n\t\t75% {\n\t\t\ttransform: translateX(0)\n\t\t\t\ttranslateY(calc(var(--spinner-size) / 3 * 2 - 1px)) rotate(-270deg)\n\t\t\t\tscale(0.5);\n\t\t}\n\t\t100% {\n\t\t\ttransform: rotate(-360deg);\n\t\t}\n\t}\n\n\tul,\n\tol {\n\t\tpadding-left: 0;\n\t\tlist-style: none;\n\t}\n\n\ta {\n\t\tcolor: inherit;\n\t\ttext-decoration: none;\n\t}\n}\n"
  },
  {
    "path": "demo/people/styles/profile.scss",
    "content": "#people-app {\n\t.profile {\n\t\tdisplay: flex;\n\t\tflex-flow: column;\n\t\talign-items: center;\n\t\tmargin: 32px 0;\n\t\tanimation: appear-from-left 0.5s forwards;\n\t\t--avatar-size: 80px;\n\t}\n\n\t.profile h2 {\n\t\ttext-transform: capitalize;\n\t}\n\n\t.profile .details {\n\t\tdisplay: flex;\n\t\tflex-flow: column;\n\t\talign-items: stretch;\n\t\tmargin: 16px auto;\n\t}\n\n\t.profile .details p {\n\t\tmargin-top: 8px;\n\t\tmargin-bottom: 8px;\n\t}\n}\n"
  },
  {
    "path": "demo/preact.jsx",
    "content": "import {\n\toptions,\n\tcreateElement,\n\tcloneElement,\n\tComponent as CevicheComponent,\n\trender\n} from 'preact';\n\noptions.vnode = vnode => {\n\tvnode.nodeName = vnode.type;\n\tvnode.attributes = vnode.props;\n\tvnode.children = vnode._children || [].concat(vnode.props.children || []);\n};\n\nfunction asArray(arr) {\n\treturn Array.isArray(arr) ? arr : [arr];\n}\n\nfunction normalize(obj) {\n\tif (Array.isArray(obj)) {\n\t\treturn obj.map(normalize);\n\t}\n\tif ('type' in obj && !('attributes' in obj)) {\n\t\tobj.attributes = obj.props;\n\t}\n\treturn obj;\n}\n\nexport function Component(props, context) {\n\tCevicheComponent.call(this, props, context);\n\tconst render = this.render;\n\tthis.render = function (props, state, context) {\n\t\tif (props.children) props.children = asArray(normalize(props.children));\n\t\treturn render.call(this, props, state, context);\n\t};\n}\nComponent.prototype = new CevicheComponent();\n\nexport { createElement, createElement as h, cloneElement, render };\n"
  },
  {
    "path": "demo/profiler.jsx",
    "content": "import { createElement, Component, options } from 'preact';\n\nfunction getPrimes(max) {\n\tlet sieve = [],\n\t\ti,\n\t\tj,\n\t\tprimes = [];\n\tfor (i = 2; i <= max; ++i) {\n\t\tif (!sieve[i]) {\n\t\t\t// i has not been marked -- it is prime\n\t\t\tprimes.push(i);\n\t\t\tfor (j = i << 1; j <= max; j += i) {\n\t\t\t\tsieve[j] = true;\n\t\t\t}\n\t\t}\n\t}\n\treturn primes.join('');\n}\n\nfunction Foo(props) {\n\treturn <div>{props.children}</div>;\n}\n\nfunction Bar() {\n\tgetPrimes(10000);\n\treturn (\n\t\t<div>\n\t\t\t<span>...yet another component</span>\n\t\t</div>\n\t);\n}\n\nfunction PrimeNumber(props) {\n\t// Slow down rendering of this component\n\tgetPrimes(10);\n\n\treturn (\n\t\t<div>\n\t\t\t<span>I'm a slow component</span>\n\t\t\t<br />\n\t\t\t{props.children}\n\t\t</div>\n\t);\n}\n\nexport default class ProfilerDemo extends Component {\n\tconstructor() {\n\t\tsuper();\n\t\tthis.onClick = this.onClick.bind(this);\n\t\tthis.state = { counter: 0 };\n\t}\n\n\tcomponentDidMount() {\n\t\toptions._diff = vnode => (vnode.startTime = performance.now());\n\t\toptions.diffed = vnode => (vnode.endTime = performance.now());\n\t}\n\n\tcomponentWillUnmount() {\n\t\tdelete options._diff;\n\t\tdelete options.diffed;\n\t}\n\n\tonClick() {\n\t\tthis.setState(prev => ({ counter: ++prev.counter }));\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<div class=\"foo\">\n\t\t\t\t<h1>⚛ Preact</h1>\n\t\t\t\t<p>\n\t\t\t\t\t<b>Devtools Profiler integration 🕒</b>\n\t\t\t\t</p>\n\t\t\t\t<Foo>\n\t\t\t\t\t<PrimeNumber>\n\t\t\t\t\t\t<Foo>I'm a fast component</Foo>\n\t\t\t\t\t\t<Bar />\n\t\t\t\t\t</PrimeNumber>\n\t\t\t\t</Foo>\n\t\t\t\t<Foo>I'm the fastest component 🎉</Foo>\n\t\t\t\t<span>Counter: {this.state.counter}</span>\n\t\t\t\t<br />\n\t\t\t\t<br />\n\t\t\t\t<button onClick={this.onClick}>Force re-render</button>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/pythagoras/index.jsx",
    "content": "import { Component } from 'preact';\nimport { select as d3select, mouse as d3mouse } from 'd3-selection';\nimport { scaleLinear } from 'd3-scale';\nimport Pythagoras from './pythagoras';\n\nexport default class PythagorasDemo extends Component {\n\tsvg = {\n\t\twidth: 1280,\n\t\theight: 600\n\t};\n\n\tstate = {\n\t\tcurrentMax: 0,\n\t\tbaseW: 80,\n\t\theightFactor: 0,\n\t\tlean: 0\n\t};\n\n\trealMax = 11;\n\n\tsvgRef = c => {\n\t\tthis.svgElement = c;\n\t};\n\n\tscaleFactor = scaleLinear().domain([this.svg.height, 0]).range([0, 0.8]);\n\n\tscaleLean = scaleLinear()\n\t\t.domain([0, this.svg.width / 2, this.svg.width])\n\t\t.range([0.5, 0, -0.5]);\n\n\tonMouseMove = event => {\n\t\tlet [x, y] = d3mouse(this.svgElement);\n\n\t\tthis.setState({\n\t\t\theightFactor: this.scaleFactor(y),\n\t\t\tlean: this.scaleLean(x)\n\t\t});\n\t};\n\n\trestart = () => {\n\t\tthis.setState({ currentMax: 0 });\n\t\tthis.next();\n\t};\n\n\tnext = () => {\n\t\tlet { currentMax } = this.state;\n\n\t\tif (currentMax < this.realMax) {\n\t\t\tthis.setState({ currentMax: currentMax + 1 });\n\t\t\tthis.timer = setTimeout(this.next, 500);\n\t\t}\n\t};\n\n\tcomponentDidMount() {\n\t\tthis.selected = d3select(this.svgElement).on('mousemove', this.onMouseMove);\n\t\tthis.next();\n\t}\n\n\tcomponentWillUnmount() {\n\t\tthis.selected.on('mousemove', null);\n\t\tclearTimeout(this.timer);\n\t}\n\n\trender({}, { currentMax, baseW, heightFactor, lean }) {\n\t\tlet { width, height } = this.svg;\n\n\t\treturn (\n\t\t\t<div class=\"App\">\n\t\t\t\t<svg width={width} height={height} ref={this.svgRef}>\n\t\t\t\t\t<Pythagoras\n\t\t\t\t\t\tw={baseW}\n\t\t\t\t\t\th={baseW}\n\t\t\t\t\t\theightFactor={heightFactor}\n\t\t\t\t\t\tlean={lean}\n\t\t\t\t\t\tx={width / 2 - 40}\n\t\t\t\t\t\ty={height - baseW}\n\t\t\t\t\t\tlvl={0}\n\t\t\t\t\t\tmaxlvl={currentMax}\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/pythagoras/pythagoras.jsx",
    "content": "import { interpolateViridis } from 'd3-scale';\n\nMath.deg = function (radians) {\n\treturn radians * (180 / Math.PI);\n};\n\nconst memoizedCalc = (function () {\n\tconst memo = {};\n\n\tconst key = ({ w, heightFactor, lean }) => `${w}-${heightFactor}-${lean}`;\n\n\treturn args => {\n\t\tlet memoKey = key(args);\n\n\t\tif (memo[memoKey]) {\n\t\t\treturn memo[memoKey];\n\t\t}\n\n\t\tlet { w, heightFactor, lean } = args;\n\t\tlet trigH = heightFactor * w;\n\n\t\tlet result = {\n\t\t\tnextRight: Math.sqrt(trigH ** 2 + (w * (0.5 + lean)) ** 2),\n\t\t\tnextLeft: Math.sqrt(trigH ** 2 + (w * (0.5 - lean)) ** 2),\n\t\t\tA: Math.deg(Math.atan(trigH / ((0.5 - lean) * w))),\n\t\t\tB: Math.deg(Math.atan(trigH / ((0.5 + lean) * w)))\n\t\t};\n\n\t\tmemo[memoKey] = result;\n\t\treturn result;\n\t};\n})();\n\nexport default function Pythagoras({\n\tw,\n\tx,\n\ty,\n\theightFactor,\n\tlean,\n\tleft,\n\tright,\n\tlvl,\n\tmaxlvl\n}) {\n\tif (lvl >= maxlvl || w < 1) {\n\t\treturn null;\n\t}\n\n\tconst { nextRight, nextLeft, A, B } = memoizedCalc({\n\t\tw,\n\t\theightFactor,\n\t\tlean\n\t});\n\n\tlet rotate = '';\n\n\tif (left) {\n\t\trotate = `rotate(${-A} 0 ${w})`;\n\t} else if (right) {\n\t\trotate = `rotate(${B} ${w} ${w})`;\n\t}\n\n\treturn (\n\t\t<g transform={`translate(${x} ${y}) ${rotate}`}>\n\t\t\t<rect\n\t\t\t\twidth={w}\n\t\t\t\theight={w}\n\t\t\t\tx={0}\n\t\t\t\ty={0}\n\t\t\t\tstyle={{ fill: interpolateViridis(lvl / maxlvl) }}\n\t\t\t/>\n\n\t\t\t<Pythagoras\n\t\t\t\tw={nextLeft}\n\t\t\t\tx={0}\n\t\t\t\ty={-nextLeft}\n\t\t\t\tlvl={lvl + 1}\n\t\t\t\tmaxlvl={maxlvl}\n\t\t\t\theightFactor={heightFactor}\n\t\t\t\tlean={lean}\n\t\t\t\tleft\n\t\t\t/>\n\n\t\t\t<Pythagoras\n\t\t\t\tw={nextRight}\n\t\t\t\tx={w - nextRight}\n\t\t\t\ty={-nextRight}\n\t\t\t\tlvl={lvl + 1}\n\t\t\t\tmaxlvl={maxlvl}\n\t\t\t\theightFactor={heightFactor}\n\t\t\t\tlean={lean}\n\t\t\t\tright\n\t\t\t/>\n\t\t</g>\n\t);\n}\n"
  },
  {
    "path": "demo/redux-toolkit.jsx",
    "content": "import { createElement } from 'preact';\nimport { Provider, useSelector } from 'react-redux';\nimport { configureStore, createSlice } from '@reduxjs/toolkit';\n\nconst initialState = {\n\tvalue: 0\n};\nconst counterSlice = createSlice({\n\tname: 'counter',\n\tinitialState,\n\treducers: {\n\t\tincrement: state => {\n\t\t\tstate.value += 1;\n\t\t},\n\t\tdecrement: state => {\n\t\t\tstate.value -= 1;\n\t\t}\n\t}\n});\nconst store = configureStore({\n\treducer: {\n\t\tcounter: counterSlice.reducer\n\t}\n});\n\nfunction Counter({ number }) {\n\tconst count = useSelector(state => state.counter.value);\n\treturn (\n\t\t<div>\n\t\t\tCounter #{number}:{count}\n\t\t</div>\n\t);\n}\n\nexport default function ReduxToolkit() {\n\tfunction increment() {\n\t\tstore.dispatch(counterSlice.actions.increment());\n\t}\n\tfunction decrement() {\n\t\tstore.dispatch(counterSlice.actions.decrement());\n\t}\n\tfunction incrementAsync() {\n\t\tsetTimeout(() => {\n\t\t\tstore.dispatch(counterSlice.actions.increment());\n\t\t}, 1000);\n\t}\n\treturn (\n\t\t<Provider store={store}>\n\t\t\t<div>\n\t\t\t\t<h1>Redux Toolkit</h1>\n\t\t\t\t<h1>Counter</h1>\n\t\t\t\t<Counter number={1} />\n\t\t\t\t<Counter number={2} />\n\t\t\t\t<button onClick={increment}>+</button>\n\t\t\t\t<button onClick={decrement}>-</button>\n\t\t\t\t<button onClick={incrementAsync}>Increment Async</button>\n\t\t\t</div>\n\t\t</Provider>\n\t);\n}\n"
  },
  {
    "path": "demo/redux.jsx",
    "content": "import { createElement } from 'preact';\nimport React from 'react';\nimport { createStore } from 'redux';\nimport { connect, Provider } from 'react-redux';\n\nconst store = createStore((state = { value: 0 }, action) => {\n\tswitch (action.type) {\n\t\tcase 'increment':\n\t\t\treturn { value: state.value + 1 };\n\t\tcase 'decrement':\n\t\t\treturn { value: state.value - 1 };\n\t\tdefault:\n\t\t\treturn state;\n\t}\n});\n\nclass Child extends React.Component {\n\trender() {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<div>Child #1: {this.props.foo}</div>\n\t\t\t\t<ConnectedChild2 />\n\t\t\t</div>\n\t\t);\n\t}\n}\nconst ConnectedChild = connect(store => ({ foo: store.value }))(Child);\n\nclass Child2 extends React.Component {\n\trender() {\n\t\treturn <div>Child #2: {this.props.foo}</div>;\n\t}\n}\nconst ConnectedChild2 = connect(store => ({ foo: store.value }))(Child2);\n\nexport default function Redux() {\n\treturn (\n\t\t<div>\n\t\t\t<h1>Counter</h1>\n\t\t\t<Provider store={store}>\n\t\t\t\t<ConnectedChild />\n\t\t\t</Provider>\n\t\t\t<br />\n\t\t\t<button onClick={() => store.dispatch({ type: 'increment' })}>+</button>\n\t\t\t<button onClick={() => store.dispatch({ type: 'decrement' })}>-</button>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "demo/reduxUpdate.jsx",
    "content": "import { createElement, Component } from 'preact';\nimport { connect, Provider } from 'react-redux';\nimport { createStore } from 'redux';\nimport { HashRouter, Route, Link } from 'react-router-dom';\n\nconst store = createStore(\n\t(state, action) => ({ ...state, display: action.display }),\n\t{ display: false }\n);\n\nfunction _Redux({ showMe, counter }) {\n\tif (!showMe) return null;\n\treturn <div>showMe {counter}</div>;\n}\nconst Redux = connect(\n\tstate => console.log('injecting', state.display) || { showMe: state.display }\n)(_Redux);\n\nlet display = false;\nclass Test extends Component {\n\tcomponentDidUpdate(prevProps) {\n\t\tif (this.props.start != prevProps.start) {\n\t\t\tthis.setState({ f: (this.props.start || 0) + 1 });\n\t\t\tsetTimeout(() => this.setState({ i: (this.state.i || 0) + 1 }));\n\t\t}\n\t}\n\n\trender() {\n\t\tconst { f } = this.state;\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<button\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tdisplay = !display;\n\t\t\t\t\t\tstore.dispatch({ type: 1, display });\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\tToggle visibility\n\t\t\t\t</button>\n\t\t\t\t<Link to={`/${(parseInt(this.props.start) || 0) + 1}`}>Click me</Link>\n\n\t\t\t\t<Redux counter={f} />\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nfunction App() {\n\treturn (\n\t\t<Provider store={store}>\n\t\t\t<HashRouter>\n\t\t\t\t<Route\n\t\t\t\t\tpath=\"/:start?\"\n\t\t\t\t\trender={({ match }) => <Test start={match.params.start || 0} />}\n\t\t\t\t/>\n\t\t\t</HashRouter>\n\t\t</Provider>\n\t);\n}\n\nexport default App;\n"
  },
  {
    "path": "demo/reorder.jsx",
    "content": "import { createElement, Component } from 'preact';\n\nfunction createItems(count = 10) {\n\tlet items = [];\n\tfor (let i = 0; i < count; i++) {\n\t\titems.push({\n\t\t\tlabel: `Item #${i + 1}`,\n\t\t\tkey: i + 1\n\t\t});\n\t}\n\treturn items;\n}\n\nfunction random() {\n\treturn Math.random() < 0.5 ? 1 : -1;\n}\n\nexport default class Reorder extends Component {\n\tstate = {\n\t\titems: createItems(),\n\t\tcount: 1,\n\t\tuseKeys: false\n\t};\n\n\tshuffle = () => {\n\t\tthis.setState({ items: this.state.items.slice().sort(random) });\n\t};\n\n\tswapTwo = () => {\n\t\tlet items = this.state.items.slice(),\n\t\t\tfirst = Math.floor(Math.random() * items.length),\n\t\t\tsecond;\n\t\tdo {\n\t\t\tsecond = Math.floor(Math.random() * items.length);\n\t\t} while (second === first);\n\t\tlet other = items[first];\n\t\titems[first] = items[second];\n\t\titems[second] = other;\n\t\tthis.setState({ items });\n\t};\n\n\treverse = () => {\n\t\tthis.setState({ items: this.state.items.slice().reverse() });\n\t};\n\n\tsetCount = e => {\n\t\tthis.setState({ count: Math.round(e.target.value) });\n\t};\n\n\trotate = () => {\n\t\tlet { items, count } = this.state;\n\t\titems = items.slice(count).concat(items.slice(0, count));\n\t\tthis.setState({ items });\n\t};\n\n\trotateBackward = () => {\n\t\tlet { items, count } = this.state,\n\t\t\tlen = items.length;\n\t\titems = items.slice(len - count, len).concat(items.slice(0, len - count));\n\t\tthis.setState({ items });\n\t};\n\n\ttoggleKeys = () => {\n\t\tthis.setState({ useKeys: !this.state.useKeys });\n\t};\n\n\trenderItem = item => (\n\t\t<li key={this.state.useKeys ? item.key : null}>{item.label}</li>\n\t);\n\n\trender({}, { items, count, useKeys }) {\n\t\treturn (\n\t\t\t<div class=\"reorder-demo\">\n\t\t\t\t<header>\n\t\t\t\t\t<button onClick={this.shuffle}>Shuffle</button>\n\t\t\t\t\t<button onClick={this.swapTwo}>Swap Two</button>\n\t\t\t\t\t<button onClick={this.reverse}>Reverse</button>\n\t\t\t\t\t<button onClick={this.rotate}>Rotate</button>\n\t\t\t\t\t<button onClick={this.rotateBackward}>Rotate Backward</button>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tonClick={this.toggleKeys}\n\t\t\t\t\t\t\tchecked={useKeys}\n\t\t\t\t\t\t/>{' '}\n\t\t\t\t\t\tuse keys?\n\t\t\t\t\t</label>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\tstep=\"1\"\n\t\t\t\t\t\t\tmin=\"1\"\n\t\t\t\t\t\t\tstyle={{ width: '3em' }}\n\t\t\t\t\t\t\tonInput={this.setCount}\n\t\t\t\t\t\t\tvalue={count}\n\t\t\t\t\t\t/>{' '}\n\t\t\t\t\t\tcount\n\t\t\t\t\t</label>\n\t\t\t\t</header>\n\t\t\t\t<ul>{items.map(this.renderItem)}</ul>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/spiral.jsx",
    "content": "import { createElement, Component } from 'preact';\n\nconst COUNT = 500;\nconst LOOPS = 6;\n\n// Component.debounce = requestAnimationFrame;\n\nexport default class Spiral extends Component {\n\tstate = { x: 0, y: 0, big: false, counter: 0 };\n\n\thandleClick = e => {\n\t\tconsole.log('click');\n\t};\n\n\tincrement = () => {\n\t\tif (this.stop) return;\n\t\t// this.setState({ counter: this.state.counter + 1 }, this.increment);\n\t\tthis.setState({ counter: this.state.counter + 1 });\n\t\t// this.forceUpdate();\n\t\trequestAnimationFrame(this.increment);\n\t};\n\n\tsetMouse({ pageX: x, pageY: y }) {\n\t\tthis.setState({ x, y });\n\t\treturn false;\n\t}\n\n\tsetBig(big) {\n\t\tthis.setState({ big });\n\t}\n\n\tcomponentDidMount() {\n\t\tconsole.log('mount');\n\n\t\t// let touch = navigator.maxTouchPoints > 1;\n\t\tlet touch = false;\n\n\t\t// set mouse position state on move:\n\t\taddEventListener(touch ? 'touchmove' : 'mousemove', e => {\n\t\t\tthis.setMouse(e.touches ? e.touches[0] : e);\n\t\t});\n\n\t\t// holding the mouse down enables big mode:\n\t\taddEventListener(touch ? 'touchstart' : 'mousedown', e => {\n\t\t\tthis.setBig(true);\n\t\t\te.preventDefault();\n\t\t});\n\t\taddEventListener(touch ? 'touchend' : 'mouseup', e => this.setBig(false));\n\n\t\trequestAnimationFrame(this.increment);\n\t}\n\n\tcomponentWillUnmount() {\n\t\tconsole.log('unmount');\n\t\tthis.stop = true;\n\t}\n\n\t// componentDidUpdate() {\n\t// \t// invoking setState() in componentDidUpdate() creates an animation loop:\n\t// \tthis.increment();\n\t// }\n\n\t// builds and returns a brand new DOM (every time)\n\trender(props, { x, y, big, counter }) {\n\t\tlet max =\n\t\t\t\tCOUNT +\n\t\t\t\tMath.round(Math.sin((counter / 90) * 2 * Math.PI) * COUNT * 0.5),\n\t\t\tcursors = [];\n\n\t\t// the advantage of JSX is that you can use the entirety of JS to \"template\":\n\t\tfor (let i = max; i--; ) {\n\t\t\tlet f = (i / max) * LOOPS,\n\t\t\t\tθ = f * 2 * Math.PI,\n\t\t\t\tm = 20 + i * 2,\n\t\t\t\thue = (f * 255 + counter * 10) % 255;\n\t\t\tcursors[i] = (\n\t\t\t\t<Cursor\n\t\t\t\t\tbig={big}\n\t\t\t\t\tcolor={'hsl(' + hue + ',100%,50%)'}\n\t\t\t\t\tx={(x + Math.sin(θ) * m) | 0}\n\t\t\t\t\ty={(y + Math.cos(θ) * m) | 0}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<div id=\"main\" onClick={this.handleClick}>\n\t\t\t\t<Cursor label x={x} y={y} big={big} />\n\t\t\t\t{cursors}\n\t\t\t</div>\n\t\t);\n\t}\n}\n\n/** Represents a single coloured dot. */\nclass Cursor extends Component {\n\t// get shared/pooled class object\n\tgetClass(big, label) {\n\t\tlet cl = 'cursor';\n\t\tif (big) cl += ' big';\n\t\tif (label) cl += ' label';\n\t\treturn cl;\n\t}\n\n\t// skip any pointless re-renders\n\tshouldComponentUpdate(props) {\n\t\tfor (let i in props)\n\t\t\tif (i !== 'children' && props[i] !== this.props[i]) return true;\n\t\treturn false;\n\t}\n\n\t// first argument is \"props\", the attributes passed to <Cursor ...>\n\trender({ x, y, label, color, big }) {\n\t\tlet inner = null;\n\t\tif (label)\n\t\t\tinner = (\n\t\t\t\t<span class=\"label\">\n\t\t\t\t\t{x},{y}\n\t\t\t\t</span>\n\t\t\t);\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclass={this.getClass(big, label)}\n\t\t\t\tstyle={{\n\t\t\t\t\ttransform: `translate(${x || 0}px, ${y || 0}px) scale(${\n\t\t\t\t\t\tbig ? 2 : 1\n\t\t\t\t\t})`,\n\t\t\t\t\t// transform: `translate3d(${x || 0}px, ${y || 0}px, 0) scale(${big?2:1})`,\n\t\t\t\t\tborderColor: color\n\t\t\t\t}}\n\t\t\t\t// style={{ left: x || 0, top: y || 0, borderColor: color }}\n\t\t\t>\n\t\t\t\t{inner}\n\t\t\t</div>\n\t\t);\n\t}\n}\n\n// Addendum: disable dragging on mobile\naddEventListener('touchstart', e => (e.preventDefault(), false));\n"
  },
  {
    "path": "demo/stateOrderBug.jsx",
    "content": "import htm from 'htm';\nimport { h } from 'preact';\nimport { useState, useCallback } from 'preact/hooks';\n\nconst html = htm.bind(h);\n\n// configuration used to show behavior vs. workaround\nlet childFirst = true;\nconst Config = () => html`\n\t<label>\n\t\t<input\n\t\t\ttype=\"checkbox\"\n\t\t\tchecked=${childFirst}\n\t\t\tonchange=${evt => {\n\t\t\t\tchildFirst = evt.target.checked;\n\t\t\t}}\n\t\t/>\n\t\tSet child state before parent state.\n\t</label>\n`;\n\nconst Child = ({ items, setItems }) => {\n\tlet [pendingId, setPendingId] = useState(null);\n\tif (!pendingId) {\n\t\tsetPendingId((pendingId = Math.random().toFixed(20).slice(2)));\n\t}\n\n\tconst onInput = useCallback(\n\t\tevt => {\n\t\t\tlet val = evt.target.value,\n\t\t\t\t_items = [...items, { _id: pendingId, val }];\n\t\t\tif (childFirst) {\n\t\t\t\tsetPendingId(null);\n\t\t\t\tsetItems(_items);\n\t\t\t} else {\n\t\t\t\tsetItems(_items);\n\t\t\t\tsetPendingId(null);\n\t\t\t}\n\t\t},\n\t\t[childFirst, setPendingId, setItems, items, pendingId]\n\t);\n\n\treturn html`\n\t\t<div class=\"item-editor\">\n\t\t\t${items.map(\n\t\t\t\t(item, idx) => html`\n\t\t\t\t\t<input\n\t\t\t\t\t\tkey=${item._id}\n\t\t\t\t\t\tvalue=${item.val}\n\t\t\t\t\t\toninput=${evt => {\n\t\t\t\t\t\t\tlet val = evt.target.value,\n\t\t\t\t\t\t\t\t_items = [...items];\n\t\t\t\t\t\t\t_items.splice(idx, 1, { ...item, val });\n\t\t\t\t\t\t\tsetItems(_items);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t`\n\t\t\t)}\n\n\t\t\t<input\n\t\t\t\tkey=${pendingId}\n\t\t\t\tplaceholder=\"type to add an item\"\n\t\t\t\toninput=${onInput}\n\t\t\t/>\n\t\t</div>\n\t`;\n};\n\nconst Parent = () => {\n\tlet [items, setItems] = useState([]);\n\treturn html`\n\t\t<div><${Config} /><${Child} items=${items} setItems=${setItems} /></div>\n\t`;\n};\n\nexport default Parent;\n"
  },
  {
    "path": "demo/style.css",
    "content": "html,\nbody {\n\tfont:\n\t\t14px system-ui,\n\t\tsans-serif;\n}\n.list {\n\tlist-style: none;\n\tpadding: 0;\n}\n.list > li {\n\tposition: relative;\n\tpadding: 5px 10px;\n\tanimation: fadeIn 1s ease;\n}\n@keyframes fadeIn {\n\t0% {\n\t\tbox-shadow:\n\t\t\tinset 0 0 2px 2px red,\n\t\t\t0 0 2px 2px red;\n\t}\n}\n.list > .odd {\n\tbackground-color: #def;\n}\n.list > .even {\n\tbackground-color: #fed;\n}\n"
  },
  {
    "path": "demo/style.scss",
    "content": "html,\nbody {\n\theight: 100%;\n\tmargin: 0;\n\tbackground: #eee;\n\tfont: 400 16px/1.3 'Helvetica Neue', helvetica, sans-serif;\n\ttext-rendering: optimizeSpeed;\n\tcolor: #444;\n}\n\n.app {\n\tdisplay: block;\n\tflex-direction: column;\n\theight: 100%;\n\n\t> header {\n\t\tflex: 0;\n\t\tbackground: #f9f9f9;\n\t\tbox-shadow: inset 0 -0.5px 0 0 rgba(0, 0, 0, 0.2),\n\t\t\t0 0.5px 0 0 rgba(255, 255, 255, 0.6);\n\n\t\tnav {\n\t\t\tdisplay: inline-block;\n\t\t\tpadding: 4px 7px;\n\n\t\t\ta {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tmargin: 2px;\n\t\t\t\tpadding: 4px 10px;\n\t\t\t\tbackground-color: rgba(255, 255, 255, 0);\n\t\t\t\tborder-radius: 1em;\n\t\t\t\tcolor: #6b1d8f;\n\t\t\t\ttext-decoration: none;\n\t\t\t\t// transition: all 250ms ease;\n\t\t\t\ttransition: all 250ms cubic-bezier(0.2, 0, 0.4, 2);\n\t\t\t\t&:hover {\n\t\t\t\t\tbackground-color: rgba(255, 255, 255, 1);\n\t\t\t\t\tbox-shadow: 0 0 0 2px #6b1d8f;\n\t\t\t\t}\n\t\t\t\t&.active {\n\t\t\t\t\tbackground-color: #6b1d8f;\n\t\t\t\t\tcolor: white;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t> main {\n\t\tflex: 1;\n\t\tpadding: 10px;\n\t}\n}\n\nh1 {\n\tmargin: 0;\n\tcolor: #6b1d8f;\n\tfont-weight: 300;\n\tfont-size: 250%;\n}\n\ninput,\ntextarea {\n\tbox-sizing: border-box;\n\tmargin: 1px;\n\tpadding: 0.25em 0.5em;\n\tbackground: #fff;\n\tborder: 1px solid #999;\n\tborder-radius: 3px;\n\tfont: inherit;\n\tcolor: #000;\n\toutline: none;\n\n\t&:focus {\n\t\tborder-color: #6b1d8f;\n\t}\n}\n\nbutton,\ninput[type='submit'],\ninput[type='reset'],\ninput[type='button'] {\n\tbox-sizing: border-box;\n\tmargin: 1px;\n\tpadding: 0.25em 0.8em;\n\tbackground: #6b1d8f;\n\tborder: 1px solid #6b1d8f;\n\t// border: none;\n\tborder-radius: 1.5em;\n\tfont: inherit;\n\tcolor: white;\n\toutline: none;\n\tcursor: pointer;\n}\n\n.cursor {\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 8px;\n\theight: 8px;\n\tmargin: -5px 0 0 -5px;\n\tborder: 2px solid #f00;\n\tborder-radius: 50%;\n\ttransform-origin: 50% 50%;\n\tpointer-events: none;\n\toverflow: hidden;\n\tfont-size: 9px;\n\tline-height: 25px;\n\ttext-indent: 15px;\n\twhite-space: nowrap;\n\n\t&:not(.label) {\n\t\tcontain: strict;\n\t}\n\n\t&.label {\n\t\toverflow: visible;\n\t}\n\n\t// &.big {\n\t// \ttransform: scale(2);\n\t// \t// width: 24px;\n\t// \t// height: 24px;\n\t// \t// margin: -13px 0 0 -13px;\n\t// }\n\n\t.label {\n\t\tposition: absolute;\n\t\tleft: 0;\n\t\ttop: 0;\n\t\t//transform: translateZ(0);\n\t\t// z-index: 10;\n\t}\n}\n\n.animation-picker {\n\tposition: fixed;\n\tdisplay: inline-block;\n\tright: 0;\n\ttop: 0;\n\tpadding: 10px;\n\tbackground: #000;\n\tcolor: #bbb;\n\tz-index: 1000;\n\n\tselect {\n\t\tfont-size: 100%;\n\t\tmargin-left: 5px;\n\t}\n}\n"
  },
  {
    "path": "demo/styled-components.jsx",
    "content": "import { createElement } from 'preact';\nimport styled, { css } from 'styled-components';\n\nconst Button = styled.button`\n\tbackground: transparent;\n\tborder-radius: 3px;\n\tborder: 2px solid palevioletred;\n\tcolor: palevioletred;\n\tmargin: 0.5em 1em;\n\tpadding: 0.25em 1em;\n\n\t${props =>\n\t\tprops.primary &&\n\t\tcss`\n\t\t\tbackground: palevioletred;\n\t\t\tcolor: white;\n\t\t`}\n`;\n\nconst Container = styled.div`\n\ttext-align: center;\n`;\n\nexport default function StyledComp() {\n\treturn (\n\t\t<Container>\n\t\t\t<Button>Normal Button</Button>\n\t\t\t<Button primary>Primary Button</Button>\n\t\t</Container>\n\t);\n}\n"
  },
  {
    "path": "demo/suspense-router/bye.jsx",
    "content": "import { Link } from './simple-router';\n\nexport default function Bye() {\n\treturn (\n\t\t<div>\n\t\t\tBye! <Link to=\"/\">Go to Hello!</Link>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "demo/suspense-router/hello.jsx",
    "content": "import { Link } from './simple-router';\n\nexport default function Hello() {\n\treturn (\n\t\t<div>\n\t\t\tHello! <Link to=\"/bye\">Go to Bye!</Link>\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "demo/suspense-router/index.jsx",
    "content": "import { Suspense, lazy } from 'react';\n\nimport { Router, Route, Switch } from './simple-router';\n\nlet Hello = lazy(() => import('./hello.jsx'));\nlet Bye = lazy(() => import('./bye.jsx'));\n\nfunction Loading() {\n\treturn <div>Hey! This is a fallback because we're loading things! :D</div>;\n}\n\nexport default function SuspenseRouterBug() {\n\treturn (\n\t\t<Router>\n\t\t\t<h1>Suspense Router bug</h1>\n\t\t\t<Suspense fallback={<Loading />}>\n\t\t\t\t<Switch>\n\t\t\t\t\t<Route path=\"/\" exact>\n\t\t\t\t\t\t<Hello />\n\t\t\t\t\t</Route>\n\t\t\t\t\t<Route path=\"/bye\">\n\t\t\t\t\t\t<Bye />\n\t\t\t\t\t</Route>\n\t\t\t\t</Switch>\n\t\t\t</Suspense>\n\t\t</Router>\n\t);\n}\n"
  },
  {
    "path": "demo/suspense-router/simple-router.jsx",
    "content": "import {\n\tcreateContext,\n\tuseState,\n\tuseContext,\n\tChildren,\n\tuseLayoutEffect\n} from 'react';\n\nconst memoryHistory = {\n\t/**\n\t * @typedef {{ pathname: string }} Location\n\t * @typedef {(location: Location) => void} HistoryListener\n\t * @type {HistoryListener[]}\n\t */\n\tlisteners: [],\n\n\t/**\n\t * @param {HistoryListener} listener\n\t */\n\tlisten(listener) {\n\t\tconst newLength = this.listeners.push(listener);\n\t\treturn () => this.listeners.splice(newLength - 1, 1);\n\t},\n\n\t/**\n\t * @param {Location} to\n\t */\n\tnavigate(to) {\n\t\tthis.listeners.forEach(listener => listener(to));\n\t}\n};\n\n/** @type {import('react').Context<{ history: typeof memoryHistory; location: Location }>} */\nconst RouterContext = createContext(null);\n\nexport function Router({ history = memoryHistory, children }) {\n\tconst [location, setLocation] = useState({ pathname: '/' });\n\n\tuseLayoutEffect(() => {\n\t\treturn history.listen(newLocation => setLocation(newLocation));\n\t}, []);\n\n\treturn (\n\t\t<RouterContext.Provider value={{ history, location }}>\n\t\t\t{children}\n\t\t</RouterContext.Provider>\n\t);\n}\n\nexport function Switch(props) {\n\tconst { location } = useContext(RouterContext);\n\n\tlet element = null;\n\tChildren.forEach(props.children, child => {\n\t\tif (element == null && child.props.path == location.pathname) {\n\t\t\telement = child;\n\t\t}\n\t});\n\n\treturn element;\n}\n\n/**\n * @param {{ children: any; path: string; exact?: boolean; }} props\n */\nexport function Route({ children, path, exact }) {\n\treturn children;\n}\n\nexport function Link({ to, children }) {\n\tconst { history } = useContext(RouterContext);\n\tconst onClick = event => {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\thistory.navigate({ pathname: to });\n\t};\n\n\treturn (\n\t\t<a href={to} onClick={onClick}>\n\t\t\t{children}\n\t\t</a>\n\t);\n}\n"
  },
  {
    "path": "demo/suspense.jsx",
    "content": "// eslint-disable-next-line no-unused-vars\nimport {\n\tcreateElement,\n\tComponent,\n\tmemo,\n\tFragment,\n\tSuspense,\n\tlazy\n} from 'react';\n\nfunction LazyComp() {\n\treturn <div>I'm (fake) lazy loaded</div>;\n}\n\nconst Lazy = lazy(() => Promise.resolve({ default: LazyComp }));\n\nfunction createSuspension(name, timeout, error) {\n\tlet done = false;\n\tlet prom;\n\n\treturn {\n\t\tname,\n\t\ttimeout,\n\t\tstart: () => {\n\t\t\tif (!prom) {\n\t\t\t\tprom = new Promise((res, rej) => {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\trej(error);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tres();\n\t\t\t\t\t\t}\n\t\t\t\t\t}, timeout);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn prom;\n\t\t},\n\t\tgetPromise: () => prom,\n\t\tisDone: () => done\n\t};\n}\n\nfunction CustomSuspense({ isDone, start, timeout, name }) {\n\tif (!isDone()) {\n\t\tthrow start();\n\t}\n\n\treturn (\n\t\t<div>\n\t\t\tHello from CustomSuspense {name}, loaded after {timeout / 1000}s\n\t\t</div>\n\t);\n}\n\nfunction init() {\n\treturn {\n\t\ts1: createSuspension('1', 1000, null),\n\t\ts2: createSuspension('2', 2000, null),\n\t\ts3: createSuspension('3', 3000, null)\n\t};\n}\n\nexport default class DevtoolsDemo extends Component {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = init();\n\t\tthis.onRerun = this.onRerun.bind(this);\n\t}\n\n\tonRerun() {\n\t\tthis.setState(init());\n\t}\n\n\trender(props, state) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<h1>lazy()</h1>\n\t\t\t\t<Suspense fallback={<div>Loading (fake) lazy loaded component...</div>}>\n\t\t\t\t\t<Lazy />\n\t\t\t\t</Suspense>\n\t\t\t\t<h1>Suspense</h1>\n\t\t\t\t<div>\n\t\t\t\t\t<button onClick={this.onRerun}>Rerun</button>\n\t\t\t\t</div>\n\t\t\t\t<Suspense fallback={<div>Fallback 1</div>}>\n\t\t\t\t\t<CustomSuspense {...state.s1} />\n\t\t\t\t\t<Suspense fallback={<div>Fallback 2</div>}>\n\t\t\t\t\t\t<CustomSuspense {...state.s2} />\n\t\t\t\t\t\t<CustomSuspense {...state.s3} />\n\t\t\t\t\t</Suspense>\n\t\t\t\t</Suspense>\n\t\t\t</div>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "demo/textFields.jsx",
    "content": "import React, { useState } from 'react';\nimport TextField from '@material-ui/core/TextField';\n\nconst PatchedTextField = props => {\n\tconst [value, set] = useState(props.value);\n\treturn (\n\t\t<TextField {...props} value={value} onChange={e => set(e.target.value)} />\n\t);\n};\n\nconst TextFields = () => (\n\t<div>\n\t\t<TextField\n\t\t\tvariant=\"outlined\"\n\t\t\tmargin=\"normal\"\n\t\t\tfullWidth\n\t\t\tlabel=\"Cannot type in\"\n\t\t/>\n\t\t<PatchedTextField\n\t\t\tvariant=\"outlined\"\n\t\t\tmargin=\"normal\"\n\t\t\tfullWidth\n\t\t\tlabel=\"I can\"\n\t\t/>\n\t\t<TextField\n\t\t\tdefaultValue=\"Reset after blur or empty\"\n\t\t\tvariant=\"outlined\"\n\t\t\tmargin=\"normal\"\n\t\t\tfullWidth\n\t\t\tlabel=\"default value\"\n\t\t/>\n\t</div>\n);\n\nexport default TextFields;\n"
  },
  {
    "path": "demo/todo.jsx",
    "content": "import { createElement, Component } from 'preact';\n\nlet counter = 0;\n\nexport default class TodoList extends Component {\n\tstate = { todos: [], text: '' };\n\n\tsetText = e => {\n\t\tthis.setState({ text: e.target.value });\n\t};\n\n\taddTodo = () => {\n\t\tlet { todos, text } = this.state;\n\t\ttodos = todos.concat({ text, id: ++counter });\n\t\tthis.setState({ todos, text: '' });\n\t};\n\n\tremoveTodo = e => {\n\t\tlet id = e.target.getAttribute('data-id');\n\t\tthis.setState({ todos: this.state.todos.filter(t => t.id != id) });\n\t};\n\n\trender({}, { todos, text }) {\n\t\treturn (\n\t\t\t<form onSubmit={this.addTodo} action=\"javascript:\">\n\t\t\t\t<input value={text} onInput={this.setText} />\n\t\t\t\t<button type=\"submit\">Add</button>\n\t\t\t\t<ul>\n\t\t\t\t\t<TodoItems todos={todos} removeTodo={this.removeTodo} />\n\t\t\t\t</ul>\n\t\t\t</form>\n\t\t);\n\t}\n}\n\nclass TodoItems extends Component {\n\trender({ todos, removeTodo }) {\n\t\treturn todos.map(todo => (\n\t\t\t<li key={todo.id}>\n\t\t\t\t<button type=\"button\" onClick={removeTodo} data-id={todo.id}>\n\t\t\t\t\t&times;\n\t\t\t\t</button>{' '}\n\t\t\t\t{todo.text}\n\t\t\t</li>\n\t\t));\n\t}\n}\n"
  },
  {
    "path": "demo/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"h\",\n    \"baseUrl\": \".\",\n    \"target\": \"es2018\",\n    \"module\": \"es2015\",\n    \"moduleResolution\": \"node\",\n    \"paths\": {\n      \"preact/hooks\": [\"../hooks/src/index.js\"],\n      \"preact\": [\"../src/index.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "demo/vite.config.js",
    "content": "import { defineConfig } from 'vite';\nimport path from 'node:path';\n\nconst root = path.join(__dirname, '..');\nconst resolvePkg = (...parts) => path.join(root, ...parts, 'src', 'index.js');\n\n// https://vitejs.dev/config/\n/** @type {import('vite').UserConfig} */\nexport default defineConfig({\n\toptimizeDeps: {\n\t\texclude: [\n\t\t\t'preact',\n\t\t\t'preact/compat',\n\t\t\t'preact/debug',\n\t\t\t'preact/hooks',\n\t\t\t'preact/devtools',\n\t\t\t'preact/jsx-runtime',\n\t\t\t'preact/jsx-dev-runtime',\n\t\t\t'preact-router',\n\t\t\t'react',\n\t\t\t'react-dom'\n\t\t]\n\t},\n\tresolve: {\n\t\talias: {\n\t\t\t'preact/debug/src/debug': path.join(root, 'debug', 'src', 'debug'),\n\t\t\t'preact/devtools/src/devtools': path.join(\n\t\t\t\troot,\n\t\t\t\t'devtools',\n\t\t\t\t'src',\n\t\t\t\t'devtools'\n\t\t\t),\n\t\t\t//'preact/debug': resolvePkg('debug'),\n\t\t\t'preact/devtools': resolvePkg('devtools'),\n\t\t\t'preact/hooks': resolvePkg('hooks'),\n\t\t\t'preact/jsx-runtime': resolvePkg('jsx-runtime'),\n\t\t\t'preact/jsx-dev-runtime': resolvePkg('jsx-runtime'),\n\t\t\tpreact: resolvePkg(''),\n\t\t\t'react-dom': resolvePkg('compat'),\n\t\t\treact: resolvePkg('compat')\n\t\t}\n\t},\n\tesbuild: {\n\t\tjsx: 'automatic',\n\t\tjsxImportSource: 'preact'\n\t}\n});\n"
  },
  {
    "path": "demo/zustand.jsx",
    "content": "import { createElement } from 'preact';\nimport create from 'zustand';\n\nconst useStore = create(set => ({\n\tvalue: 0,\n\ttext: 'John',\n\tsetText: text => set(state => ({ ...state, text })),\n\tincrement: () => set(state => ({ value: state.value + 1 })),\n\tdecrement: () => set(state => ({ value: state.value - 1 })),\n\tincrementAsync: async () => {\n\t\tawait new Promise(resolve => setTimeout(resolve, 1000));\n\t\tset(state => ({ value: state.value + 1 }));\n\t}\n}));\n\nfunction Counter({ number }) {\n\tconst value = useStore(state => state.value);\n\treturn (\n\t\t<div>\n\t\t\tCounter #{number}: {value}\n\t\t</div>\n\t);\n}\nfunction Text() {\n\tconst text = useStore(state => state.text);\n\tconst { setText } = useStore();\n\tfunction handleInput(e) {\n\t\tsetText(e.target.value);\n\t}\n\treturn (\n\t\t<div>\n\t\t\tText: {text}\n\t\t\t<input value={text} onInput={handleInput} />\n\t\t</div>\n\t);\n}\n\nexport default function ZustandComponent() {\n\tconst { increment, decrement, incrementAsync } = useStore();\n\n\treturn (\n\t\t<div>\n\t\t\t<h1>Zustand</h1>\n\t\t\t<h1>Counter</h1>\n\t\t\t<Counter number={1} />\n\t\t\t<Counter number={2} />\n\t\t\t<button onClick={increment}>+</button>\n\t\t\t<button onClick={decrement}>-</button>\n\t\t\t<button onClick={incrementAsync}>Increment Async</button>\n\t\t\t<Text />\n\t\t</div>\n\t);\n}\n"
  },
  {
    "path": "devtools/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-present Jason Miller\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": "devtools/mangle.json",
    "content": "{\n  \"help\": {\n    \"what is this file?\": \"It controls protected/private property mangling so that minified builds have consistent property names.\",\n    \"why are there duplicate minified properties?\": \"Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size.\"\n  },\n  \"minify\": {\n    \"mangle\": {\n      \"properties\": {\n        \"regex\": \"^_[^_]\",\n        \"reserved\": [\n          \"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\",\n          \"__REACT_DEVTOOLS_GLOBAL_HOOK__\",\n          \"__PREACT_DEVTOOLS__\",\n          \"_renderers\",\n          \"__source\",\n          \"__self\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "devtools/package.json",
    "content": "{\n  \"name\": \"preact-devtools\",\n  \"amdName\": \"preactDevtools\",\n  \"private\": true,\n  \"description\": \"Preact bridge for Preact devtools\",\n  \"main\": \"dist/devtools.js\",\n  \"module\": \"dist/devtools.mjs\",\n  \"umd:main\": \"dist/devtools.umd.js\",\n  \"source\": \"src/index.js\",\n  \"types\": \"src/index.d.ts\",\n  \"license\": \"MIT\",\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "devtools/src/devtools.js",
    "content": "import { Component, Fragment, options } from 'preact';\n\nexport function initDevTools() {\n\tconst globalVar =\n\t\ttypeof globalThis !== 'undefined'\n\t\t\t? globalThis\n\t\t\t: typeof window !== 'undefined'\n\t\t\t\t? window\n\t\t\t\t: undefined;\n\n\tif (\n\t\tglobalVar !== null &&\n\t\tglobalVar !== undefined &&\n\t\tglobalVar.__PREACT_DEVTOOLS__\n\t) {\n\t\tglobalVar.__PREACT_DEVTOOLS__.attachPreact('11.0.0-beta.1', options, {\n\t\t\tFragment,\n\t\t\tComponent\n\t\t});\n\t}\n}\n"
  },
  {
    "path": "devtools/src/index.d.ts",
    "content": "/**\n * Customize the displayed name of a useState, useReducer or useRef hook\n * in the devtools panel.\n *\n * @param value Wrapped native hook.\n * @param name Custom name\n */\nexport function addHookName<T>(value: T, name: string): T;\n"
  },
  {
    "path": "devtools/src/index.js",
    "content": "import { options } from 'preact';\nimport { initDevTools } from './devtools';\n\ninitDevTools();\n\n/**\n * Display a custom label for a custom hook for the devtools panel\n * @type {<T>(value: T, name: string) => T}\n */\nexport function addHookName(value, name) {\n\tif (options._addHookName) {\n\t\toptions._addHookName(name);\n\t}\n\treturn value;\n}\n"
  },
  {
    "path": "devtools/test/browser/addHookName.test.jsx",
    "content": "import { createElement, render, options } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useState } from 'preact/hooks';\nimport { addHookName } from 'preact/devtools';\nimport { vi } from 'vitest';\n\ndescribe('addHookName', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tdelete options._addHookName;\n\t});\n\n\tit('should do nothing when no options hook is present', () => {\n\t\tfunction useFoo() {\n\t\t\treturn addHookName(useState(0), 'foo');\n\t\t}\n\n\t\tfunction App() {\n\t\t\tlet [v] = useFoo();\n\t\t\treturn <div>{v}</div>;\n\t\t}\n\n\t\texpect(() => render(<App />, scratch)).to.not.throw();\n\t});\n\n\tit('should call options hook with value', () => {\n\t\tlet spy = (options._addHookName = vi.fn());\n\n\t\tfunction useFoo() {\n\t\t\treturn addHookName(useState(0), 'foo');\n\t\t}\n\n\t\tfunction App() {\n\t\t\tlet [v] = useFoo();\n\t\t\treturn <div>{v}</div>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith('foo');\n\t});\n});\n"
  },
  {
    "path": "hooks/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-present Jason Miller\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": "hooks/mangle.json",
    "content": "{\n  \"help\": {\n    \"what is this file?\": \"It controls protected/private property mangling so that minified builds have consistent property names.\",\n    \"why are there duplicate minified properties?\": \"Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size.\"\n  },\n  \"minify\": {\n    \"mangle\": {\n      \"properties\": {\n        \"regex\": \"^_[^_]\",\n        \"reserved\": [\n          \"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\",\n          \"__REACT_DEVTOOLS_GLOBAL_HOOK__\",\n          \"__PREACT_DEVTOOLS__\",\n          \"_renderers\",\n          \"__source\",\n          \"__self\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "hooks/package.json",
    "content": "{\n  \"name\": \"preact-hooks\",\n  \"amdName\": \"preactHooks\",\n  \"private\": true,\n  \"description\": \"Hook addon for Preact\",\n  \"main\": \"dist/hooks.js\",\n  \"module\": \"dist/hooks.mjs\",\n  \"umd:main\": \"dist/hooks.umd.js\",\n  \"source\": \"src/index.js\",\n  \"types\": \"src/index.d.ts\",\n  \"license\": \"MIT\",\n  \"mangle\": {\n    \"regex\": \"^_\"\n  },\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "hooks/src/index.d.ts",
    "content": "import { ErrorInfo, PreactContext, Ref, RefObject } from '../../src/index';\n\ntype Inputs = ReadonlyArray<unknown>;\n\nexport type Dispatch<A> = (value: A) => void;\nexport type StateUpdater<S> = S | ((prevState: S) => S);\n\n/**\n * Returns a stateful value, and a function to update it.\n * @param initialState The initial value (or a function that returns the initial value)\n */\nexport function useState<S>(\n\tinitialState: S | (() => S)\n): [S, Dispatch<StateUpdater<S>>];\n\nexport function useState<S = undefined>(): [\n\tS | undefined,\n\tDispatch<StateUpdater<S | undefined>>\n];\n\nexport type Reducer<S, A> = (prevState: S, action: A) => S;\n\n/**\n * An alternative to `useState`.\n *\n * `useReducer` is usually preferable to `useState` when you have complex state logic that involves\n * multiple sub-values. It also lets you optimize performance for components that trigger deep\n * updates because you can pass `dispatch` down instead of callbacks.\n * @param reducer Given the current state and an action, returns the new state\n * @param initialState The initial value to store as state\n */\nexport function useReducer<S, A>(\n\treducer: Reducer<S, A>,\n\tinitialState: S\n): [S, Dispatch<A>];\n\n/**\n * An alternative to `useState`.\n *\n * `useReducer` is usually preferable to `useState` when you have complex state logic that involves\n * multiple sub-values. It also lets you optimize performance for components that trigger deep\n * updates because you can pass `dispatch` down instead of callbacks.\n * @param reducer Given the current state and an action, returns the new state\n * @param initialArg The initial argument to pass to the `init` function\n * @param init A function that, given the `initialArg`, returns the initial value to store as state\n */\nexport function useReducer<S, A, I>(\n\treducer: Reducer<S, A>,\n\tinitialArg: I,\n\tinit: (arg: I) => S\n): [S, Dispatch<A>];\n\n/**\n * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument\n * (`initialValue`). The returned object will persist for the full lifetime of the component.\n *\n * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable\n * value around similar to how you’d use instance fields in classes.\n *\n * @param initialValue the initial value to store in the ref object\n */\nexport function useRef<T>(initialValue: T): RefObject<T>;\nexport function useRef<T>(initialValue: T | null): RefObject<T | null>;\nexport function useRef<T>(\n\tinitialValue: T | undefined\n): RefObject<T | undefined>;\n\ntype EffectCallback = () => void | (() => void);\n/**\n * Accepts a function that contains imperative, possibly effectful code.\n * The effects run after browser paint, without blocking it.\n *\n * @param effect Imperative function that can return a cleanup function\n * @param inputs If present, effect will only activate if the values in the list change (using ===).\n */\nexport function useEffect(effect: EffectCallback, inputs?: Inputs): void;\n\ntype CreateHandle = () => object;\n\n/**\n * @param ref The ref that will be mutated\n * @param create The function that will be executed to get the value that will be attached to\n * ref.current\n * @param inputs If present, effect will only activate if the values in the list change (using ===).\n */\nexport function useImperativeHandle<T, R extends T>(\n\tref: Ref<T>,\n\tcreate: () => R,\n\tinputs?: Inputs\n): void;\n\n/**\n * Accepts a function that contains imperative, possibly effectful code.\n * Use this to read layout from the DOM and synchronously re-render.\n * Updates scheduled inside `useLayoutEffect` will be flushed synchronously, after all DOM mutations but before the browser has a chance to paint.\n * Prefer the standard `useEffect` hook when possible to avoid blocking visual updates.\n *\n * @param effect Imperative function that can return a cleanup function\n * @param inputs If present, effect will only activate if the values in the list change (using ===).\n */\nexport function useLayoutEffect(effect: EffectCallback, inputs?: Inputs): void;\n\n/**\n * Returns a memoized version of the callback that only changes if one of the `inputs`\n * has changed (using ===).\n */\nexport function useCallback<T extends Function>(callback: T, inputs: Inputs): T;\n\n/**\n * Pass a factory function and an array of inputs.\n * useMemo will only recompute the memoized value when one of the inputs has changed.\n * This optimization helps to avoid expensive calculations on every render.\n * If no array is provided, a new value will be computed whenever a new function instance is passed as the first argument.\n */\n// for `inputs`, allow undefined, but don't make it optional as that is very likely a mistake\nexport function useMemo<T>(factory: () => T, inputs: Inputs | undefined): T;\n\n/**\n * Returns the current context value, as given by the nearest context provider for the given context.\n * When the provider updates, this Hook will trigger a rerender with the latest context value.\n *\n * @param context The context you want to use\n */\nexport function useContext<T>(context: PreactContext<T>): T;\n\n/**\n * Customize the displayed value in the devtools panel.\n *\n * @param value Custom hook name or object that is passed to formatter\n * @param formatter Formatter to modify value before sending it to the devtools\n */\nexport function useDebugValue<T>(value: T, formatter?: (value: T) => any): void;\n\nexport function useErrorBoundary(\n\tcallback?: (error: any, errorInfo: ErrorInfo) => Promise<void> | void\n): [any, () => void];\n\nexport function useId(): string;\n"
  },
  {
    "path": "hooks/src/index.js",
    "content": "import { options as _options } from 'preact';\nimport { COMPONENT_FORCE } from '../../src/constants';\n\nconst ObjectIs = Object.is;\n\n/** @type {number} */\nlet currentIndex;\n\n/** @type {import('./internal').Component} */\nlet currentComponent;\n\n/** @type {import('./internal').Component} */\nlet previousComponent;\n\n/** @type {number} */\nlet currentHook = 0;\n\n/** @type {Array<import('./internal').Component>} */\nlet afterPaintEffects = [];\n\n// Cast to use internal Options type\nconst options = /** @type {import('./internal').Options} */ (_options);\n\nlet oldBeforeDiff = options._diff;\nlet oldBeforeRender = options._render;\nlet oldAfterDiff = options.diffed;\nlet oldCommit = options._commit;\nlet oldBeforeUnmount = options.unmount;\nlet oldRoot = options._root;\n\n// We take the minimum timeout for requestAnimationFrame to ensure that\n// the callback is invoked after the next frame. 35ms is based on a 30hz\n// refresh rate, which is the minimum rate for a smooth user experience.\nconst RAF_TIMEOUT = 35;\nlet prevRaf;\n\n/** @type {(vnode: import('./internal').VNode) => void} */\noptions._diff = vnode => {\n\tcurrentComponent = null;\n\tif (oldBeforeDiff) oldBeforeDiff(vnode);\n};\n\noptions._root = (vnode, parentDom) => {\n\tif (vnode && parentDom._children && parentDom._children._mask) {\n\t\tvnode._mask = parentDom._children._mask;\n\t}\n\n\tif (oldRoot) oldRoot(vnode, parentDom);\n};\n\n/** @type {(vnode: import('./internal').VNode) => void} */\noptions._render = vnode => {\n\tif (oldBeforeRender) oldBeforeRender(vnode);\n\n\tcurrentComponent = vnode._component;\n\tcurrentIndex = 0;\n\n\tconst hooks = currentComponent.__hooks;\n\tif (hooks) {\n\t\tif (previousComponent === currentComponent) {\n\t\t\thooks._pendingEffects = [];\n\t\t\tcurrentComponent._renderCallbacks = [];\n\t\t\thooks._list.some(hookItem => {\n\t\t\t\tif (hookItem._nextValue) {\n\t\t\t\t\thookItem._value = hookItem._nextValue;\n\t\t\t\t}\n\t\t\t\thookItem._pendingArgs = hookItem._nextValue = undefined;\n\t\t\t});\n\t\t} else {\n\t\t\thooks._pendingEffects.some(invokeCleanup);\n\t\t\thooks._pendingEffects.some(invokeEffect);\n\t\t\thooks._pendingEffects = [];\n\t\t\tcurrentIndex = 0;\n\t\t}\n\t}\n\tpreviousComponent = currentComponent;\n};\n\n/** @type {(vnode: import('./internal').VNode) => void} */\noptions.diffed = vnode => {\n\tif (oldAfterDiff) oldAfterDiff(vnode);\n\n\tconst c = vnode._component;\n\tif (c && c.__hooks) {\n\t\tif (c.__hooks._pendingEffects.length) afterPaint(afterPaintEffects.push(c));\n\t\tc.__hooks._list.some(hookItem => {\n\t\t\tif (hookItem._pendingArgs) {\n\t\t\t\thookItem._args = hookItem._pendingArgs;\n\t\t\t}\n\t\t\thookItem._pendingArgs = undefined;\n\t\t});\n\t}\n\tpreviousComponent = currentComponent = null;\n};\n\n// TODO: Improve typing of commitQueue parameter\n/** @type {(vnode: import('./internal').VNode, commitQueue: any) => void} */\noptions._commit = (vnode, commitQueue) => {\n\tcommitQueue.some(component => {\n\t\ttry {\n\t\t\tcomponent._renderCallbacks.some(invokeCleanup);\n\t\t\tcomponent._renderCallbacks = component._renderCallbacks.filter(cb =>\n\t\t\t\tcb._value ? invokeEffect(cb) : true\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tcommitQueue.some(c => {\n\t\t\t\tif (c._renderCallbacks) c._renderCallbacks = [];\n\t\t\t});\n\t\t\tcommitQueue = [];\n\t\t\toptions._catchError(e, component._vnode);\n\t\t}\n\t});\n\n\tif (oldCommit) oldCommit(vnode, commitQueue);\n};\n\n/** @type {(vnode: import('./internal').VNode) => void} */\noptions.unmount = vnode => {\n\tif (oldBeforeUnmount) oldBeforeUnmount(vnode);\n\n\tconst c = vnode._component;\n\tif (c && c.__hooks) {\n\t\tlet hasErrored;\n\t\tc.__hooks._list.some(s => {\n\t\t\ttry {\n\t\t\t\tinvokeCleanup(s);\n\t\t\t} catch (e) {\n\t\t\t\thasErrored = e;\n\t\t\t}\n\t\t});\n\t\tc.__hooks = undefined;\n\t\tif (hasErrored) options._catchError(hasErrored, c._vnode);\n\t}\n};\n\n/**\n * Get a hook's state from the currentComponent\n * @param {number} index The index of the hook to get\n * @param {number} type The index of the hook to get\n * @returns {any}\n */\nfunction getHookState(index, type) {\n\tif (options._hook) {\n\t\toptions._hook(currentComponent, index, currentHook || type);\n\t}\n\tcurrentHook = 0;\n\n\t// Largely inspired by:\n\t// * https://github.com/michael-klein/funcy.js/blob/f6be73468e6ec46b0ff5aa3cc4c9baf72a29025a/src/hooks/core_hooks.mjs\n\t// * https://github.com/michael-klein/funcy.js/blob/650beaa58c43c33a74820a3c98b3c7079cf2e333/src/renderer.mjs\n\t// Other implementations to look at:\n\t// * https://codesandbox.io/s/mnox05qp8\n\tconst hooks =\n\t\tcurrentComponent.__hooks ||\n\t\t(currentComponent.__hooks = {\n\t\t\t_list: [],\n\t\t\t_pendingEffects: []\n\t\t});\n\n\tif (index >= hooks._list.length) {\n\t\thooks._list.push({});\n\t}\n\n\treturn hooks._list[index];\n}\n\n/**\n * @template {unknown} S\n * @param {import('./index').Dispatch<import('./index').StateUpdater<S>>} [initialState]\n * @returns {[S, (state: S) => void]}\n */\nexport function useState(initialState) {\n\tcurrentHook = 1;\n\treturn useReducer(invokeOrReturn, initialState);\n}\n\n/**\n * @template {unknown} S\n * @template {unknown} A\n * @param {import('./index').Reducer<S, A>} reducer\n * @param {import('./index').Dispatch<import('./index').StateUpdater<S>>} initialState\n * @param {(initialState: any) => void} [init]\n * @returns {[ S, (state: S) => void ]}\n */\nexport function useReducer(reducer, initialState, init) {\n\t/** @type {import('./internal').ReducerHookState} */\n\tconst hookState = getHookState(currentIndex++, 2);\n\thookState._reducer = reducer;\n\tif (!hookState._component) {\n\t\thookState._value = [\n\t\t\t!init ? invokeOrReturn(undefined, initialState) : init(initialState),\n\n\t\t\taction => {\n\t\t\t\tconst currentValue = hookState._nextValue\n\t\t\t\t\t? hookState._nextValue[0]\n\t\t\t\t\t: hookState._value[0];\n\t\t\t\tconst nextValue = hookState._reducer(currentValue, action);\n\n\t\t\t\tif (!ObjectIs(currentValue, nextValue)) {\n\t\t\t\t\thookState._nextValue = [nextValue, hookState._value[1]];\n\t\t\t\t\thookState._component.setState({});\n\t\t\t\t}\n\t\t\t}\n\t\t];\n\n\t\thookState._component = currentComponent;\n\n\t\tif (!currentComponent._hasScuFromHooks) {\n\t\t\tcurrentComponent._hasScuFromHooks = true;\n\t\t\tlet prevScu = currentComponent.shouldComponentUpdate;\n\t\t\tconst prevCWU = currentComponent.componentWillUpdate;\n\n\t\t\t// If we're dealing with a forced update `shouldComponentUpdate` will\n\t\t\t// not be called. But we use that to update the hook values, so we\n\t\t\t// need to call it.\n\t\t\tcurrentComponent.componentWillUpdate = function (p, s, c) {\n\t\t\t\tif (this._bits & COMPONENT_FORCE) {\n\t\t\t\t\tlet tmp = prevScu;\n\t\t\t\t\t// Clear to avoid other sCU hooks from being called\n\t\t\t\t\tprevScu = undefined;\n\t\t\t\t\tupdateHookState(p, s, c);\n\t\t\t\t\tprevScu = tmp;\n\t\t\t\t}\n\n\t\t\t\tif (prevCWU) prevCWU.call(this, p, s, c);\n\t\t\t};\n\n\t\t\t// This SCU has the purpose of bailing out after repeated updates\n\t\t\t// to stateful hooks.\n\t\t\t// we store the next value in _nextValue[0] and keep doing that for all\n\t\t\t// state setters, if we have next states and\n\t\t\t// all next states within a component end up being equal to their original state\n\t\t\t// we are safe to bail out for this specific component.\n\t\t\t/**\n\t\t\t *\n\t\t\t * @type {import('./internal').Component[\"shouldComponentUpdate\"]}\n\t\t\t */\n\t\t\t// @ts-ignore - We don't use TS to downtranspile\n\t\t\t// eslint-disable-next-line no-inner-declarations\n\t\t\tfunction updateHookState(p, s, c) {\n\t\t\t\tif (!hookState._component.__hooks) return true;\n\n\t\t\t\tconst hooksList = hookState._component.__hooks._list;\n\t\t\t\t// We check whether we have components with a nextValue set that\n\t\t\t\t// have values that aren't equal to one another this pushes\n\t\t\t\t// us to update further down the tree\n\t\t\t\tlet shouldUpdate =\n\t\t\t\t\thookState._component.props !== p ||\n\t\t\t\t\thooksList.every(x => !x._nextValue);\n\n\t\t\t\thooksList.some(hookItem => {\n\t\t\t\t\tif (hookItem._nextValue) {\n\t\t\t\t\t\tconst currentValue = hookItem._value[0];\n\t\t\t\t\t\thookItem._value = hookItem._nextValue;\n\t\t\t\t\t\thookItem._nextValue = undefined;\n\t\t\t\t\t\tif (!ObjectIs(currentValue, hookItem._value[0]))\n\t\t\t\t\t\t\tshouldUpdate = true;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\treturn prevScu\n\t\t\t\t\t? prevScu.call(this, p, s, c) || shouldUpdate\n\t\t\t\t\t: shouldUpdate;\n\t\t\t}\n\n\t\t\tcurrentComponent.shouldComponentUpdate = updateHookState;\n\t\t}\n\t}\n\n\treturn hookState._value;\n}\n\n/**\n * @param {import('./internal').Effect} callback\n * @param {unknown[]} args\n * @returns {void}\n */\nexport function useEffect(callback, args) {\n\t/** @type {import('./internal').EffectHookState} */\n\tconst state = getHookState(currentIndex++, 3);\n\tif (!options._skipEffects && argsChanged(state._args, args)) {\n\t\tstate._value = callback;\n\t\tstate._pendingArgs = args;\n\n\t\tcurrentComponent.__hooks._pendingEffects.push(state);\n\t}\n}\n\n/**\n * @param {import('./internal').Effect} callback\n * @param {unknown[]} args\n * @returns {void}\n */\nexport function useLayoutEffect(callback, args) {\n\t/** @type {import('./internal').EffectHookState} */\n\tconst state = getHookState(currentIndex++, 4);\n\tif (!options._skipEffects && argsChanged(state._args, args)) {\n\t\tstate._value = callback;\n\t\tstate._pendingArgs = args;\n\n\t\tcurrentComponent._renderCallbacks.push(state);\n\t}\n}\n\n/** @type {(initialValue: unknown) => unknown} */\nexport function useRef(initialValue) {\n\tcurrentHook = 5;\n\treturn useMemo(() => ({ current: initialValue }), []);\n}\n\n/**\n * @param {object} ref\n * @param {() => object} createHandle\n * @param {unknown[]} args\n * @returns {void}\n */\nexport function useImperativeHandle(ref, createHandle, args) {\n\tcurrentHook = 6;\n\tuseLayoutEffect(\n\t\t() => {\n\t\t\tif (typeof ref == 'function') {\n\t\t\t\tconst result = ref(createHandle());\n\t\t\t\treturn () => {\n\t\t\t\t\tref(null);\n\t\t\t\t\tif (result && typeof result == 'function') result();\n\t\t\t\t};\n\t\t\t} else if (ref) {\n\t\t\t\tref.current = createHandle();\n\t\t\t\treturn () => (ref.current = null);\n\t\t\t}\n\t\t},\n\t\targs == null ? args : args.concat(ref)\n\t);\n}\n\n/**\n * @template {unknown} T\n * @param {() => T} factory\n * @param {unknown[]} args\n * @returns {T}\n */\nexport function useMemo(factory, args) {\n\t/** @type {import('./internal').MemoHookState<T>} */\n\tconst state = getHookState(currentIndex++, 7);\n\tif (argsChanged(state._args, args)) {\n\t\tstate._value = factory();\n\t\tstate._args = args;\n\t\tstate._factory = factory;\n\t}\n\n\treturn state._value;\n}\n\n/**\n * @param {() => void} callback\n * @param {unknown[]} args\n * @returns {() => void}\n */\nexport function useCallback(callback, args) {\n\tcurrentHook = 8;\n\treturn useMemo(() => callback, args);\n}\n\n/**\n * @param {import('./internal').PreactContext} context\n */\nexport function useContext(context) {\n\tconst provider = currentComponent.context[context._id];\n\t// We could skip this call here, but than we'd not call\n\t// `options._hook`. We need to do that in order to make\n\t// the devtools aware of this hook.\n\t/** @type {import('./internal').ContextHookState} */\n\tconst state = getHookState(currentIndex++, 9);\n\t// The devtools needs access to the context object to\n\t// be able to pull of the default value when no provider\n\t// is present in the tree.\n\tstate._context = context;\n\tif (!provider) return context._defaultValue;\n\t// This is probably not safe to convert to \"!\"\n\tif (state._value == null) {\n\t\tstate._value = true;\n\t\tprovider.sub(currentComponent);\n\t}\n\treturn provider.props.value;\n}\n\n/**\n * Display a custom label for a custom hook for the devtools panel\n * @type {<T>(value: T, cb?: (value: T) => string | number) => void}\n */\nexport function useDebugValue(value, formatter) {\n\tif (options.useDebugValue) {\n\t\toptions.useDebugValue(\n\t\t\tformatter ? formatter(value) : /** @type {any}*/ (value)\n\t\t);\n\t}\n}\n\n/**\n * @param {(error: unknown, errorInfo: import('preact').ErrorInfo) => void} cb\n * @returns {[unknown, () => void]}\n */\nexport function useErrorBoundary(cb) {\n\t/** @type {import('./internal').ErrorBoundaryHookState} */\n\tconst state = getHookState(currentIndex++, 10);\n\tconst errState = useState();\n\tstate._value = cb;\n\tif (!currentComponent.componentDidCatch) {\n\t\tcurrentComponent.componentDidCatch = (err, errorInfo) => {\n\t\t\tif (state._value) state._value(err, errorInfo);\n\t\t\terrState[1](err);\n\t\t};\n\t}\n\treturn [\n\t\terrState[0],\n\t\t() => {\n\t\t\terrState[1](undefined);\n\t\t}\n\t];\n}\n\n/** @type {() => string} */\nexport function useId() {\n\t/** @type {import('./internal').IdHookState} */\n\tconst state = getHookState(currentIndex++, 11);\n\tif (!state._value) {\n\t\t// Grab either the root node or the nearest async boundary node.\n\t\t/** @type {import('./internal').VNode} */\n\t\tlet root = currentComponent._vnode;\n\t\twhile (root !== null && !root._mask && root._parent !== null) {\n\t\t\troot = root._parent;\n\t\t}\n\n\t\tlet mask = root._mask || (root._mask = [0, 0]);\n\t\tstate._value = 'P' + mask[0] + '-' + mask[1]++;\n\t}\n\n\treturn state._value;\n}\n\n/**\n * After paint effects consumer.\n */\nfunction flushAfterPaintEffects() {\n\tlet component;\n\twhile ((component = afterPaintEffects.shift())) {\n\t\tconst hooks = component.__hooks;\n\t\tif (!component._parentDom || !hooks) continue;\n\t\ttry {\n\t\t\thooks._pendingEffects.some(invokeCleanup);\n\t\t\thooks._pendingEffects.some(invokeEffect);\n\t\t\thooks._pendingEffects = [];\n\t\t} catch (e) {\n\t\t\thooks._pendingEffects = [];\n\t\t\toptions._catchError(e, component._vnode);\n\t\t}\n\t}\n}\n\nlet HAS_RAF = typeof requestAnimationFrame == 'function';\n\n/**\n * Schedule a callback to be invoked after the browser has a chance to paint a new frame.\n * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after\n * the next browser frame.\n *\n * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked\n * even if RAF doesn't fire (for example if the browser tab is not visible)\n *\n * @param {() => void} callback\n */\nfunction afterNextFrame(callback) {\n\tconst done = () => {\n\t\tclearTimeout(timeout);\n\t\tif (HAS_RAF) cancelAnimationFrame(raf);\n\t\tsetTimeout(callback);\n\t};\n\tconst timeout = setTimeout(done, RAF_TIMEOUT);\n\n\tlet raf;\n\tif (HAS_RAF) {\n\t\traf = requestAnimationFrame(done);\n\t}\n}\n\n// Note: if someone used options.debounceRendering = requestAnimationFrame,\n// then effects will ALWAYS run on the NEXT frame instead of the current one, incurring a ~16ms delay.\n// Perhaps this is not such a big deal.\n/**\n * Schedule afterPaintEffects flush after the browser paints\n * @param {number} newQueueLength\n * @returns {void}\n */\nfunction afterPaint(newQueueLength) {\n\tif (newQueueLength === 1 || prevRaf !== options.requestAnimationFrame) {\n\t\tprevRaf = options.requestAnimationFrame;\n\t\t(prevRaf || afterNextFrame)(flushAfterPaintEffects);\n\t}\n}\n\n/**\n * @param {import('./internal').HookState} hook\n * @returns {void}\n */\nfunction invokeCleanup(hook) {\n\t// A hook cleanup can introduce a call to render which creates a new root, this will call options.vnode\n\t// and move the currentComponent away.\n\tconst comp = currentComponent;\n\tlet cleanup = hook._cleanup;\n\tif (typeof cleanup == 'function') {\n\t\thook._cleanup = undefined;\n\t\tcleanup();\n\t}\n\n\tcurrentComponent = comp;\n}\n\n/**\n * Invoke a Hook's effect\n * @param {import('./internal').EffectHookState} hook\n * @returns {void}\n */\nfunction invokeEffect(hook) {\n\t// A hook call can introduce a call to render which creates a new root, this will call options.vnode\n\t// and move the currentComponent away.\n\tconst comp = currentComponent;\n\thook._cleanup = hook._value();\n\tcurrentComponent = comp;\n}\n\n/**\n * @param {unknown[]} oldArgs\n * @param {unknown[]} newArgs\n * @returns {boolean}\n */\nfunction argsChanged(oldArgs, newArgs) {\n\treturn (\n\t\t!oldArgs ||\n\t\toldArgs.length !== newArgs.length ||\n\t\tnewArgs.some((arg, index) => !ObjectIs(arg, oldArgs[index]))\n\t);\n}\n\n/**\n * @template Arg\n * @param {Arg} arg\n * @param {(arg: Arg) => any} f\n * @returns {any}\n */\nfunction invokeOrReturn(arg, f) {\n\treturn typeof f == 'function' ? f(arg) : f;\n}\n"
  },
  {
    "path": "hooks/src/internal.d.ts",
    "content": "import {\n\tOptions as PreactOptions,\n\tComponent as PreactComponent,\n\tVNode as PreactVNode,\n\tPreactContext,\n\tHookType,\n\tErrorInfo\n} from '../../src/internal';\nimport { Reducer, StateUpdater } from '.';\n\nexport { PreactContext };\n\nexport interface Options extends PreactOptions {\n\t/** Attach a hook that is invoked before a vnode is diffed. */\n\t_diff?(vnode: VNode): void;\n\t/** Attach a hook that is invoked before a vnode has rendered. */\n\t_render?(vnode: VNode): void;\n\t/** Attach a hook that is invoked after a vnode has rendered. */\n\tdiffed?(vnode: VNode): void;\n\t/** Attach a hook that is invoked after a tree was mounted or was updated. */\n\t_commit?(vnode: VNode, commitQueue: Component[]): void;\n\t_unmount?(vnode: VNode): void;\n\t/** Attach a hook that is invoked before a hook's state is queried. */\n\t_hook?(component: Component, index: number, type: HookType): void;\n}\n\n// Hook tracking\n\nexport interface ComponentHooks {\n\t/** The list of hooks a component uses */\n\t_list: HookState[];\n\t/** List of Effects to be invoked after the next frame is rendered */\n\t_pendingEffects: EffectHookState[];\n}\n\nexport interface Component\n\textends Omit<PreactComponent<any, any>, '_renderCallbacks'> {\n\t__hooks?: ComponentHooks;\n\t// Extend to include HookStates\n\t_renderCallbacks?: Array<HookState | (() => void)>;\n\t_hasScuFromHooks?: boolean;\n}\n\nexport interface VNode extends Omit<PreactVNode, '_component'> {\n\t_mask?: [number, number];\n\t_component?: Component; // Override with our specific Component type\n}\n\nexport type HookState =\n\t| EffectHookState\n\t| MemoHookState\n\t| ReducerHookState\n\t| ContextHookState\n\t| ErrorBoundaryHookState\n\t| IdHookState;\n\ninterface BaseHookState {\n\t_value?: unknown;\n\t_nextValue?: unknown;\n\t_pendingValue?: unknown;\n\t_args?: unknown;\n\t_pendingArgs?: unknown;\n\t_component?: unknown;\n\t_cleanup?: unknown;\n}\n\nexport type Effect = () => void | Cleanup;\nexport type Cleanup = () => void;\n\nexport interface EffectHookState extends BaseHookState {\n\t_value?: Effect;\n\t_args?: unknown[];\n\t_pendingArgs?: unknown[];\n\t_cleanup?: Cleanup | void;\n}\n\nexport interface MemoHookState<T = unknown> extends BaseHookState {\n\t_value?: T;\n\t_pendingValue?: T;\n\t_args?: unknown[];\n\t_pendingArgs?: unknown[];\n\t_factory?: () => T;\n}\n\nexport interface ReducerHookState<S = unknown, A = unknown>\n\textends BaseHookState {\n\t_nextValue?: [S, StateUpdater<S>];\n\t_value?: [S, StateUpdater<S>];\n\t_component?: Component;\n\t_reducer?: Reducer<S, A>;\n}\n\nexport interface ContextHookState extends BaseHookState {\n\t/** Whether this hooks as subscribed to updates yet */\n\t_value?: boolean;\n\t_context?: PreactContext;\n}\n\nexport interface ErrorBoundaryHookState extends BaseHookState {\n\t_value?: (error: unknown, errorInfo: ErrorInfo) => void;\n}\n\nexport interface IdHookState extends BaseHookState {\n\t_value?: string;\n}\n"
  },
  {
    "path": "hooks/test/_util/useEffectUtil.js",
    "content": "export function scheduleEffectAssert(assertFn) {\n\treturn new Promise(resolve => {\n\t\trequestAnimationFrame(() =>\n\t\t\tsetTimeout(() => {\n\t\t\t\tassertFn();\n\t\t\t\tresolve();\n\t\t\t}, 0)\n\t\t);\n\t});\n}\n"
  },
  {
    "path": "hooks/test/browser/combinations.test.jsx",
    "content": "import { setupRerender, act } from 'preact/test-utils';\nimport { createElement, render, Component, createContext } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport {\n\tuseState,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseMemo,\n\tuseContext\n} from 'preact/hooks';\nimport { scheduleEffectAssert } from '../_util/useEffectUtil';\nimport { vi } from 'vitest';\n\ndescribe('combinations', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('can mix useState hooks', () => {\n\t\tconst states = {};\n\t\tconst setStates = {};\n\n\t\tfunction Parent() {\n\t\t\tconst [state1, setState1] = useState(1);\n\t\t\tconst [state2, setState2] = useState(2);\n\n\t\t\tObject.assign(states, { state1, state2 });\n\t\t\tObject.assign(setStates, { setState1, setState2 });\n\n\t\t\treturn <Child />;\n\t\t}\n\n\t\tfunction Child() {\n\t\t\tconst [state3, setState3] = useState(3);\n\t\t\tconst [state4, setState4] = useState(4);\n\n\t\t\tObject.assign(states, { state3, state4 });\n\t\t\tObject.assign(setStates, { setState3, setState4 });\n\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Parent />, scratch);\n\t\texpect(states).to.deep.equal({\n\t\t\tstate1: 1,\n\t\t\tstate2: 2,\n\t\t\tstate3: 3,\n\t\t\tstate4: 4\n\t\t});\n\n\t\tsetStates.setState2(n => n * 10);\n\t\tsetStates.setState3(n => n * 10);\n\t\trerender();\n\t\texpect(states).to.deep.equal({\n\t\t\tstate1: 1,\n\t\t\tstate2: 20,\n\t\t\tstate3: 30,\n\t\t\tstate4: 4\n\t\t});\n\t});\n\n\tit('can rerender asynchronously from within an effect', () => {\n\t\tconst didRender = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tconst [counter, setCounter] = useState(0);\n\n\t\t\tuseEffect(() => {\n\t\t\t\tif (counter === 0) setCounter(1);\n\t\t\t});\n\n\t\t\tdidRender(counter);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\treturn scheduleEffectAssert(() => {\n\t\t\trerender();\n\t\t\texpect(didRender).toHaveBeenCalledTimes(2);\n\t\t\texpect(didRender).toHaveBeenCalledWith(1);\n\t\t});\n\t});\n\n\tit('can rerender synchronously from within a layout effect', () => {\n\t\tconst didRender = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tconst [counter, setCounter] = useState(0);\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tif (counter === 0) setCounter(1);\n\t\t\t});\n\n\t\t\tdidRender(counter);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trerender();\n\n\t\texpect(didRender).toHaveBeenCalledTimes(2);\n\t\texpect(didRender).toHaveBeenCalledWith(1);\n\t});\n\n\tit('can access refs from within a layout effect callback', () => {\n\t\tlet refAtLayoutTime;\n\n\t\tfunction Comp() {\n\t\t\tconst input = useRef();\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\trefAtLayoutTime = input.current;\n\t\t\t});\n\n\t\t\treturn <input ref={input} value=\"hello\" />;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\texpect(refAtLayoutTime.value).to.equal('hello');\n\t});\n\n\tit('can use multiple useState and useReducer hooks', () => {\n\t\tlet states = [];\n\t\tlet dispatchState4;\n\n\t\tfunction reducer1(state, action) {\n\t\t\tswitch (action.type) {\n\t\t\t\tcase 'increment':\n\t\t\t\t\treturn state + action.count;\n\t\t\t}\n\t\t}\n\n\t\tfunction reducer2(state, action) {\n\t\t\tswitch (action.type) {\n\t\t\t\tcase 'increment':\n\t\t\t\t\treturn state + action.count * 2;\n\t\t\t}\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst [state1] = useState(0);\n\t\t\tconst [state2] = useReducer(reducer1, 10);\n\t\t\tconst [state3] = useState(1);\n\t\t\tconst [state4, dispatch] = useReducer(reducer2, 20);\n\n\t\t\tdispatchState4 = dispatch;\n\t\t\tstates.push(state1, state2, state3, state4);\n\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\texpect(states).to.deep.equal([0, 10, 1, 20]);\n\n\t\tstates = [];\n\n\t\tdispatchState4({ type: 'increment', count: 10 });\n\t\trerender();\n\n\t\texpect(states).to.deep.equal([0, 10, 1, 40]);\n\t});\n\n\tit('ensures useEffect always schedule after the next paint following a redraw effect, when using the default debounce strategy', () => {\n\t\tlet effectCount = 0;\n\n\t\tfunction Comp() {\n\t\t\tconst [counter, setCounter] = useState(0);\n\n\t\t\tuseEffect(() => {\n\t\t\t\tif (counter === 0) setCounter(1);\n\t\t\t\teffectCount++;\n\t\t\t});\n\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\treturn scheduleEffectAssert(() => {\n\t\t\texpect(effectCount).to.equal(1);\n\t\t});\n\t});\n\n\tit('should not reuse functional components with hooks', () => {\n\t\tlet updater = { first: undefined, second: undefined };\n\t\tfunction Foo(props) {\n\t\t\tlet [v, setter] = useState(0);\n\t\t\tupdater[props.id] = () => setter(++v);\n\t\t\treturn <div>{v}</div>;\n\t\t}\n\n\t\tlet updateParent;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: true };\n\t\t\t\tupdateParent = () => this.setState(p => ({ active: !p.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.active && <Foo id=\"first\" />}\n\t\t\t\t\t\t<Foo id=\"second\" />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tact(() => updater.second());\n\t\texpect(scratch.textContent).to.equal('01');\n\n\t\tupdateParent();\n\t\trerender();\n\t\texpect(scratch.textContent).to.equal('1');\n\n\t\tupdateParent();\n\t\trerender();\n\n\t\texpect(scratch.textContent).to.equal('01');\n\t});\n\n\tit('should have a right call order with correct dom ref', () => {\n\t\tlet i = 0,\n\t\t\tset;\n\t\tconst calls = [];\n\n\t\tfunction Inner() {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push('layout inner call ' + scratch.innerHTML);\n\t\t\t\treturn () => calls.push('layout inner dispose ' + scratch.innerHTML);\n\t\t\t});\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('effect inner call ' + scratch.innerHTML);\n\t\t\t\treturn () => calls.push('effect inner dispose ' + scratch.innerHTML);\n\t\t\t});\n\t\t\treturn <span>hello {i}</span>;\n\t\t}\n\n\t\tfunction Outer() {\n\t\t\ti++;\n\t\t\tconst [state, setState] = useState(false);\n\t\t\tset = () => setState(!state);\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push('layout outer call ' + scratch.innerHTML);\n\t\t\t\treturn () => calls.push('layout outer dispose ' + scratch.innerHTML);\n\t\t\t});\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('effect outer call ' + scratch.innerHTML);\n\t\t\t\treturn () => calls.push('effect outer dispose ' + scratch.innerHTML);\n\t\t\t});\n\t\t\treturn <Inner />;\n\t\t}\n\n\t\tact(() => render(<Outer />, scratch));\n\t\texpect(calls).to.deep.equal([\n\t\t\t'layout inner call <span>hello 1</span>',\n\t\t\t'layout outer call <span>hello 1</span>',\n\t\t\t'effect inner call <span>hello 1</span>',\n\t\t\t'effect outer call <span>hello 1</span>'\n\t\t]);\n\n\t\t// NOTE: this order is (at the time of writing) intentionally different from\n\t\t// React. React calls all disposes across all components, and then invokes all\n\t\t// effects across all components. We call disposes and effects in order of components:\n\t\t// for each component, call its disposes and then its effects. If presented with a\n\t\t// compelling use case to support inter-component dispose dependencies, then rewrite this\n\t\t// test to test React's order. In other words, if there is a use case to support calling\n\t\t// all disposes across components then re-order the lines below to demonstrate the desired behavior.\n\n\t\tact(() => set());\n\t\texpect(calls).to.deep.equal([\n\t\t\t'layout inner call <span>hello 1</span>',\n\t\t\t'layout outer call <span>hello 1</span>',\n\t\t\t'effect inner call <span>hello 1</span>',\n\t\t\t'effect outer call <span>hello 1</span>',\n\t\t\t'layout inner dispose <span>hello 2</span>',\n\t\t\t'layout inner call <span>hello 2</span>',\n\t\t\t'layout outer dispose <span>hello 2</span>',\n\t\t\t'layout outer call <span>hello 2</span>',\n\t\t\t'effect inner dispose <span>hello 2</span>',\n\t\t\t'effect inner call <span>hello 2</span>',\n\t\t\t'effect outer dispose <span>hello 2</span>',\n\t\t\t'effect outer call <span>hello 2</span>'\n\t\t]);\n\t});\n\n\t// TODO: I actually think this is an acceptable failure, because we update child first and then parent\n\t// the effects are out of order\n\tit.skip('should run effects child-first even for children separated by memoization', () => {\n\t\tlet ops = [];\n\n\t\t/** @type {() => void} */\n\t\tlet updateChild;\n\t\t/** @type {() => void} */\n\t\tlet updateParent;\n\n\t\tfunction Child() {\n\t\t\tconst [, setCount] = useState(0);\n\t\t\tupdateChild = () => setCount(c => c + 1);\n\t\t\tuseEffect(() => {\n\t\t\t\tops.push('child effect');\n\t\t\t});\n\t\t\treturn <div>Child</div>;\n\t\t}\n\n\t\tfunction Parent() {\n\t\t\tconst [, setCount] = useState(0);\n\t\t\tupdateParent = () => setCount(c => c + 1);\n\t\t\tconst memoedChild = useMemo(() => <Child />, []);\n\t\t\tuseEffect(() => {\n\t\t\t\tops.push('parent effect');\n\t\t\t});\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<div>Parent</div>\n\t\t\t\t\t{memoedChild}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tact(() => render(<Parent />, scratch));\n\t\texpect(ops).to.deep.equal(['child effect', 'parent effect']);\n\n\t\tops = [];\n\t\tupdateChild();\n\t\tupdateParent();\n\t\tact(() => rerender());\n\n\t\texpect(ops).to.deep.equal(['child effect', 'parent effect']);\n\t});\n\n\tit('should not block hook updates when context updates are enqueued', () => {\n\t\tconst Ctx = createContext({\n\t\t\tvalue: 0,\n\t\t\tsetValue: /** @type {*} */ () => {}\n\t\t});\n\n\t\tlet triggerSubmit = () => {};\n\t\tfunction Child() {\n\t\t\tconst ctx = useContext(Ctx);\n\t\t\tconst [shouldSubmit, setShouldSubmit] = useState(false);\n\t\t\ttriggerSubmit = () => setShouldSubmit(true);\n\n\t\t\tuseEffect(() => {\n\t\t\t\tif (shouldSubmit) {\n\t\t\t\t\t// Update parent state and child state at the same time\n\t\t\t\t\tctx.setValue(v => v + 1);\n\t\t\t\t\tsetShouldSubmit(false);\n\t\t\t\t}\n\t\t\t}, [shouldSubmit]);\n\n\t\t\treturn <p>{ctx.value}</p>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\tconst [value, setValue] = useState(0);\n\t\t\tconst ctx = useMemo(() => {\n\t\t\t\treturn { value, setValue };\n\t\t\t}, [value]);\n\t\t\treturn (\n\t\t\t\t<Ctx.Provider value={ctx}>\n\t\t\t\t\t<Child />\n\t\t\t\t</Ctx.Provider>\n\t\t\t);\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(scratch.textContent).to.equal('0');\n\n\t\tact(() => {\n\t\t\ttriggerSubmit();\n\t\t});\n\t\texpect(scratch.textContent).to.equal('1');\n\n\t\t// This is where the update wasn't applied\n\t\tact(() => {\n\t\t\ttriggerSubmit();\n\t\t});\n\t\texpect(scratch.textContent).to.equal('2');\n\t});\n\n\tit('parent and child refs should be set before all effects', () => {\n\t\tconst anchorId = 'anchor';\n\t\tconst tooltipId = 'tooltip';\n\t\tconst effectLog = [];\n\n\t\tlet useRef2 = vi.fn(init => {\n\t\t\tconst realRef = useRef(init);\n\t\t\tconst ref = useRef(init);\n\t\t\tObject.defineProperty(ref, 'current', {\n\t\t\t\tget: () => realRef.current,\n\t\t\t\tset: value => {\n\t\t\t\t\trealRef.current = value;\n\t\t\t\t\teffectLog.push('set ref ' + value?.tagName);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn ref;\n\t\t});\n\n\t\tfunction Tooltip({ anchorRef, children }) {\n\t\t\t// For example, used to manually position the tooltip\n\t\t\tconst tooltipRef = useRef2(null);\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\texpect(anchorRef.current?.id).to.equal(anchorId);\n\t\t\t\texpect(tooltipRef.current?.id).to.equal(tooltipId);\n\t\t\t\teffectLog.push('tooltip layout effect');\n\t\t\t}, [anchorRef, tooltipRef]);\n\t\t\tuseEffect(() => {\n\t\t\t\texpect(anchorRef.current?.id).to.equal(anchorId);\n\t\t\t\texpect(tooltipRef.current?.id).to.equal(tooltipId);\n\t\t\t\teffectLog.push('tooltip effect');\n\t\t\t}, [anchorRef, tooltipRef]);\n\n\t\t\treturn (\n\t\t\t\t<div class=\"tooltip-wrapper\">\n\t\t\t\t\t<div id={tooltipId} ref={tooltipRef}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction App() {\n\t\t\t// For example, used to define what element to anchor the tooltip to\n\t\t\tconst anchorRef = useRef2(null);\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\texpect(anchorRef.current?.id).to.equal(anchorId);\n\t\t\t\teffectLog.push('anchor layout effect');\n\t\t\t}, [anchorRef]);\n\t\t\tuseEffect(() => {\n\t\t\t\texpect(anchorRef.current?.id).to.equal(anchorId);\n\t\t\t\teffectLog.push('anchor effect');\n\t\t\t}, [anchorRef]);\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p id={anchorId} ref={anchorRef}>\n\t\t\t\t\t\tMore info\n\t\t\t\t\t</p>\n\t\t\t\t\t<Tooltip anchorRef={anchorRef}>a tooltip</Tooltip>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(effectLog).to.deep.equal([\n\t\t\t'set ref P',\n\t\t\t'set ref DIV',\n\t\t\t'tooltip layout effect',\n\t\t\t'anchor layout effect',\n\t\t\t'tooltip effect',\n\t\t\t'anchor effect'\n\t\t]);\n\t});\n\n\tit('should not loop infinitely', () => {\n\t\tconst actions = [];\n\t\tlet toggle;\n\t\tfunction App() {\n\t\t\tconst [value, setValue] = useState(false);\n\n\t\t\tconst data = useMemo(() => {\n\t\t\t\tactions.push('memo');\n\t\t\t\treturn {};\n\t\t\t}, [value]);\n\n\t\t\tconst [prevData, setPreviousData] = useState(data);\n\t\t\tif (prevData !== data) {\n\t\t\t\tsetPreviousData(data);\n\t\t\t}\n\n\t\t\tactions.push('render');\n\t\t\ttoggle = () => setValue(!value);\n\t\t\treturn <div>Value: {JSON.stringify(value)}</div>;\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(actions).to.deep.equal(['memo', 'render']);\n\t\texpect(scratch.innerHTML).to.deep.equal('<div>Value: false</div>');\n\n\t\tact(() => {\n\t\t\ttoggle();\n\t\t});\n\t\texpect(actions).to.deep.equal([\n\t\t\t'memo',\n\t\t\t'render',\n\t\t\t'memo',\n\t\t\t'render',\n\t\t\t'render'\n\t\t]);\n\t\texpect(scratch.innerHTML).to.deep.equal('<div>Value: true</div>');\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/componentDidCatch.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport { act } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useEffect } from 'preact/hooks';\n\ndescribe('errorInfo', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should pass errorInfo on hook unmount error', () => {\n\t\tlet info;\n\t\tlet update;\n\t\tclass Receiver extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { error: null, i: 0 };\n\t\t\t\tupdate = this.setState.bind(this);\n\t\t\t}\n\t\t\tcomponentDidCatch(error, errorInfo) {\n\t\t\t\tinfo = errorInfo;\n\t\t\t\tthis.setState({ error });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tif (this.state.error) return <div />;\n\t\t\t\tif (this.state.i === 0) return <ThrowErr />;\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tfunction ThrowErr() {\n\t\t\tuseEffect(() => {\n\t\t\t\treturn () => {\n\t\t\t\t\tthrow new Error('fail');\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\treturn <h1 />;\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<Receiver />, scratch);\n\t\t});\n\n\t\tact(() => {\n\t\t\tupdate({ i: 1 });\n\t\t});\n\n\t\texpect(info).to.deep.equal({});\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/errorBoundary.test.jsx",
    "content": "import { Fragment, createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useErrorBoundary, useLayoutEffect, useState } from 'preact/hooks';\nimport { setupRerender } from 'preact/test-utils';\nimport { vi } from 'vitest';\n\ndescribe('errorBoundary', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch, rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('catches errors', () => {\n\t\tlet resetErr,\n\t\t\tsuccess = false;\n\t\tconst Throws = () => {\n\t\t\tthrow new Error('test');\n\t\t};\n\n\t\tconst App = props => {\n\t\t\tconst [err, reset] = useErrorBoundary();\n\t\t\tresetErr = reset;\n\t\t\treturn err ? <p>Error</p> : success ? <p>Success</p> : <Throws />;\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\n\t\tsuccess = true;\n\t\tresetErr();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Success</p>');\n\t});\n\n\tit('calls the errorBoundary callback', () => {\n\t\tconst spy = vi.fn();\n\t\tconst error = new Error('test');\n\t\tconst Throws = () => {\n\t\t\tthrow error;\n\t\t};\n\n\t\tconst App = props => {\n\t\t\tconst [err] = useErrorBoundary(spy);\n\t\t\treturn err ? <p>Error</p> : <Throws />;\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith(error, {});\n\t});\n\n\tit('returns error', () => {\n\t\tconst error = new Error('test');\n\t\tconst Throws = () => {\n\t\t\tthrow error;\n\t\t};\n\n\t\tlet returned;\n\t\tconst App = () => {\n\t\t\tconst [err] = useErrorBoundary();\n\t\t\treturned = err;\n\t\t\treturn err ? <p>Error</p> : <Throws />;\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\trerender();\n\t\texpect(returned).to.equal(error);\n\t});\n\n\tit('does not leave a stale closure', () => {\n\t\tconst spy = vi.fn(),\n\t\t\tspy2 = vi.fn();\n\t\tlet resetErr;\n\t\tconst error = new Error('test');\n\t\tconst Throws = () => {\n\t\t\tthrow error;\n\t\t};\n\n\t\tconst App = props => {\n\t\t\tconst [err, reset] = useErrorBoundary(props.onError);\n\t\t\tresetErr = reset;\n\t\t\treturn err ? <p>Error</p> : <Throws />;\n\t\t};\n\n\t\trender(<App onError={spy} />, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith(error, {});\n\n\t\tresetErr();\n\t\trender(<App onError={spy2} />, scratch);\n\t\trerender();\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy2).toHaveBeenCalledOnce();\n\t\texpect(spy2).toHaveBeenCalledWith(error, {});\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t});\n\n\tit('does not invoke old effects when a cleanup callback throws an error and is handled', () => {\n\t\tlet throwErr = false;\n\t\tlet thrower = vi.fn(() => {\n\t\t\tif (throwErr) {\n\t\t\t\tthrow new Error('test');\n\t\t\t}\n\t\t});\n\t\tlet badEffect = vi.fn(() => thrower);\n\t\tlet goodEffect = vi.fn();\n\n\t\tfunction EffectThrowsError() {\n\t\t\tuseLayoutEffect(badEffect);\n\t\t\treturn <span>Test</span>;\n\t\t}\n\n\t\tfunction Child({ children }) {\n\t\t\tuseLayoutEffect(goodEffect);\n\t\t\treturn children;\n\t\t}\n\n\t\tfunction App() {\n\t\t\tconst [err] = useErrorBoundary();\n\t\t\treturn err\n\t\t\t\t? <p>Error</p>\n\t\t\t\t: <Child>\n\t\t\t\t\t\t<EffectThrowsError />\n\t\t\t\t\t</Child>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<span>Test</span>');\n\t\texpect(badEffect).toHaveBeenCalledOnce();\n\t\texpect(goodEffect).toHaveBeenCalledOnce();\n\n\t\tthrowErr = true;\n\t\trender(<App />, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t\texpect(thrower).toHaveBeenCalledOnce();\n\t\texpect(badEffect).toHaveBeenCalledOnce();\n\t\texpect(goodEffect).toHaveBeenCalledOnce();\n\t});\n\n\tit('should not duplicate in lists where an item throws and the parent catches and returns a differing type', () => {\n\t\tconst baseTodos = [\n\t\t\t{ text: 'first item', completed: false },\n\t\t\t{ text: 'Test the feature', completed: false },\n\t\t\t{ text: 'another item', completed: false }\n\t\t];\n\n\t\tfunction TodoList() {\n\t\t\tconst [todos, setTodos] = useState([...baseTodos]);\n\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t{todos.map((todo, index) => (\n\t\t\t\t\t\t\t<TodoItem\n\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\ttoggleTodo={() => {\n\t\t\t\t\t\t\t\t\ttodos[index] = {\n\t\t\t\t\t\t\t\t\t\t...todos[index],\n\t\t\t\t\t\t\t\t\t\tcompleted: !todos[index].completed\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\tsetTodos([...todos]);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\ttodo={todo}\n\t\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tfunction TodoItem(props) {\n\t\t\tconst [error] = useErrorBoundary();\n\n\t\t\tif (error) {\n\t\t\t\treturn <li>An error occurred: {error}</li>;\n\t\t\t}\n\n\t\t\treturn <TodoItemInner {...props} />;\n\t\t}\n\t\tlet set;\n\t\tfunction TodoItemInner({ todo, index, toggleTodo }) {\n\t\t\tif (todo.completed) {\n\t\t\t\tthrow new Error('Todo completed!');\n\t\t\t}\n\n\t\t\tif (index === 1) {\n\t\t\t\tset = toggleTodo;\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<li>\n\t\t\t\t\t<label>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tchecked={todo.completed}\n\t\t\t\t\t\t\tonInput={toggleTodo}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{todo.completed ? <s>{todo.text}</s> : todo.text}\n\t\t\t\t\t</label>\n\t\t\t\t</li>\n\t\t\t);\n\t\t}\n\n\t\trender(<TodoList />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><li><label><input type=\"checkbox\">first item</label></li><li><label><input type=\"checkbox\">Test the feature</label></li><li><label><input type=\"checkbox\">another item</label></li></ul>'\n\t\t);\n\n\t\tset();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><li><label><input type=\"checkbox\">first item</label></li><li>An error occurred: </li><li><label><input type=\"checkbox\">another item</label></li></ul>'\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/hooks.options.test.jsx",
    "content": "import {\n\tafterDiffSpy,\n\tbeforeRenderSpy,\n\tunmountSpy,\n\thookSpy\n} from '../../../test/_util/optionSpies';\n\nimport { setupRerender, act } from 'preact/test-utils';\nimport { createElement, render, createContext, options } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport {\n\tuseState,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseCallback,\n\tuseContext,\n\tuseErrorBoundary\n} from 'preact/hooks';\nimport { vi } from 'vitest';\n\ndescribe('hook options', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t/** @type {() => void} */\n\tlet increment;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\n\t\tafterDiffSpy.mockClear();\n\t\tunmountSpy.mockClear();\n\t\tbeforeRenderSpy.mockClear();\n\t\thookSpy.mockClear();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tfunction App() {\n\t\tconst [count, setCount] = useState(0);\n\t\tincrement = () => setCount(prevCount => prevCount + 1);\n\t\treturn <div>{count}</div>;\n\t}\n\n\tit('should call old options on mount', () => {\n\t\trender(<App />, scratch);\n\n\t\texpect(beforeRenderSpy).toHaveBeenCalled();\n\t\texpect(afterDiffSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options.diffed on update', () => {\n\t\trender(<App />, scratch);\n\n\t\tincrement();\n\t\trerender();\n\n\t\texpect(beforeRenderSpy).toHaveBeenCalled();\n\t\texpect(afterDiffSpy).toHaveBeenCalled();\n\t});\n\n\tit('should call old options on unmount', () => {\n\t\trender(<App />, scratch);\n\t\trender(null, scratch);\n\n\t\texpect(unmountSpy).toHaveBeenCalled();\n\t});\n\n\tit('should detect hooks', () => {\n\t\tconst USE_STATE = 1;\n\t\tconst USE_REDUCER = 2;\n\t\tconst USE_EFFECT = 3;\n\t\tconst USE_LAYOUT_EFFECT = 4;\n\t\tconst USE_REF = 5;\n\t\tconst USE_IMPERATIVE_HANDLE = 6;\n\t\tconst USE_MEMO = 7;\n\t\tconst USE_CALLBACK = 8;\n\t\tconst USE_CONTEXT = 9;\n\t\tconst USE_ERROR_BOUNDARY = 10;\n\n\t\tconst Ctx = createContext(null);\n\n\t\tfunction App() {\n\t\t\tuseState(0);\n\t\t\tuseReducer(x => x, 0);\n\t\t\tuseEffect(() => null, []);\n\t\t\tuseLayoutEffect(() => null, []);\n\t\t\tconst ref = useRef(null);\n\t\t\tuseImperativeHandle(ref, () => null);\n\t\t\tuseMemo(() => null, []);\n\t\t\tuseCallback(() => null, []);\n\t\t\tuseContext(Ctx);\n\t\t\tuseErrorBoundary(() => null);\n\t\t}\n\n\t\trender(\n\t\t\t<Ctx.Provider value=\"a\">\n\t\t\t\t<App />\n\t\t\t</Ctx.Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(hookSpy.mock.calls.map(arg => [arg[1], arg[2]])).to.deep.equal([\n\t\t\t[0, USE_STATE],\n\t\t\t[1, USE_REDUCER],\n\t\t\t[2, USE_EFFECT],\n\t\t\t[3, USE_LAYOUT_EFFECT],\n\t\t\t[4, USE_REF],\n\t\t\t[5, USE_IMPERATIVE_HANDLE],\n\t\t\t[6, USE_MEMO],\n\t\t\t[7, USE_CALLBACK],\n\t\t\t[8, USE_CONTEXT],\n\t\t\t[9, USE_ERROR_BOUNDARY],\n\t\t\t// Belongs to useErrorBoundary that uses multiple native hooks.\n\t\t\t[10, USE_STATE]\n\t\t]);\n\t});\n\n\tdescribe('Effects', () => {\n\t\tbeforeEach(() => {\n\t\t\toptions._skipEffects = options.__s = true;\n\t\t});\n\n\t\tafterEach(() => {\n\t\t\toptions._skipEffects = options.__s = false;\n\t\t});\n\n\t\tit('should skip effect hooks', () => {\n\t\t\tconst spy = vi.fn();\n\t\t\tfunction App() {\n\t\t\t\tuseEffect(spy, []);\n\t\t\t\tuseLayoutEffect(spy, []);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tact(() => {\n\t\t\t\trender(<App />, scratch);\n\t\t\t});\n\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useCallback.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useCallback } from 'preact/hooks';\n\ndescribe('useCallback', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('only recomputes the callback when inputs change', () => {\n\t\tconst callbacks = [];\n\n\t\tfunction Comp({ a, b }) {\n\t\t\tconst cb = useCallback(() => a + b, [a, b]);\n\t\t\tcallbacks.push(cb);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp a={1} b={1} />, scratch);\n\t\trender(<Comp a={1} b={1} />, scratch);\n\n\t\texpect(callbacks[0]).to.equal(callbacks[1]);\n\t\texpect(callbacks[0]()).to.equal(2);\n\n\t\trender(<Comp a={1} b={2} />, scratch);\n\t\trender(<Comp a={1} b={2} />, scratch);\n\n\t\texpect(callbacks[1]).to.not.equal(callbacks[2]);\n\t\texpect(callbacks[2]).to.equal(callbacks[3]);\n\t\texpect(callbacks[2]()).to.equal(3);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useContext.test.jsx",
    "content": "import { createElement, render, createContext, Component } from 'preact';\nimport { act } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useContext, useEffect, useState } from 'preact/hooks';\nimport { vi } from 'vitest';\n\ndescribe('useContext', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('gets values from context', () => {\n\t\tconst values = [];\n\t\tconst Context = createContext(13);\n\n\t\tfunction Comp() {\n\t\t\tconst value = useContext(Context);\n\t\t\tvalues.push(value);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(\n\t\t\t<Context.Provider value={42}>\n\t\t\t\t<Comp />\n\t\t\t</Context.Provider>,\n\t\t\tscratch\n\t\t);\n\t\trender(\n\t\t\t<Context.Provider value={69}>\n\t\t\t\t<Comp />\n\t\t\t</Context.Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(values).to.deep.equal([13, 42, 69]);\n\t});\n\n\tit('should use default value', () => {\n\t\tconst Foo = createContext(42);\n\t\tconst spy = vi.fn();\n\n\t\tfunction App() {\n\t\t\tspy(useContext(Foo));\n\t\t\treturn <div />;\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(spy).toHaveBeenCalledWith(42);\n\t});\n\n\tit('should update when value changes with nonUpdating Component on top', async () => {\n\t\tconst spy = vi.fn();\n\t\tconst Ctx = createContext(0);\n\n\t\tclass NoUpdate extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tfunction App(props) {\n\t\t\treturn (\n\t\t\t\t<Ctx.Provider value={props.value}>\n\t\t\t\t\t<NoUpdate>\n\t\t\t\t\t\t<Comp />\n\t\t\t\t\t</NoUpdate>\n\t\t\t\t</Ctx.Provider>\n\t\t\t);\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst value = useContext(Ctx);\n\t\t\tspy(value);\n\t\t\treturn <h1>{value}</h1>;\n\t\t}\n\n\t\trender(<App value={0} />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith(0);\n\t\trender(<App value={1} />, scratch);\n\n\t\treturn new Promise(resolve => {\n\t\t\t// Wait for enqueued hook update\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Should not be called a third time\n\t\t\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\t\t\texpect(spy).toHaveBeenCalledWith(1);\n\t\t\t\tresolve();\n\t\t\t}, 0);\n\t\t});\n\t});\n\n\tit('should only update when value has changed', async () => {\n\t\tconst spy = vi.fn();\n\t\tconst Ctx = createContext(0);\n\n\t\tfunction App(props) {\n\t\t\treturn (\n\t\t\t\t<Ctx.Provider value={props.value}>\n\t\t\t\t\t<Comp />\n\t\t\t\t</Ctx.Provider>\n\t\t\t);\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst value = useContext(Ctx);\n\t\t\tspy(value);\n\t\t\treturn <h1>{value}</h1>;\n\t\t}\n\n\t\trender(<App value={0} />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith(0);\n\t\trender(<App value={1} />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\texpect(spy).toHaveBeenCalledWith(1);\n\n\t\treturn new Promise(resolve => {\n\t\t\t// Wait for enqueued hook update\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Should not be called a third time\n\t\t\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\t\t\tresolve();\n\t\t\t}, 0);\n\t\t});\n\t});\n\n\tit('should allow multiple context hooks at the same time', () => {\n\t\tconst Foo = createContext(0);\n\t\tconst Bar = createContext(10);\n\t\tconst spy = vi.fn();\n\t\tconst unmountspy = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tconst foo = useContext(Foo);\n\t\t\tconst bar = useContext(Bar);\n\t\t\tspy(foo, bar);\n\t\t\tuseEffect(() => () => unmountspy());\n\n\t\t\treturn <div />;\n\t\t}\n\n\t\trender(\n\t\t\t<Foo.Provider value={0}>\n\t\t\t\t<Bar.Provider value={10}>\n\t\t\t\t\t<Comp />\n\t\t\t\t</Bar.Provider>\n\t\t\t</Foo.Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith(0, 10);\n\n\t\trender(\n\t\t\t<Foo.Provider value={11}>\n\t\t\t\t<Bar.Provider value={42}>\n\t\t\t\t\t<Comp />\n\t\t\t\t</Bar.Provider>\n\t\t\t</Foo.Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\texpect(unmountspy).not.toHaveBeenCalled();\n\t});\n\n\tit('should only subscribe a component once', () => {\n\t\tconst values = [];\n\t\tconst Context = createContext(13);\n\t\tlet provider, subSpy;\n\n\t\tfunction Comp() {\n\t\t\tprovider = this._vnode._parent._component;\n\t\t\tconst value = useContext(Context);\n\t\t\tvalues.push(value);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\trender(\n\t\t\t<Context.Provider value={42}>\n\t\t\t\t<Comp />\n\t\t\t</Context.Provider>,\n\t\t\tscratch\n\t\t);\n\t\tsubSpy = vi.spyOn(provider, 'sub');\n\n\t\trender(\n\t\t\t<Context.Provider value={69}>\n\t\t\t\t<Comp />\n\t\t\t</Context.Provider>,\n\t\t\tscratch\n\t\t);\n\t\texpect(subSpy).not.toHaveBeenCalled();\n\n\t\texpect(values).to.deep.equal([13, 42, 69]);\n\t});\n\n\tit('should only subscribe a component once (non-provider)', () => {\n\t\tconst values = [];\n\t\tconst Context = createContext(13);\n\t\tlet provider, subSpy;\n\n\t\tfunction Comp() {\n\t\t\tprovider = this._vnode._parent._component;\n\t\t\tconst value = useContext(Context);\n\t\t\tvalues.push(value);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\trender(\n\t\t\t<Context value={42}>\n\t\t\t\t<Comp />\n\t\t\t</Context>,\n\t\t\tscratch\n\t\t);\n\t\tsubSpy = vi.spyOn(provider, 'sub');\n\n\t\trender(\n\t\t\t<Context value={69}>\n\t\t\t\t<Comp />\n\t\t\t</Context>,\n\t\t\tscratch\n\t\t);\n\t\texpect(subSpy).not.toHaveBeenCalled();\n\n\t\texpect(values).to.deep.equal([13, 42, 69]);\n\t});\n\n\tit('should maintain context', async () => {\n\t\tconst context = createContext(null);\n\t\tconst { Provider } = context;\n\t\tconst first = { name: 'first' };\n\t\tconst second = { name: 'second' };\n\n\t\tconst Input = () => {\n\t\t\tconst config = useContext(context);\n\n\t\t\t// Avoid eslint complaining about unused first value\n\t\t\tconst state = useState('initial');\n\t\t\tconst set = state[1];\n\n\t\t\tuseEffect(() => {\n\t\t\t\t// Schedule the update on the next frame\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tset('irrelevant');\n\t\t\t\t});\n\t\t\t}, [config]);\n\n\t\t\treturn <div>{config.name}</div>;\n\t\t};\n\n\t\tconst App = props => {\n\t\t\tconst [config, setConfig] = useState({});\n\n\t\t\tuseEffect(() => {\n\t\t\t\tsetConfig(props.config);\n\t\t\t}, [props.config]);\n\n\t\t\treturn (\n\t\t\t\t<Provider value={config}>\n\t\t\t\t\t<Input />\n\t\t\t\t</Provider>\n\t\t\t);\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App config={first} />, scratch);\n\n\t\t\t// Create a new div to append the `second` case\n\t\t\tconst div = scratch.appendChild(document.createElement('div'));\n\t\t\trender(<App config={second} />, div);\n\t\t});\n\n\t\treturn new Promise(resolve => {\n\t\t\t// Push the expect into the next frame\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\texpect(scratch.innerHTML).equal(\n\t\t\t\t\t'<div>first</div><div><div>second</div></div>'\n\t\t\t\t);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t});\n\n\tit('should not rerender consumers that have been unmounted', () => {\n\t\tconst context = createContext(0);\n\t\tconst Provider = context.Provider;\n\n\t\tconst Inner = vi.fn(() => {\n\t\t\tconst value = useContext(context);\n\t\t\treturn <div>{value}</div>;\n\t\t});\n\n\t\tlet toggleConsumer;\n\t\tlet changeValue;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\n\t\t\t\tthis.state = { value: 0, show: true };\n\t\t\t\tchangeValue = value => this.setState({ value });\n\t\t\t\ttoggleConsumer = () => this.setState(({ show }) => ({ show: !show }));\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={state.value}>\n\t\t\t\t\t\t<div>{state.show ? <Inner /> : null}</div>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>0</div></div>');\n\t\texpect(Inner).toHaveBeenCalledOnce();\n\n\t\tact(() => changeValue(1));\n\t\texpect(scratch.innerHTML).to.equal('<div><div>1</div></div>');\n\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\n\t\tact(() => toggleConsumer());\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\n\t\tact(() => changeValue(2));\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('should rerender when reset to defaultValue', () => {\n\t\tconst defaultValue = { state: 'hi' };\n\t\tconst context = createContext(defaultValue);\n\t\tlet set;\n\n\t\tconst Consumer = () => {\n\t\t\tconst ctx = useContext(context);\n\t\t\treturn <p>{ctx.state}</p>;\n\t\t};\n\n\t\tclass NoUpdate extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <Consumer />;\n\t\t\t}\n\t\t}\n\n\t\tconst Provider = () => {\n\t\t\tconst [state, setState] = useState(defaultValue);\n\t\t\tset = setState;\n\t\t\treturn (\n\t\t\t\t<context.Provider value={state}>\n\t\t\t\t\t<NoUpdate />\n\t\t\t\t</context.Provider>\n\t\t\t);\n\t\t};\n\n\t\trender(<Provider />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>hi</p>');\n\n\t\tact(() => {\n\t\t\tset({ state: 'bye' });\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>bye</p>');\n\n\t\tact(() => {\n\t\t\tset(defaultValue);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>hi</p>');\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useDebugValue.test.jsx",
    "content": "import { createElement, render, options } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useDebugValue, useState } from 'preact/hooks';\nimport { vi } from 'vitest';\n\ndescribe('useDebugValue', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tdelete options.useDebugValue;\n\t});\n\n\tit('should do nothing when no options hook is present', () => {\n\t\tfunction useFoo() {\n\t\t\tuseDebugValue('foo');\n\t\t\treturn useState(0);\n\t\t}\n\n\t\tfunction App() {\n\t\t\tlet [v] = useFoo();\n\t\t\treturn <div>{v}</div>;\n\t\t}\n\n\t\texpect(() => render(<App />, scratch)).to.not.throw();\n\t});\n\n\tit('should call options hook with value', () => {\n\t\tlet spy = (options.useDebugValue = vi.fn());\n\n\t\tfunction useFoo() {\n\t\t\tuseDebugValue('foo');\n\t\t\treturn useState(0);\n\t\t}\n\n\t\tfunction App() {\n\t\t\tlet [v] = useFoo();\n\t\t\treturn <div>{v}</div>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith('foo');\n\t});\n\n\tit('should apply optional formatter', () => {\n\t\tlet spy = (options.useDebugValue = vi.fn());\n\n\t\tfunction useFoo() {\n\t\t\tuseDebugValue('foo', x => x + 'bar');\n\t\t\treturn useState(0);\n\t\t}\n\n\t\tfunction App() {\n\t\t\tlet [v] = useFoo();\n\t\t\treturn <div>{v}</div>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledWith('foobar');\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useEffect.test.jsx",
    "content": "import { Component, Fragment, createElement, render } from 'preact';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { act, teardown as teardownAct } from 'preact/test-utils';\nimport { vi } from 'vitest';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { scheduleEffectAssert } from '../_util/useEffectUtil';\nimport { useEffectAssertions } from './useEffectAssertions';\n\ndescribe('useEffect', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tuseEffectAssertions(useEffect, scheduleEffectAssert);\n\n\tit('calls the effect immediately if another render is about to start', () => {\n\t\tconst cleanupFunction = vi.fn();\n\t\tconst callback = vi.fn(() => cleanupFunction);\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(cleanupFunction).not.toHaveBeenCalled();\n\t\texpect(callback).toHaveBeenCalledOnce();\n\n\t\trender(<Comp />, scratch);\n\n\t\texpect(cleanupFunction).toHaveBeenCalledOnce();\n\t\texpect(callback).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('cancels the effect when the component get unmounted before it had the chance to run it', () => {\n\t\tconst cleanupFunction = vi.fn();\n\t\tconst callback = vi.fn(() => cleanupFunction);\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(null, scratch);\n\n\t\treturn scheduleEffectAssert(() => {\n\t\t\texpect(cleanupFunction).not.toHaveBeenCalled();\n\t\t\texpect(callback).not.toHaveBeenCalled();\n\t\t});\n\t});\n\n\tit('should execute multiple effects in same component in the right order', () => {\n\t\tlet executionOrder = [];\n\t\tconst App = ({ i }) => {\n\t\t\texecutionOrder = [];\n\t\t\tuseEffect(() => {\n\t\t\t\texecutionOrder.push('action1');\n\t\t\t\treturn () => executionOrder.push('cleanup1');\n\t\t\t}, [i]);\n\t\t\tuseEffect(() => {\n\t\t\t\texecutionOrder.push('action2');\n\t\t\t\treturn () => executionOrder.push('cleanup2');\n\t\t\t}, [i]);\n\t\t\treturn <p>Test</p>;\n\t\t};\n\t\tact(() => render(<App i={0} />, scratch));\n\t\tact(() => render(<App i={2} />, scratch));\n\t\texpect(executionOrder).to.deep.equal([\n\t\t\t'cleanup1',\n\t\t\t'cleanup2',\n\t\t\t'action1',\n\t\t\t'action2'\n\t\t]);\n\t});\n\n\tit('should execute effects in parent if child throws in effect', async () => {\n\t\tconst executionOrder = [];\n\n\t\tconst Child = () => {\n\t\t\tuseEffect(() => {\n\t\t\t\texecutionOrder.push('child');\n\t\t\t\tthrow new Error('test');\n\t\t\t}, []);\n\n\t\t\tuseEffect(() => {\n\t\t\t\texecutionOrder.push('child after throw');\n\t\t\t\treturn () => executionOrder.push('child after throw cleanup');\n\t\t\t}, []);\n\n\t\t\treturn <p>Test</p>;\n\t\t};\n\n\t\tconst Parent = () => {\n\t\t\tuseEffect(() => {\n\t\t\t\texecutionOrder.push('parent');\n\t\t\t\treturn () => executionOrder.push('parent cleanup');\n\t\t\t}, []);\n\t\t\treturn <Child />;\n\t\t};\n\n\t\tclass ErrorBoundary extends Component {\n\t\t\tcomponentDidCatch(error) {\n\t\t\t\tthis.setState({ error });\n\t\t\t}\n\n\t\t\trender({ children }, { error }) {\n\t\t\t\treturn error ? <div>error</div> : children;\n\t\t\t}\n\t\t}\n\n\t\tact(() =>\n\t\t\trender(\n\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t<Parent />\n\t\t\t\t</ErrorBoundary>,\n\t\t\t\tscratch\n\t\t\t)\n\t\t);\n\n\t\texpect(executionOrder).to.deep.equal(['child', 'parent', 'parent cleanup']);\n\t\texpect(scratch.innerHTML).to.equal('<div>error</div>');\n\t});\n\n\tit('should throw an error upwards', () => {\n\t\tconst spy = vi.fn();\n\t\tlet errored = false;\n\n\t\tconst Page1 = () => {\n\t\t\tconst [state, setState] = useState('loading');\n\t\t\tuseEffect(() => {\n\t\t\t\tsetState('loaded');\n\t\t\t}, []);\n\t\t\treturn <p>{state}</p>;\n\t\t};\n\n\t\tconst Page2 = () => {\n\t\t\tuseEffect(() => {\n\t\t\t\tthrow new Error('err');\n\t\t\t}, []);\n\t\t\treturn <p>invisible</p>;\n\t\t};\n\n\t\tclass App extends Component {\n\t\t\tcomponentDidCatch(err) {\n\t\t\t\tspy();\n\t\t\t\terrored = err;\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (errored) {\n\t\t\t\t\treturn <p>Error</p>;\n\t\t\t\t}\n\n\t\t\t\treturn <Fragment>{props.page === 1 ? <Page1 /> : <Page2 />}</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\tact(() => render(<App page={1} />, scratch));\n\t\texpect(spy).not.toHaveBeenCalled();\n\t\texpect(scratch.innerHTML).to.equal('<p>loaded</p>');\n\n\t\tact(() => render(<App page={2} />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t\terrored = false;\n\n\t\tact(() => render(<App page={1} />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<p>loaded</p>');\n\t});\n\n\tit('should throw an error upwards from return', () => {\n\t\tconst spy = vi.fn();\n\t\tlet errored = false;\n\n\t\tconst Page1 = () => {\n\t\t\tconst [state, setState] = useState('loading');\n\t\t\tuseEffect(() => {\n\t\t\t\tsetState('loaded');\n\t\t\t}, []);\n\t\t\treturn <p>{state}</p>;\n\t\t};\n\n\t\tconst Page2 = () => {\n\t\t\tuseEffect(() => {\n\t\t\t\treturn () => {\n\t\t\t\t\tthrow new Error('err');\n\t\t\t\t};\n\t\t\t}, []);\n\t\t\treturn <p>Load</p>;\n\t\t};\n\n\t\tclass App extends Component {\n\t\t\tcomponentDidCatch(err) {\n\t\t\t\tspy();\n\t\t\t\terrored = err;\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (errored) {\n\t\t\t\t\treturn <p>Error</p>;\n\t\t\t\t}\n\n\t\t\t\treturn <Fragment>{props.page === 1 ? <Page1 /> : <Page2 />}</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\tact(() => render(<App page={2} />, scratch));\n\t\texpect(scratch.innerHTML).to.equal('<p>Load</p>');\n\n\t\tact(() => render(<App page={1} />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t});\n\n\tit('catches errors when error is invoked during render', () => {\n\t\tconst spy = vi.fn();\n\t\tlet errored;\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(() => {\n\t\t\t\tthrow new Error('hi');\n\t\t\t});\n\t\t\treturn null;\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\tcomponentDidCatch(err) {\n\t\t\t\tspy();\n\t\t\t\terrored = err;\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (errored) {\n\t\t\t\t\treturn <p>Error</p>;\n\t\t\t\t}\n\n\t\t\t\treturn <Comp />;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(errored).to.be.an('Error').with.property('message', 'hi');\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t});\n\n\tit('should allow creating a new root', () => {\n\t\tconst root = document.createElement('div');\n\t\tconst global = document.createElement('div');\n\t\tscratch.appendChild(root);\n\t\tscratch.appendChild(global);\n\n\t\tconst Modal = props => {\n\t\t\tconst [, setCanProceed] = useState(true);\n\t\t\tconst ChildProp = props.content;\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<ChildProp setCanProceed={setCanProceed} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tconst Inner = () => {\n\t\t\tuseEffect(() => {\n\t\t\t\trender(<div>global</div>, global);\n\t\t\t}, []);\n\n\t\t\treturn <div>Inner</div>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<Modal\n\t\t\t\t\tcontent={props => {\n\t\t\t\t\t\tprops.setCanProceed(false);\n\t\t\t\t\t\treturn <Inner />;\n\t\t\t\t\t}}\n\t\t\t\t/>,\n\t\t\t\troot\n\t\t\t);\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div><div>Inner</div></div></div><div><div>global</div></div>'\n\t\t);\n\t});\n\n\tit('should not crash when effect returns truthy non-function value', () => {\n\t\tconst callback = vi.fn(() => 'truthy');\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(callback).toHaveBeenCalledOnce();\n\n\t\trender(<div>Replacement</div>, scratch);\n\t});\n\n\tit('support render roots from an effect', async () => {\n\t\tlet promise, increment;\n\n\t\tconst Counter = () => {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tconst renderRoot = useRef();\n\t\t\tuseEffect(() => {\n\t\t\t\tif (count > 0) {\n\t\t\t\t\tconst div = renderRoot.current;\n\t\t\t\t\treturn () => render(<Dummy />, div);\n\t\t\t\t}\n\t\t\t\treturn () => 'test';\n\t\t\t}, [count]);\n\n\t\t\tincrement = () => {\n\t\t\t\tsetCount(x => x + 1);\n\t\t\t\tpromise = new Promise(res => {\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tsetCount(x => x + 1);\n\t\t\t\t\t\tres();\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t};\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<div>Count: {count}</div>\n\t\t\t\t\t<div ref={renderRoot} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tconst Dummy = () => <div>dummy</div>;\n\n\t\trender(<Counter />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Count: 0</div><div></div></div>'\n\t\t);\n\n\t\tact(() => {\n\t\t\tincrement();\n\t\t});\n\t\tawait promise;\n\t\tact(() => {});\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Count: 2</div><div><div>dummy</div></div></div>'\n\t\t);\n\t});\n\n\tit('hooks should be called in right order', async () => {\n\t\tteardownAct();\n\n\t\tlet increment;\n\n\t\tconst Counter = () => {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tuseState('binggo!!');\n\t\t\tconst renderRoot = useRef();\n\t\t\tuseEffect(() => {\n\t\t\t\tconst div = renderRoot.current;\n\t\t\t\trender(<Dummy />, div);\n\t\t\t}, [count]);\n\n\t\t\tincrement = () => {\n\t\t\t\tsetCount(x => x + 1);\n\t\t\t\treturn Promise.resolve().then(() => setCount(x => x + 1));\n\t\t\t};\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<div>Count: {count}</div>\n\t\t\t\t\t<div ref={renderRoot} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tconst Dummy = () => {\n\t\t\tuseState();\n\t\t\treturn <div>dummy</div>;\n\t\t};\n\n\t\trender(<Counter />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Count: 0</div><div></div></div>'\n\t\t);\n\t\t/** Using the act function will affect the timing of the useEffect */\n\t\tawait increment();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Count: 2</div><div><div>dummy</div></div></div>'\n\t\t);\n\t});\n\n\tit('handles errors correctly', () => {\n\t\tclass ErrorBoundary extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { error: null };\n\t\t\t}\n\n\t\t\tcomponentDidCatch(error) {\n\t\t\t\tthis.setState({ error: 'oh no' });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.error ? (\n\t\t\t\t\t<h2>Error! {this.state.error}</h2>\n\t\t\t\t) : (\n\t\t\t\t\tthis.props.children\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tlet update;\n\t\tconst firstEffectSpy = vi.fn();\n\t\tconst firstEffectcleanup = vi.fn();\n\t\tconst secondEffectSpy = vi.fn();\n\t\tconst secondEffectcleanup = vi.fn();\n\n\t\tconst MainContent = () => {\n\t\t\tconst [val, setVal] = useState(false);\n\n\t\t\tupdate = () => setVal(!val);\n\t\t\tuseEffect(() => {\n\t\t\t\tfirstEffectSpy();\n\t\t\t\treturn () => {\n\t\t\t\t\tfirstEffectcleanup();\n\t\t\t\t\tthrow new Error('oops');\n\t\t\t\t};\n\t\t\t}, [val]);\n\n\t\t\tuseEffect(() => {\n\t\t\t\tsecondEffectSpy();\n\t\t\t\treturn () => {\n\t\t\t\t\tsecondEffectcleanup();\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\treturn <h1>Hello world</h1>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t<MainContent />\n\t\t\t\t</ErrorBoundary>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\texpect(firstEffectSpy).toHaveBeenCalledOnce();\n\t\texpect(secondEffectSpy).toHaveBeenCalledOnce();\n\n\t\tact(() => {\n\t\t\tupdate();\n\t\t});\n\n\t\texpect(firstEffectSpy).toHaveBeenCalledOnce();\n\t\texpect(secondEffectSpy).toHaveBeenCalledOnce();\n\t\texpect(firstEffectcleanup).toHaveBeenCalledOnce();\n\t\texpect(secondEffectcleanup).toHaveBeenCalledOnce();\n\t});\n\n\tit('orders effects effectively', () => {\n\t\tconst calls = [];\n\t\tconst GrandChild = ({ id }) => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push(`${id} - Effect`);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push(`${id} - Cleanup`);\n\t\t\t\t};\n\t\t\t}, [id]);\n\t\t\treturn <p>{id}</p>;\n\t\t};\n\n\t\tconst Child = ({ id }) => {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push(`${id} - Effect`);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push(`${id} - Cleanup`);\n\t\t\t\t};\n\t\t\t}, [id]);\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<GrandChild id={`${id}-GrandChild-1`} />\n\t\t\t\t\t<GrandChild id={`${id}-GrandChild-2`} />\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t};\n\n\t\tfunction Parent() {\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('Parent - Effect');\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('Parent - Cleanup');\n\t\t\t\t};\n\t\t\t}, []);\n\t\t\treturn (\n\t\t\t\t<div className=\"App\">\n\t\t\t\t\t<Child id=\"Child-1\" />\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Child id=\"Child-2\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<Child id=\"Child-3\" />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<Parent />, scratch);\n\t\t});\n\n\t\texpect(calls).to.deep.equal([\n\t\t\t'Child-1-GrandChild-1 - Effect',\n\t\t\t'Child-1-GrandChild-2 - Effect',\n\t\t\t'Child-1 - Effect',\n\t\t\t'Child-2-GrandChild-1 - Effect',\n\t\t\t'Child-2-GrandChild-2 - Effect',\n\t\t\t'Child-2 - Effect',\n\t\t\t'Child-3-GrandChild-1 - Effect',\n\t\t\t'Child-3-GrandChild-2 - Effect',\n\t\t\t'Child-3 - Effect',\n\t\t\t'Parent - Effect'\n\t\t]);\n\t});\n\n\tit('should cancel effects from a disposed render', () => {\n\t\tconst calls = [];\n\t\tconst App = () => {\n\t\t\tconst [greeting, setGreeting] = useState('bye');\n\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('doing effect' + greeting);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + greeting);\n\t\t\t\t};\n\t\t\t}, [greeting]);\n\n\t\t\tif (greeting === 'bye') {\n\t\t\t\tsetGreeting('hi');\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\t});\n\n\tit('should not rerun committed effects', () => {\n\t\tconst calls = [];\n\t\tconst App = ({ i }) => {\n\t\t\tconst [greeting, setGreeting] = useState('hi');\n\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('doing effect' + greeting);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + greeting);\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\tif (i === 2) {\n\t\t\t\tsetGreeting('bye');\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\n\t\tact(() => {\n\t\t\trender(<App i={2} />, scratch);\n\t\t});\n\t});\n\n\tit('should not schedule effects that have no change', () => {\n\t\tconst calls = [];\n\t\tlet set;\n\t\tconst App = ({ i }) => {\n\t\t\tconst [greeting, setGreeting] = useState('hi');\n\t\t\tset = setGreeting;\n\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('doing effect' + greeting);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + greeting);\n\t\t\t\t};\n\t\t\t}, [greeting]);\n\n\t\t\tif (greeting === 'bye') {\n\t\t\t\tsetGreeting('hi');\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\n\t\tact(() => {\n\t\t\tset('bye');\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\t});\n\n\tit('should not crash when effect throws and component is unmounted by render(null) during flush', () => {\n\t\t// In flushAfterPaintEffects():\n\t\t//   1. Guard checks component.__hooks — truthy, passes\n\t\t//   2. invokeEffect runs the effect callback\n\t\t//   3. The callback calls render(null, scratch) which unmounts the tree\n\t\t//      → options.unmount sets component.__hooks = undefined\n\t\t//   4. Resetting the hooks array to an empty array would throw an error\n\t\tlet setVal;\n\n\t\tfunction App() {\n\t\t\tconst [val, _setVal] = useState(0);\n\t\t\tsetVal = _setVal;\n\t\t\tuseEffect(() => {\n\t\t\t\tif (val === 1) {\n\t\t\t\t\trender(null, scratch);\n\t\t\t\t}\n\t\t\t}, [val]);\n\t\t\treturn <div>val: {val}</div>;\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\tact(() => {\n\t\t\tsetVal(1);\n\t\t});\n\t});\n\n\tit('should not rerun when receiving NaN on subsequent renders', () => {\n\t\tconst calls = [];\n\t\tconst Component = ({ value }) => {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tuseEffect(() => {\n\t\t\t\tcalls.push('doing effect' + count);\n\t\t\t\tsetCount(count + 1);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + count);\n\t\t\t\t};\n\t\t\t}, [value]);\n\t\t\treturn <p>{count}</p>;\n\t\t};\n\t\tconst App = () => <Component value={Number.NaN} />;\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effect0']);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useEffectAssertions.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\n// Common behaviors between all effect hooks\nexport function useEffectAssertions(useEffect, scheduleEffectAssert) {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('performs the effect after every render by default', () => {\n\t\tconst callback = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\treturn scheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t)\n\t\t\t.then(() => render(<Comp />, scratch))\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledTimes(2))\n\t\t\t);\n\t});\n\n\tit('performs the effect only if one of the inputs changed', () => {\n\t\tconst callback = vi.fn();\n\n\t\tfunction Comp(props) {\n\t\t\tuseEffect(callback, [props.a, props.b]);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp a={1} b={2} />, scratch);\n\n\t\treturn scheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t.then(() => render(<Comp a={1} b={2} />, scratch))\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t)\n\t\t\t.then(() => render(<Comp a={2} b={2} />, scratch))\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledTimes(2))\n\t\t\t)\n\t\t\t.then(() => render(<Comp a={2} b={2} />, scratch))\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledTimes(2))\n\t\t\t);\n\t});\n\n\tit('performs the effect at mount time and never again if an empty input Array is passed', () => {\n\t\tconst callback = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback, []);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(callback).toHaveBeenCalledOnce();\n\n\t\treturn scheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t.then(() => render(<Comp />, scratch))\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t);\n\t});\n\n\tit('calls the cleanup function followed by the effect after each render', () => {\n\t\tconst cleanupFunction = vi.fn();\n\t\tconst callback = vi.fn(() => cleanupFunction);\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\treturn scheduleEffectAssert(() => {\n\t\t\texpect(cleanupFunction).not.toHaveBeenCalled();\n\t\t\texpect(callback).toHaveBeenCalledOnce();\n\t\t})\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => expect(callback).toHaveBeenCalledOnce())\n\t\t\t)\n\t\t\t.then(() => render(<Comp />, scratch))\n\t\t\t.then(() =>\n\t\t\t\tscheduleEffectAssert(() => {\n\t\t\t\t\texpect(cleanupFunction).toHaveBeenCalledOnce();\n\t\t\t\t\texpect(callback).toHaveBeenCalledTimes(2);\n\t\t\t\t\tconst callbackLastInvocation =\n\t\t\t\t\t\tcallback.mock.invocationCallOrder[\n\t\t\t\t\t\t\tcallback.mock.invocationCallOrder.length - 1\n\t\t\t\t\t\t];\n\t\t\t\t\texpect(callbackLastInvocation).to.be.greaterThan(\n\t\t\t\t\t\tcleanupFunction.mock.invocationCallOrder[0]\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t);\n\t});\n\n\tit('cleanups the effect when the component get unmounted if the effect was called before', () => {\n\t\tconst cleanupFunction = vi.fn();\n\t\tconst callback = vi.fn(() => cleanupFunction);\n\n\t\tfunction Comp() {\n\t\t\tuseEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\treturn scheduleEffectAssert(() => {\n\t\t\trender(null, scratch);\n\t\t\trerender();\n\t\t\texpect(cleanupFunction).toHaveBeenCalledOnce();\n\t\t});\n\t});\n\n\tit('works with closure effect callbacks capturing props', () => {\n\t\tconst values = [];\n\n\t\tfunction Comp(props) {\n\t\t\tuseEffect(() => values.push(props.value));\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp value={1} />, scratch);\n\t\trender(<Comp value={2} />, scratch);\n\n\t\treturn scheduleEffectAssert(() => expect(values).to.deep.equal([1, 2]));\n\t});\n}\n"
  },
  {
    "path": "hooks/test/browser/useId.test.jsx",
    "content": "import { createElement, Fragment, hydrate, render } from 'preact';\nimport { useId, useReducer, useState } from 'preact/hooks';\nimport { setupRerender } from 'preact/test-utils';\nimport { render as rts } from 'preact-render-to-string';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('useId', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch, rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('keeps the id consistent after an update', () => {\n\t\tfunction Comp() {\n\t\t\tconst id = useId();\n\t\t\treturn <div id={id} />;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\tconst id = scratch.firstChild.getAttribute('id');\n\t\texpect(scratch.firstChild.getAttribute('id')).to.equal(id);\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('id')).to.equal(id);\n\t});\n\n\tit('ids are unique according to dom-depth', () => {\n\t\tfunction Child() {\n\t\t\tconst id = useId();\n\t\t\tconst spanId = useId();\n\t\t\treturn (\n\t\t\t\t<div id={id}>\n\t\t\t\t\t<span id={spanId}>h</span>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<div id={id}>\n\t\t\t\t\t<Child />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"P0-0\"><div id=\"P0-1\"><span id=\"P0-2\">h</span></div></div>'\n\t\t);\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"P0-0\"><div id=\"P0-1\"><span id=\"P0-2\">h</span></div></div>'\n\t\t);\n\t});\n\n\tit('ids are unique across siblings', () => {\n\t\tfunction Child() {\n\t\t\tconst id = useId();\n\t\t\treturn <span id={id}>h</span>;\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<div id={id}>\n\t\t\t\t\t<Child />\n\t\t\t\t\t<Child />\n\t\t\t\t\t<Child />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"P0-0\"><span id=\"P0-1\">h</span><span id=\"P0-2\">h</span><span id=\"P0-3\">h</span></div>'\n\t\t);\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"P0-0\"><span id=\"P0-1\">h</span><span id=\"P0-2\">h</span><span id=\"P0-3\">h</span></div>'\n\t\t);\n\t});\n\n\tit('correctly handles new elements', () => {\n\t\tlet set;\n\t\tfunction Child() {\n\t\t\tconst id = useId();\n\t\t\treturn <span id={id}>h</span>;\n\t\t}\n\n\t\tfunction Stateful() {\n\t\t\tconst [state, setState] = useState(false);\n\t\t\tset = setState;\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Child />\n\t\t\t\t\t{state && <Child />}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<div id={id}>\n\t\t\t\t\t<Stateful />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"P0-0\"><div><span id=\"P0-1\">h</span></div></div>'\n\t\t);\n\n\t\tset(true);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"P0-0\"><div><span id=\"P0-1\">h</span><span id=\"P0-2\">h</span></div></div>'\n\t\t);\n\t});\n\n\tit('matches with rts', () => {\n\t\tconst ChildFragmentReturn = ({ children }) => {\n\t\t\treturn <Fragment>{children}</Fragment>;\n\t\t};\n\n\t\tconst ChildReturn = ({ children }) => {\n\t\t\treturn children;\n\t\t};\n\n\t\tconst SomeMessage = ({ msg }) => {\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<p>\n\t\t\t\t\t{msg} {id}\n\t\t\t\t</p>\n\t\t\t);\n\t\t};\n\n\t\tconst Stateful = () => {\n\t\t\tconst [count, add] = useReducer(c => c + 1, 0);\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\tid: {id}, count: {count}\n\t\t\t\t\t<button onClick={add}>+1</button>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tconst Component = ({ showStateful = false }) => {\n\t\t\tconst rootId = useId();\n\t\t\tconst paragraphId = useId();\n\n\t\t\treturn (\n\t\t\t\t<main>\n\t\t\t\t\tID: {rootId}\n\t\t\t\t\t<p>Hello world id: {paragraphId}</p>\n\t\t\t\t\t{showStateful\n\t\t\t\t\t\t? <Stateful />\n\t\t\t\t\t\t: <ChildReturn>\n\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t\t<ChildReturn>\n\t\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t\t\t<ChildReturn>\n\t\t\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t\t\t</ChildReturn>\n\t\t\t\t\t\t\t\t</ChildReturn>\n\t\t\t\t\t\t\t</ChildReturn>}\n\t\t\t\t\t<ChildFragmentReturn>\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return\" />\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return-2\" />\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return-3\" />\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return-4\" />\n\t\t\t\t\t\t<ChildReturn>\n\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t<ChildFragmentReturn>\n\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return\" />\n\t\t\t\t\t\t\t</ChildFragmentReturn>\n\t\t\t\t\t\t</ChildReturn>\n\t\t\t\t\t</ChildFragmentReturn>\n\t\t\t\t</main>\n\t\t\t);\n\t\t};\n\n\t\tconst rtsOutput = rts(<Component />);\n\t\trender(<Component />, scratch);\n\t\texpect(rtsOutput === scratch.innerHTML).to.equal(true);\n\t});\n\n\tit('matches with rts after hydration', () => {\n\t\tconst ChildFragmentReturn = ({ children }) => {\n\t\t\treturn <Fragment>{children}</Fragment>;\n\t\t};\n\n\t\tconst ChildReturn = ({ children }) => {\n\t\t\treturn children;\n\t\t};\n\n\t\tconst SomeMessage = ({ msg }) => {\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<p>\n\t\t\t\t\t{msg} {id}\n\t\t\t\t</p>\n\t\t\t);\n\t\t};\n\n\t\tconst Stateful = () => {\n\t\t\tconst [count, add] = useReducer(c => c + 1, 0);\n\t\t\tconst id = useId();\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\tid: {id}, count: {count}\n\t\t\t\t\t<button onClick={add}>+1</button>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tconst Component = ({ showStateful = false }) => {\n\t\t\tconst rootId = useId();\n\t\t\tconst paragraphId = useId();\n\n\t\t\treturn (\n\t\t\t\t<main>\n\t\t\t\t\tID: {rootId}\n\t\t\t\t\t<p>Hello world id: {paragraphId}</p>\n\t\t\t\t\t{showStateful\n\t\t\t\t\t\t? <Stateful />\n\t\t\t\t\t\t: <ChildReturn>\n\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t\t<ChildReturn>\n\t\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t\t\t<ChildReturn>\n\t\t\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t\t\t</ChildReturn>\n\t\t\t\t\t\t\t\t</ChildReturn>\n\t\t\t\t\t\t\t</ChildReturn>}\n\t\t\t\t\t<ChildFragmentReturn>\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return\" />\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return-2\" />\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return-3\" />\n\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return-4\" />\n\t\t\t\t\t\t<ChildReturn>\n\t\t\t\t\t\t\t<SomeMessage msg=\"child-return\" />\n\t\t\t\t\t\t\t<ChildFragmentReturn>\n\t\t\t\t\t\t\t\t<SomeMessage msg=\"child-fragment-return\" />\n\t\t\t\t\t\t\t</ChildFragmentReturn>\n\t\t\t\t\t\t</ChildReturn>\n\t\t\t\t\t</ChildFragmentReturn>\n\t\t\t\t</main>\n\t\t\t);\n\t\t};\n\n\t\tconst rtsOutput = rts(<Component />);\n\n\t\tscratch.innerHTML = rtsOutput;\n\t\thydrate(<Component />, scratch);\n\t\texpect(rtsOutput).to.equal(scratch.innerHTML);\n\t});\n\n\tit('should be unique across Fragments', () => {\n\t\tconst ids = [];\n\t\tfunction Foo() {\n\t\t\tconst id = useId();\n\t\t\tids.push(id);\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Foo />\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</Fragment>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(ids[0]).not.to.equal(ids[1]);\n\t});\n\n\tit('should match implicite Fragments with RTS', () => {\n\t\tfunction Foo() {\n\t\t\tconst id = useId();\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\n\t\tfunction Bar(props) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<Bar>\n\t\t\t\t\t<Foo />\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Bar>\n\t\t\t);\n\t\t}\n\n\t\tconst rtsOutput = rts(<App />);\n\n\t\tscratch.innerHTML = rtsOutput;\n\t\thydrate(<App />, scratch);\n\t\texpect(rtsOutput).to.equal(scratch.innerHTML);\n\t});\n\n\tit('should skip component top level Fragment child', () => {\n\t\tconst Wrapper = ({ children }) => {\n\t\t\treturn <Fragment>{children}</Fragment>;\n\t\t};\n\n\t\tconst ids = [];\n\t\tfunction Foo() {\n\t\t\tconst id = useId();\n\t\t\tids.push(id);\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\tconst id = useId();\n\t\t\tids.push(id);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>{id}</p>\n\t\t\t\t\t<Wrapper>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</Wrapper>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(ids[0]).not.to.equal(ids[1]);\n\t});\n\n\tit('should skip over HTML', () => {\n\t\tconst ids = [];\n\n\t\tfunction Foo() {\n\t\t\tconst id = useId();\n\t\t\tids.push(id);\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</span>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(ids[0]).not.to.equal(ids[1]);\n\t});\n\n\tit('should reset for each renderToString roots', () => {\n\t\tconst ids = [];\n\n\t\tfunction Foo() {\n\t\t\tconst id = useId();\n\t\t\tids.push(id);\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</span>\n\t\t\t\t\t<span>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst res1 = rts(<App />);\n\t\tconst res2 = rts(<App />);\n\t\texpect(res1).to.equal(res2);\n\t});\n\n\tit('should work with conditional components', () => {\n\t\tfunction Foo() {\n\t\t\tconst id = useId();\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\t\tfunction Bar() {\n\t\t\tconst id = useId();\n\t\t\treturn <p>{id}</p>;\n\t\t}\n\n\t\tlet update;\n\t\tfunction App() {\n\t\t\tconst [v, setV] = useState(false);\n\t\t\tupdate = setV;\n\t\t\treturn <div>{!v ? <Foo /> : <Bar />}</div>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tconst first = scratch.innerHTML;\n\n\t\tupdate(v => !v);\n\t\trerender();\n\t\texpect(first).not.to.equal(scratch.innerHTML);\n\t});\n\n\tit('should return a unique id across invocations of render', () => {\n\t\tconst Id = () => {\n\t\t\tconst id = useId();\n\t\t\treturn <div>My id is {id}</div>;\n\t\t};\n\n\t\tconst App = props => {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Id />\n\t\t\t\t\t{props.secondId ? <Id /> : null}\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(createElement(App, { secondId: false }), scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>My id is P0-0</div></div>');\n\t\trender(createElement(App, { secondId: true }), scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>My id is P0-0</div><div>My id is P0-1</div></div>'\n\t\t);\n\t});\n\n\tit('should not crash for rendering null after a non-null render', () => {\n\t\tconst Id = () => {\n\t\t\tconst id = useId();\n\t\t\treturn <div>My id is {id}</div>;\n\t\t};\n\n\t\tconst App = props => {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Id />\n\t\t\t\t\t{props.secondId ? <Id /> : null}\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(createElement(App, { secondId: false }), scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>My id is P0-0</div></div>');\n\t\trender(null, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useImperativeHandle.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useImperativeHandle, useRef, useState } from 'preact/hooks';\nimport { setupRerender } from 'preact/test-utils';\nimport { vi } from 'vitest';\n\ndescribe('useImperativeHandle', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('Mutates given ref', () => {\n\t\tlet ref;\n\n\t\tfunction Comp() {\n\t\t\tref = useRef({});\n\t\t\tuseImperativeHandle(ref, () => ({ test: () => 'test' }), []);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(ref.current).to.have.property('test');\n\t\texpect(ref.current.test()).to.equal('test');\n\t});\n\n\tit('Calls ref unmounting function', () => {\n\t\tlet ref;\n\t\tconst unmount = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tuseImperativeHandle(\n\t\t\t\tr => {\n\t\t\t\t\tref = r;\n\t\t\t\t\treturn unmount;\n\t\t\t\t},\n\t\t\t\t() => ({ test: () => 'test' }),\n\t\t\t\t[]\n\t\t\t);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(ref).to.have.property('test');\n\t\texpect(ref.test()).to.equal('test');\n\t\trender(null, scratch);\n\t\texpect(unmount).toHaveBeenCalledOnce();\n\t\texpect(ref).to.equal(null);\n\t});\n\n\tit('calls createHandle after every render by default', () => {\n\t\tlet ref,\n\t\t\tcreateHandleSpy = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tref = useRef({});\n\t\t\tuseImperativeHandle(ref, createHandleSpy);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(2);\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(3);\n\t});\n\n\tit('calls createHandle only on mount if an empty array is passed', () => {\n\t\tlet ref,\n\t\t\tcreateHandleSpy = vi.fn();\n\n\t\tfunction Comp() {\n\t\t\tref = useRef({});\n\t\t\tuseImperativeHandle(ref, createHandleSpy, []);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t});\n\n\tit('Updates given ref when args change', () => {\n\t\tlet ref,\n\t\t\tcreateHandleSpy = vi.fn();\n\n\t\tfunction Comp({ a }) {\n\t\t\tref = useRef({});\n\t\t\tuseImperativeHandle(ref, () => {\n\t\t\t\tcreateHandleSpy();\n\t\t\t\treturn { test: () => 'test' + a };\n\t\t\t}, [a]);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp a={0} />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref.current).to.have.property('test');\n\t\texpect(ref.current.test()).to.equal('test0');\n\n\t\trender(<Comp a={1} />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(2);\n\t\texpect(ref.current).to.have.property('test');\n\t\texpect(ref.current.test()).to.equal('test1');\n\n\t\trender(<Comp a={0} />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(3);\n\t\texpect(ref.current).to.have.property('test');\n\t\texpect(ref.current.test()).to.equal('test0');\n\t});\n\n\tit('Updates given ref when passed-in ref changes', () => {\n\t\tlet ref1, ref2;\n\n\t\t/** @type {(arg: any) => void} */\n\t\tlet setRef;\n\n\t\t/** @type {() => void} */\n\t\tlet updateState;\n\n\t\tconst createHandleSpy = vi.fn(() => ({\n\t\t\ttest: () => 'test'\n\t\t}));\n\n\t\tfunction Comp() {\n\t\t\tref1 = useRef({});\n\t\t\tref2 = useRef({});\n\n\t\t\tconst [ref, setRefInternal] = useState(ref1);\n\t\t\tsetRef = setRefInternal;\n\n\t\t\tlet [value, setState] = useState(0);\n\t\t\tupdateState = () => setState((value + 1) % 2);\n\n\t\t\tuseImperativeHandle(ref, createHandleSpy, []);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp a={0} />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\n\t\tupdateState();\n\t\trerender();\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\n\t\tsetRef(ref2);\n\t\trerender();\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(2);\n\n\t\tupdateState();\n\t\trerender();\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(2);\n\n\t\tsetRef(ref1);\n\t\trerender();\n\t\texpect(createHandleSpy).toHaveBeenCalledTimes(3);\n\t});\n\n\tit('should not update ref when args have not changed', () => {\n\t\tlet ref,\n\t\t\tcreateHandleSpy = vi.fn(() => ({ test: () => 'test' }));\n\n\t\tfunction Comp() {\n\t\t\tref = useRef({});\n\t\t\tuseImperativeHandle(ref, createHandleSpy, [1]);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref.current.test()).to.equal('test');\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref.current.test()).to.equal('test');\n\t});\n\n\tit('should not throw with nullish ref', () => {\n\t\tfunction Comp() {\n\t\t\tuseImperativeHandle(null, () => ({ test: () => 'test' }), [1]);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\texpect(() => render(<Comp />, scratch)).to.not.throw();\n\t});\n\n\tit('should reset ref object to null when the component get unmounted', () => {\n\t\tlet ref,\n\t\t\tcreateHandleSpy = vi.fn(() => ({ test: () => 'test' }));\n\n\t\tfunction Comp() {\n\t\t\tref = useRef({});\n\t\t\tuseImperativeHandle(ref, createHandleSpy, [1]);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref.current).to.not.equal(null);\n\n\t\trender(<div />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref.current).to.equal(null);\n\t});\n\n\tit('should reset ref callback to null when the component get unmounted', () => {\n\t\tconst ref = vi.fn();\n\t\tconst handle = { test: () => 'test' };\n\t\tconst createHandleSpy = vi.fn(() => handle);\n\n\t\tfunction Comp() {\n\t\t\tuseImperativeHandle(ref, createHandleSpy, [1]);\n\t\t\treturn <p>Test</p>;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref).toHaveBeenCalledWith(handle);\n\n\t\tref.mockClear();\n\n\t\trender(<div />, scratch);\n\t\texpect(createHandleSpy).toHaveBeenCalledOnce();\n\t\texpect(ref).toHaveBeenCalledWith(null);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useLayoutEffect.test.jsx",
    "content": "import { act } from 'preact/test-utils';\nimport { createElement, render, Fragment, Component } from 'preact';\nimport {\n\tsetupScratch,\n\tteardown,\n\tserializeHtml\n} from '../../../test/_util/helpers';\nimport { useEffectAssertions } from './useEffectAssertions';\nimport { useLayoutEffect, useRef, useState } from 'preact/hooks';\nimport { vi } from 'vitest';\n\ndescribe('useLayoutEffect', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\t// Layout effects fire synchronously\n\tconst scheduleEffectAssert = assertFn =>\n\t\tnew Promise(resolve => {\n\t\t\tassertFn();\n\t\t\tresolve();\n\t\t});\n\n\tuseEffectAssertions(useLayoutEffect, scheduleEffectAssert);\n\n\tit('calls the effect immediately after render', () => {\n\t\tconst cleanupFunction = vi.fn();\n\t\tconst callback = vi.fn(() => cleanupFunction);\n\n\t\tfunction Comp() {\n\t\t\tuseLayoutEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(cleanupFunction).toHaveBeenCalledOnce();\n\t\texpect(callback).toHaveBeenCalledTimes(2);\n\n\t\trender(<Comp />, scratch);\n\n\t\texpect(cleanupFunction).toHaveBeenCalledTimes(2);\n\t\texpect(callback).toHaveBeenCalledTimes(3);\n\t});\n\n\tit('works on a nested component', () => {\n\t\tconst callback = vi.fn();\n\n\t\tfunction Parent() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Child />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction Child() {\n\t\t\tuseLayoutEffect(callback);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Parent />, scratch);\n\n\t\texpect(callback).toHaveBeenCalledOnce();\n\t});\n\n\tit('should execute multiple layout effects in same component in the right order', () => {\n\t\tlet executionOrder = [];\n\t\tconst App = ({ i }) => {\n\t\t\texecutionOrder = [];\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\texecutionOrder.push('action1');\n\t\t\t\treturn () => executionOrder.push('cleanup1');\n\t\t\t}, [i]);\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\texecutionOrder.push('action2');\n\t\t\t\treturn () => executionOrder.push('cleanup2');\n\t\t\t}, [i]);\n\t\t\treturn <p>Test</p>;\n\t\t};\n\t\trender(<App i={0} />, scratch);\n\t\trender(<App i={2} />, scratch);\n\t\texpect(executionOrder).to.deep.equal([\n\t\t\t'cleanup1',\n\t\t\t'cleanup2',\n\t\t\t'action1',\n\t\t\t'action2'\n\t\t]);\n\t});\n\n\tit('should correctly display DOM', () => {\n\t\tfunction AutoResizeTextareaLayoutEffect(props) {\n\t\t\tconst ref = useRef(null);\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\t// IE & Edge put textarea's value as child of textarea when reading innerHTML so use\n\t\t\t\t// cross browser serialize helper\n\t\t\t\tconst actualHtml = serializeHtml(scratch);\n\t\t\t\tconst expectedHTML = `<div class=\"${props.value}\"><p>${props.value}</p><textarea></textarea></div>`;\n\t\t\t\texpect(actualHtml).to.equal(expectedHTML);\n\t\t\t\texpect(document.body.contains(ref.current)).to.equal(true);\n\t\t\t});\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<p>{props.value}</p>\n\t\t\t\t\t<textarea ref={ref} value={props.value} onChange={props.onChange} />\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tfunction App(props) {\n\t\t\treturn (\n\t\t\t\t<div class={props.value}>\n\t\t\t\t\t<AutoResizeTextareaLayoutEffect {...props} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App value=\"hi\" />, scratch);\n\t\trender(<App value=\"hii\" />, scratch);\n\t});\n\n\tit('should invoke layout effects after subtree is fully connected', () => {\n\t\tlet ref;\n\t\tlet layoutEffect = vi.fn(() => {\n\t\t\tconst isConnected = document.body.contains(ref.current);\n\t\t\texpect(isConnected).to.equal(true, 'isConnected');\n\t\t});\n\n\t\tfunction Inner() {\n\t\t\tref = useRef(null);\n\t\t\tuseLayoutEffect(layoutEffect);\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<textarea ref={ref} />\n\t\t\t\t\t<span>hello</span>;\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tfunction Outer() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Inner />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Outer />, scratch);\n\t\texpect(layoutEffect).toHaveBeenCalledOnce();\n\t});\n\n\t// TODO: Make this test pass to resolve issue #1886\n\tit.skip('should call effects correctly when unmounting', () => {\n\t\tlet onClick, calledFoo, calledBar, calledFooCleanup, calledBarCleanup;\n\n\t\tconst Foo = () => {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tif (!calledFoo) calledFoo = scratch.innerHTML;\n\t\t\t\treturn () => {\n\t\t\t\t\tif (!calledFooCleanup) calledFooCleanup = scratch.innerHTML;\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Foo</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tconst Bar = () => {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tif (!calledBar) calledBar = scratch.innerHTML;\n\t\t\t\treturn () => {\n\t\t\t\t\tif (!calledBarCleanup) calledBarCleanup = scratch.innerHTML;\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Bar</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tfunction App() {\n\t\t\tconst [current, setCurrent] = useState('/foo');\n\n\t\t\tonClick = () => setCurrent(current === '/foo' ? '/bar' : '/foo');\n\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<button onClick={onClick}>next</button>\n\n\t\t\t\t\t{current === '/foo' && <Foo />}\n\t\t\t\t\t{current === '/bar' && <Bar />}\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(calledFoo).to.equal(\n\t\t\t'<button>next</button><div><p>Foo</p></div>',\n\t\t\t'calledFoo'\n\t\t);\n\n\t\tact(() => onClick());\n\t\texpect(calledFooCleanup).to.equal(\n\t\t\t'<button>next</button><div><p>Bar</p></div>',\n\t\t\t'calledFooCleanup'\n\t\t);\n\t\texpect(calledBar).to.equal(\n\t\t\t'<button>next</button><div><p>Bar</p></div>',\n\t\t\t'calledBar'\n\t\t);\n\n\t\tact(() => onClick());\n\t\texpect(calledBarCleanup).to.equal(\n\t\t\t'<button>next</button><div><p>Foo</p></div>',\n\t\t\t'calledBarCleanup'\n\t\t);\n\t});\n\n\tit('should throw an error upwards', () => {\n\t\tconst spy = vi.fn();\n\t\tlet errored = false;\n\n\t\tconst Page1 = () => {\n\t\t\tconst [state, setState] = useState('loading');\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tsetState('loaded');\n\t\t\t}, []);\n\t\t\treturn <p>{state}</p>;\n\t\t};\n\n\t\tconst Page2 = () => {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tthrow new Error('err');\n\t\t\t}, []);\n\t\t\treturn <p>invisible</p>;\n\t\t};\n\n\t\tclass App extends Component {\n\t\t\tcomponentDidCatch(err) {\n\t\t\t\tspy();\n\t\t\t\terrored = err;\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (errored) {\n\t\t\t\t\treturn <p>Error</p>;\n\t\t\t\t}\n\n\t\t\t\treturn <Fragment>{props.page === 1 ? <Page1 /> : <Page2 />}</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\tact(() => render(<App page={1} />, scratch));\n\t\texpect(spy).not.toHaveBeenCalled();\n\t\texpect(scratch.innerHTML).to.equal('<p>loaded</p>');\n\n\t\tact(() => render(<App page={2} />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t\terrored = false;\n\n\t\tact(() => render(<App page={1} />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<p>loaded</p>');\n\t});\n\n\tit('should throw an error upwards from return', () => {\n\t\tconst spy = vi.fn();\n\t\tlet errored = false;\n\n\t\tconst Page1 = () => {\n\t\t\tconst [state, setState] = useState('loading');\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tsetState('loaded');\n\t\t\t}, []);\n\t\t\treturn <p>{state}</p>;\n\t\t};\n\n\t\tconst Page2 = () => {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\treturn () => {\n\t\t\t\t\tthrow new Error('err');\n\t\t\t\t};\n\t\t\t}, []);\n\t\t\treturn <p>Load</p>;\n\t\t};\n\n\t\tclass App extends Component {\n\t\t\tcomponentDidCatch(err) {\n\t\t\t\tspy();\n\t\t\t\terrored = err;\n\t\t\t\tthis.forceUpdate();\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\tif (errored) {\n\t\t\t\t\treturn <p>Error</p>;\n\t\t\t\t}\n\n\t\t\t\treturn <Fragment>{props.page === 1 ? <Page1 /> : <Page2 />}</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\tact(() => render(<App page={2} />, scratch));\n\t\texpect(scratch.innerHTML).to.equal('<p>Load</p>');\n\n\t\tact(() => render(<App page={1} />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<p>Error</p>');\n\t});\n\n\tit('orders effects effectively', () => {\n\t\tconst calls = [];\n\t\tconst GrandChild = ({ id }) => {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push(`${id} - Effect`);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push(`${id} - Cleanup`);\n\t\t\t\t};\n\t\t\t}, [id]);\n\t\t\treturn <p>{id}</p>;\n\t\t};\n\n\t\tconst Child = ({ id }) => {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push(`${id} - Effect`);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push(`${id} - Cleanup`);\n\t\t\t\t};\n\t\t\t}, [id]);\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<GrandChild id={`${id}-GrandChild-1`} />\n\t\t\t\t\t<GrandChild id={`${id}-GrandChild-2`} />\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t};\n\n\t\tfunction Parent() {\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push('Parent - Effect');\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('Parent - Cleanup');\n\t\t\t\t};\n\t\t\t}, []);\n\t\t\treturn (\n\t\t\t\t<div className=\"App\">\n\t\t\t\t\t<Child id=\"Child-1\" />\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Child id=\"Child-2\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<Child id=\"Child-3\" />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<Parent />, scratch);\n\t\t});\n\n\t\texpect(calls).to.deep.equal([\n\t\t\t'Child-1-GrandChild-1 - Effect',\n\t\t\t'Child-1-GrandChild-2 - Effect',\n\t\t\t'Child-1 - Effect',\n\t\t\t'Child-2-GrandChild-1 - Effect',\n\t\t\t'Child-2-GrandChild-2 - Effect',\n\t\t\t'Child-2 - Effect',\n\t\t\t'Child-3-GrandChild-1 - Effect',\n\t\t\t'Child-3-GrandChild-2 - Effect',\n\t\t\t'Child-3 - Effect',\n\t\t\t'Parent - Effect'\n\t\t]);\n\t});\n\n\tit('should cancel effects from a disposed render', () => {\n\t\tconst calls = [];\n\t\tconst App = () => {\n\t\t\tconst [greeting, setGreeting] = useState('bye');\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push('doing effect' + greeting);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + greeting);\n\t\t\t\t};\n\t\t\t}, [greeting]);\n\n\t\t\tif (greeting === 'bye') {\n\t\t\t\tsetGreeting('hi');\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\t});\n\n\tit('should not rerun committed effects', () => {\n\t\tconst calls = [];\n\t\tconst App = ({ i }) => {\n\t\t\tconst [greeting, setGreeting] = useState('hi');\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push('doing effect' + greeting);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + greeting);\n\t\t\t\t};\n\t\t\t}, []);\n\n\t\t\tif (i === 2) {\n\t\t\t\tsetGreeting('bye');\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\n\t\tact(() => {\n\t\t\trender(<App i={2} />, scratch);\n\t\t});\n\t});\n\n\tit('should not schedule effects that have no change', () => {\n\t\tconst calls = [];\n\t\tlet set;\n\t\tconst App = ({ i }) => {\n\t\t\tconst [greeting, setGreeting] = useState('hi');\n\t\t\tset = setGreeting;\n\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\tcalls.push('doing effect' + greeting);\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up' + greeting);\n\t\t\t\t};\n\t\t\t}, [greeting]);\n\n\t\t\tif (greeting === 'bye') {\n\t\t\t\tsetGreeting('hi');\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\n\t\tact(() => {\n\t\t\tset('bye');\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['doing effecthi']);\n\t});\n\n\tit('should run layout affects after all refs are invoked', () => {\n\t\tconst calls = [];\n\t\tconst verifyRef = name => el => {\n\t\t\tcalls.push(name);\n\t\t\texpect(document.body.contains(el), name).to.equal(true);\n\t\t};\n\n\t\tconst App = () => {\n\t\t\tconst ref = useRef();\n\t\t\tuseLayoutEffect(() => {\n\t\t\t\texpect(ref.current).to.equalNode(scratch.querySelector('p'));\n\n\t\t\t\tcalls.push('doing effect');\n\t\t\t\treturn () => {\n\t\t\t\t\tcalls.push('cleaning up');\n\t\t\t\t};\n\t\t\t});\n\n\t\t\treturn (\n\t\t\t\t<div ref={verifyRef('callback ref outer')}>\n\t\t\t\t\t<p ref={ref}>\n\t\t\t\t\t\t<span ref={verifyRef('callback ref inner')}>Hi</span>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls).to.deep.equal([\n\t\t\t'callback ref inner',\n\t\t\t'callback ref outer',\n\t\t\t'doing effect'\n\t\t]);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useMemo.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useMemo, useState } from 'preact/hooks';\nimport { act } from 'preact/test-utils';\nimport { vi } from 'vitest';\n\ndescribe('useMemo', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('only recomputes the result when inputs change', () => {\n\t\tlet memoFunction = vi.fn((a, b) => a + b);\n\t\tconst results = [];\n\n\t\tfunction Comp({ a, b }) {\n\t\t\tconst result = useMemo(() => memoFunction(a, b), [a, b]);\n\t\t\tresults.push(result);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp a={1} b={1} />, scratch);\n\t\trender(<Comp a={1} b={1} />, scratch);\n\n\t\texpect(results).to.deep.equal([2, 2]);\n\t\texpect(memoFunction).toHaveBeenCalledOnce();\n\n\t\trender(<Comp a={1} b={2} />, scratch);\n\t\trender(<Comp a={1} b={2} />, scratch);\n\n\t\texpect(results).to.deep.equal([2, 2, 3, 3]);\n\t\texpect(memoFunction).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('should rerun when deps length changes', () => {\n\t\tlet memoFunction = vi.fn(() => 1 + 2);\n\n\t\tfunction Comp({ all }) {\n\t\t\tconst deps = [1, all && 2].filter(Boolean);\n\t\t\tconst result = useMemo(() => memoFunction(), deps);\n\t\t\treturn result;\n\t\t}\n\n\t\trender(<Comp all />, scratch);\n\t\texpect(memoFunction).toHaveBeenCalledOnce();\n\t\trender(<Comp all={false} />, scratch);\n\t\texpect(memoFunction).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('should rerun when first run threw an error', () => {\n\t\tlet hasThrown = false;\n\t\tlet memoFunction = vi.fn(() => {\n\t\t\tif (!hasThrown) {\n\t\t\t\thasThrown = true;\n\t\t\t\tthrow new Error('test');\n\t\t\t} else {\n\t\t\t\treturn 3;\n\t\t\t}\n\t\t});\n\n\t\tfunction Comp() {\n\t\t\tconst result = useMemo(() => memoFunction(), []);\n\t\t\treturn result;\n\t\t}\n\n\t\texpect(() => render(<Comp />, scratch)).to.throw('test');\n\t\texpect(memoFunction).toHaveBeenCalledOnce();\n\t\texpect(() => render(<Comp />, scratch)).not.to.throw();\n\t\texpect(memoFunction).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('short circuits diffing for memoized components', () => {\n\t\tlet spy = vi.fn();\n\t\tlet spy2 = vi.fn();\n\t\tconst X = ({ count }) => {\n\t\t\tspy();\n\t\t\treturn <span>{count}</span>;\n\t\t};\n\n\t\tconst Y = ({ count }) => {\n\t\t\tspy2();\n\t\t\treturn <p>{count}</p>;\n\t\t};\n\n\t\tconst App = ({ x }) => {\n\t\t\tconst y = useMemo(() => <Y count={x} />, [x]);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<X count={x} />\n\t\t\t\t\t{y}\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App x={0} />, scratch);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(spy2).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<div><span>0</span><p>0</p></div>');\n\n\t\trender(<App x={0} />, scratch);\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\texpect(spy2).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<div><span>0</span><p>0</p></div>');\n\n\t\trender(<App x={1} />, scratch);\n\t\texpect(spy).toHaveBeenCalledTimes(3);\n\t\texpect(spy2).toHaveBeenCalledTimes(2);\n\t\texpect(scratch.innerHTML).to.equal('<div><span>1</span><p>1</p></div>');\n\n\t\trender(<App x={1} />, scratch);\n\t\texpect(spy2).toHaveBeenCalledTimes(2);\n\t\texpect(scratch.innerHTML).to.equal('<div><span>1</span><p>1</p></div>');\n\n\t\trender(<App x={2} />, scratch);\n\t\texpect(spy2).toHaveBeenCalledTimes(3);\n\t\texpect(scratch.innerHTML).to.equal('<div><span>2</span><p>2</p></div>');\n\t});\n\n\tit('should not commit memoization from a skipped render', () => {\n\t\tconst calls = [];\n\t\tlet set;\n\t\tconst App = () => {\n\t\t\tconst [greeting, setGreeting] = useState('hi');\n\t\t\tset = setGreeting;\n\n\t\t\tconst value = useMemo(() => {\n\t\t\t\tcalls.push('doing memo');\n\t\t\t\treturn greeting;\n\t\t\t}, [greeting]);\n\t\t\tcalls.push(`render ${value}`);\n\n\t\t\tif (greeting === 'bye') {\n\t\t\t\tsetGreeting('hi');\n\t\t\t}\n\n\t\t\treturn <p>{value}</p>;\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\texpect(calls.length).to.equal(2);\n\t\texpect(calls).to.deep.equal(['doing memo', 'render hi']);\n\n\t\tact(() => {\n\t\t\tset('bye');\n\t\t});\n\t\texpect(calls.length).to.equal(6);\n\t\texpect(calls).to.deep.equal([\n\t\t\t'doing memo',\n\t\t\t'render hi',\n\t\t\t'doing memo',\n\t\t\t'render bye',\n\t\t\t'doing memo',\n\t\t\t'render hi'\n\t\t]);\n\t});\n\n\tit('should promote falsy value after a skipped render', () => {\n\t\tlet update;\n\n\t\tfunction App() {\n\t\t\tconst [v, set] = useState(0);\n\t\t\tupdate = set;\n\t\t\tconst res = useMemo(() => 0, [v > 1]);\n\n\t\t\tif (v === 0) {\n\t\t\t\tset(v + 1);\n\t\t\t}\n\t\t\treturn <p>{res}</p>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.textContent).to.equal('0');\n\n\t\tact(() => {\n\t\t\tupdate(v => v + 1);\n\t\t});\n\t\tact(() => {\n\t\t\tupdate(v => v + 1);\n\t\t});\n\n\t\texpect(scratch.textContent).to.equal('0');\n\t});\n\n\tit('should promote undefined value after a skipped render', () => {\n\t\tlet value;\n\t\tfunction Comp({ all }) {\n\t\t\tconst result = (value = useMemo(() => (all ? 5 : undefined), [all]));\n\t\t\treturn result;\n\t\t}\n\t\trender(<Comp all />, scratch);\n\t\texpect(value).to.equal(5);\n\t\trender(<Comp all={false} />, scratch);\n\t\texpect(value).to.equal(undefined);\n\t\trender(<Comp all={false} />, scratch);\n\t\texpect(value).to.equal(undefined);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useReducer.test.jsx",
    "content": "import { setupRerender, act } from 'preact/test-utils';\nimport { createElement, render, createContext } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useReducer, useEffect, useContext } from 'preact/hooks';\n\ndescribe('useReducer', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('rerenders when dispatching an action', () => {\n\t\tconst states = [];\n\t\tlet _dispatch;\n\n\t\tconst initState = { count: 0 };\n\n\t\tfunction reducer(state, action) {\n\t\t\tswitch (action.type) {\n\t\t\t\tcase 'increment':\n\t\t\t\t\treturn { count: state.count + action.by };\n\t\t\t}\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst [state, dispatch] = useReducer(reducer, initState);\n\t\t\t_dispatch = dispatch;\n\t\t\tstates.push(state);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\t_dispatch({ type: 'increment', by: 10 });\n\t\trerender();\n\n\t\texpect(states).to.deep.equal([{ count: 0 }, { count: 10 }]);\n\t});\n\n\tit('can be dispatched by another component', () => {\n\t\tconst initState = { count: 0 };\n\n\t\tfunction reducer(state, action) {\n\t\t\tswitch (action.type) {\n\t\t\t\tcase 'increment':\n\t\t\t\t\treturn { count: state.count + action.by };\n\t\t\t}\n\t\t}\n\n\t\tfunction ReducerComponent() {\n\t\t\tconst [state, dispatch] = useReducer(reducer, initState);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Count: {state.count}</p>\n\t\t\t\t\t<DispatchComponent dispatch={dispatch} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction DispatchComponent(props) {\n\t\t\treturn (\n\t\t\t\t<button onClick={() => props.dispatch({ type: 'increment', by: 10 })}>\n\t\t\t\t\tIncrement\n\t\t\t\t</button>\n\t\t\t);\n\t\t}\n\n\t\trender(<ReducerComponent />, scratch);\n\t\texpect(scratch.textContent).to.include('Count: 0');\n\n\t\tconst button = scratch.querySelector('button');\n\t\tbutton.click();\n\n\t\trerender();\n\t\texpect(scratch.textContent).to.include('Count: 10');\n\t});\n\n\tit('can lazily initialize its state with an action', () => {\n\t\tconst states = [];\n\t\tlet _dispatch;\n\n\t\tfunction init(initialCount) {\n\t\t\treturn { count: initialCount };\n\t\t}\n\n\t\tfunction reducer(state, action) {\n\t\t\tswitch (action.type) {\n\t\t\t\tcase 'increment':\n\t\t\t\t\treturn { count: state.count + action.by };\n\t\t\t}\n\t\t}\n\n\t\tfunction Comp({ initCount }) {\n\t\t\tconst [state, dispatch] = useReducer(reducer, initCount, init);\n\t\t\t_dispatch = dispatch;\n\t\t\tstates.push(state);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp initCount={10} />, scratch);\n\n\t\t_dispatch({ type: 'increment', by: 10 });\n\t\trerender();\n\n\t\texpect(states).to.deep.equal([{ count: 10 }, { count: 20 }]);\n\t});\n\n\tit('provides a stable reference for dispatch', () => {\n\t\tconst dispatches = [];\n\t\tlet _dispatch;\n\n\t\tconst initState = { count: 0 };\n\n\t\tfunction reducer(state, action) {\n\t\t\tswitch (action.type) {\n\t\t\t\tcase 'increment':\n\t\t\t\t\treturn { count: state.count + action.by };\n\t\t\t}\n\t\t}\n\n\t\tfunction Comp() {\n\t\t\tconst [, dispatch] = useReducer(reducer, initState);\n\t\t\t_dispatch = dispatch;\n\t\t\tdispatches.push(dispatch);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\t_dispatch({ type: 'increment', by: 10 });\n\t\trerender();\n\n\t\texpect(dispatches[0]).to.equal(dispatches[1]);\n\t});\n\n\tit('uses latest reducer', () => {\n\t\tconst states = [];\n\t\tlet _dispatch;\n\n\t\tconst initState = { count: 0 };\n\n\t\tfunction Comp({ increment }) {\n\t\t\tconst [state, dispatch] = useReducer(function (state, action) {\n\t\t\t\tswitch (action.type) {\n\t\t\t\t\tcase 'increment':\n\t\t\t\t\t\treturn { count: state.count + increment };\n\t\t\t\t}\n\t\t\t}, initState);\n\t\t\t_dispatch = dispatch;\n\t\t\tstates.push(state);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp increment={10} />, scratch);\n\n\t\trender(<Comp increment={20} />, scratch);\n\n\t\t_dispatch({ type: 'increment' });\n\t\trerender();\n\n\t\texpect(states).to.deep.equal([{ count: 0 }, { count: 0 }, { count: 20 }]);\n\t});\n\n\t// Relates to #2549\n\tit('should not mutate the hookState', () => {\n\t\tconst reducer = (state, action) => ({\n\t\t\t...state,\n\t\t\tinnerMessage: action.payload\n\t\t});\n\n\t\tconst ContextMessage = ({ context }) => {\n\t\t\tconst [{ innerMessage }, dispatch] = useContext(context);\n\t\t\tuseEffect(() => {\n\t\t\t\tdispatch({ payload: 'message' });\n\t\t\t}, []);\n\n\t\t\treturn innerMessage && <p>{innerMessage}</p>;\n\t\t};\n\n\t\tconst Wrapper = ({ children }) => <div>{children}</div>;\n\n\t\tconst badContextDefault = {};\n\t\tconst BadContext = createContext({});\n\n\t\tconst Abstraction = ({ reducer, defaultState, children }) => (\n\t\t\t<BadContext.Provider value={useReducer(reducer, defaultState)}>\n\t\t\t\t<Wrapper>{children}</Wrapper>\n\t\t\t</BadContext.Provider>\n\t\t);\n\n\t\tconst App = () => (\n\t\t\t<Abstraction reducer={reducer} defaultState={badContextDefault}>\n\t\t\t\t<ContextMessage context={BadContext} />\n\t\t\t</Abstraction>\n\t\t);\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<div><p>message</p></div>');\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useRef.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { useRef } from 'preact/hooks';\n\ndescribe('useRef', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('provides a stable reference', () => {\n\t\tconst values = [];\n\n\t\tfunction Comp() {\n\t\t\tconst ref = useRef(1);\n\t\t\tvalues.push(ref.current);\n\t\t\tref.current = 2;\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(values).to.deep.equal([1, 2]);\n\t});\n\n\tit('defaults to undefined', () => {\n\t\tconst values = [];\n\n\t\tfunction Comp() {\n\t\t\tconst ref = useRef();\n\t\t\tvalues.push(ref.current);\n\t\t\tref.current = 2;\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(values).to.deep.equal([undefined, 2]);\n\t});\n});\n"
  },
  {
    "path": "hooks/test/browser/useState.test.jsx",
    "content": "import { setupRerender, act } from 'preact/test-utils';\nimport { createElement, render, createContext, Component } from 'preact';\nimport { vi } from 'vitest';\nimport { useState, useContext, useEffect } from 'preact/hooks';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\n\ndescribe('useState', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tComponent.prototype.shouldComponentUpdate = undefined;\n\t\tteardown(scratch);\n\t});\n\n\tit('serves the same state across render calls', () => {\n\t\tconst stateHistory = [];\n\n\t\tfunction Comp() {\n\t\t\tconst [state] = useState({ a: 1 });\n\t\t\tstateHistory.push(state);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(stateHistory).to.deep.equal([{ a: 1 }, { a: 1 }]);\n\t\texpect(stateHistory[0]).to.equal(stateHistory[1]);\n\t});\n\n\tit('can initialize the state via a function', () => {\n\t\tconst initState = vi.fn(() => 1);\n\n\t\tfunction Comp() {\n\t\t\tuseState(initState);\n\t\t\treturn null;\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\trender(<Comp />, scratch);\n\n\t\texpect(initState).toHaveBeenCalledOnce();\n\t});\n\n\tit('does not rerender on equal state', () => {\n\t\tlet lastState;\n\t\tlet doSetState;\n\n\t\tconst Comp = vi.fn(() => {\n\t\t\tconst [state, setState] = useState(0);\n\t\t\tlastState = state;\n\t\t\tdoSetState = setState;\n\t\t\treturn null;\n\t\t});\n\n\t\trender(<Comp />, scratch);\n\t\texpect(lastState).to.equal(0);\n\t\texpect(Comp).toHaveBeenCalledOnce();\n\n\t\tdoSetState(0);\n\t\trerender();\n\t\texpect(lastState).to.equal(0);\n\t\texpect(Comp).toHaveBeenCalledOnce();\n\n\t\tdoSetState(() => 0);\n\t\trerender();\n\t\texpect(lastState).to.equal(0);\n\t\texpect(Comp).toHaveBeenCalledOnce();\n\t});\n\n\tit('rerenders when setting the state', () => {\n\t\tlet lastState;\n\t\tlet doSetState;\n\n\t\tconst Comp = vi.fn(() => {\n\t\t\tconst [state, setState] = useState(0);\n\t\t\tlastState = state;\n\t\t\tdoSetState = setState;\n\t\t\treturn null;\n\t\t});\n\n\t\trender(<Comp />, scratch);\n\t\texpect(lastState).to.equal(0);\n\t\texpect(Comp).toHaveBeenCalledOnce();\n\n\t\tdoSetState(1);\n\t\trerender();\n\t\texpect(lastState).to.equal(1);\n\t\texpect(Comp).toHaveBeenCalledTimes(2);\n\n\t\t// Updater function style\n\t\tdoSetState(current => current * 10);\n\t\trerender();\n\t\texpect(lastState).to.equal(10);\n\t\texpect(Comp).toHaveBeenCalledTimes(3);\n\t});\n\n\tit('can be set by another component', () => {\n\t\tfunction StateContainer() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Count: {count}</p>\n\t\t\t\t\t<Increment increment={() => setCount(c => c + 10)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tfunction Increment(props) {\n\t\t\treturn <button onClick={props.increment}>Increment</button>;\n\t\t}\n\n\t\trender(<StateContainer />, scratch);\n\t\texpect(scratch.textContent).to.include('Count: 0');\n\n\t\tconst button = scratch.querySelector('button');\n\t\tbutton.click();\n\n\t\trerender();\n\t\texpect(scratch.textContent).to.include('Count: 10');\n\t});\n\n\tit('should correctly initialize', () => {\n\t\tlet scopedThing = 'hi';\n\t\tlet arg;\n\n\t\tfunction useSomething() {\n\t\t\tconst args = useState(setup);\n\t\t\tfunction setup(thing = scopedThing) {\n\t\t\t\targ = thing;\n\t\t\t\treturn thing;\n\t\t\t}\n\t\t\treturn args;\n\t\t}\n\n\t\tconst App = () => {\n\t\t\tconst [state] = useSomething();\n\t\t\treturn <p>{state}</p>;\n\t\t};\n\n\t\trender(<App />, scratch);\n\n\t\texpect(arg).to.equal('hi');\n\t\texpect(scratch.innerHTML).to.equal('<p>hi</p>');\n\t});\n\n\tit('should correctly re-initialize when first run threw an error', () => {\n\t\tlet hasThrown = false;\n\t\tlet setup = vi.fn(() => {\n\t\t\tif (!hasThrown) {\n\t\t\t\thasThrown = true;\n\t\t\t\tthrow new Error('test');\n\t\t\t} else {\n\t\t\t\treturn 'hi';\n\t\t\t}\n\t\t});\n\n\t\tconst App = () => {\n\t\t\tconst state = useState(setup)[0];\n\t\t\treturn <p>{state}</p>;\n\t\t};\n\n\t\texpect(() => render(<App />, scratch)).to.throw('test');\n\t\texpect(setup).toHaveBeenCalledOnce();\n\t\texpect(() => render(<App />, scratch)).not.to.throw();\n\t\texpect(setup).toHaveBeenCalledTimes(2);\n\t\texpect(scratch.innerHTML).to.equal('<p>hi</p>');\n\t});\n\n\tit('should handle queued useState', () => {\n\t\tfunction Message({ message, onClose }) {\n\t\t\tconst [isVisible, setVisible] = useState(Boolean(message));\n\t\t\tconst [prevMessage, setPrevMessage] = useState(message);\n\n\t\t\tif (message !== prevMessage) {\n\t\t\t\tsetPrevMessage(message);\n\t\t\t\tsetVisible(Boolean(message));\n\t\t\t}\n\n\t\t\tif (!isVisible) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn <p onClick={onClose}>{message}</p>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\tconst [message, setMessage] = useState('Click Here!!');\n\t\t\treturn (\n\t\t\t\t<Message\n\t\t\t\t\tonClose={() => {\n\t\t\t\t\t\tsetMessage('');\n\t\t\t\t\t}}\n\t\t\t\t\tmessage={message}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.textContent).to.equal('Click Here!!');\n\t\tconst text = scratch.querySelector('p');\n\t\ttext.click();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should render a second time when the render function updates state', () => {\n\t\tconst calls = [];\n\t\tconst App = () => {\n\t\t\tconst [greeting, setGreeting] = useState('bye');\n\n\t\t\tif (greeting === 'bye') {\n\t\t\t\tsetGreeting('hi');\n\t\t\t}\n\n\t\t\tcalls.push(greeting);\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(2);\n\t\texpect(calls).to.deep.equal(['bye', 'hi']);\n\t\texpect(scratch.textContent).to.equal('hi');\n\t});\n\n\t// https://github.com/preactjs/preact/issues/3669\n\tit('correctly updates with multiple state updates', () => {\n\t\tlet simulateClick;\n\t\tfunction TestWidget() {\n\t\t\tconst [saved, setSaved] = useState(false);\n\t\t\tconst [, setSaving] = useState(false);\n\n\t\t\tsimulateClick = () => {\n\t\t\t\tsetSaving(true);\n\t\t\t\tsetSaved(true);\n\t\t\t\tsetSaving(false);\n\t\t\t};\n\n\t\t\treturn <div>{saved ? 'Saved!' : 'Unsaved!'}</div>;\n\t\t}\n\n\t\trender(<TestWidget />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Unsaved!</div>');\n\n\t\tact(() => {\n\t\t\tsimulateClick();\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.equal('<div>Saved!</div>');\n\t});\n\n\t// https://github.com/preactjs/preact/issues/3674\n\tit('ensure we iterate over all hooks', () => {\n\t\tlet open, close;\n\n\t\tfunction TestWidget() {\n\t\t\tconst [, setCounter] = useState(0);\n\t\t\tconst [isOpen, setOpen] = useState(false);\n\n\t\t\topen = () => {\n\t\t\t\tsetCounter(42);\n\t\t\t\tsetOpen(true);\n\t\t\t};\n\n\t\t\tclose = () => {\n\t\t\t\tsetOpen(false);\n\t\t\t};\n\n\t\t\treturn <div>{isOpen ? 'open' : 'closed'}</div>;\n\t\t}\n\n\t\trender(<TestWidget />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>closed</div>');\n\n\t\tact(() => {\n\t\t\topen();\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.equal('<div>open</div>');\n\n\t\tact(() => {\n\t\t\tclose();\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<div>closed</div>');\n\t});\n\n\tit('does not loop when states are equal after batches', () => {\n\t\tconst renderSpy = vi.fn();\n\t\tconst Context = createContext(null);\n\n\t\tfunction ModalProvider(props) {\n\t\t\tlet [modalCount, setModalCount] = useState(0);\n\t\t\trenderSpy(modalCount);\n\t\t\tlet context = {\n\t\t\t\tmodalCount,\n\t\t\t\taddModal() {\n\t\t\t\t\tsetModalCount(count => count + 1);\n\t\t\t\t},\n\t\t\t\tremoveModal() {\n\t\t\t\t\tsetModalCount(count => count - 1);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\treturn (\n\t\t\t\t<Context.Provider value={context}>{props.children}</Context.Provider>\n\t\t\t);\n\t\t}\n\n\t\tfunction useModal() {\n\t\t\tlet context = useContext(Context);\n\t\t\tuseEffect(() => {\n\t\t\t\tcontext.addModal();\n\t\t\t\treturn () => {\n\t\t\t\t\tcontext.removeModal();\n\t\t\t\t};\n\t\t\t}, [context]);\n\t\t}\n\n\t\tfunction Popover() {\n\t\t\tuseModal();\n\t\t\treturn <div>Popover</div>;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<ModalProvider>\n\t\t\t\t\t<Popover />\n\t\t\t\t</ModalProvider>\n\t\t\t);\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(renderSpy).toHaveBeenCalledTimes(2);\n\t});\n\n\tit('Cancels effect invocations correctly when bailing', () => {\n\t\tconst renderSpy = vi.fn();\n\t\tconst cleanupSpy = vi.fn();\n\t\tconst spy = vi.fn();\n\t\tlet set;\n\n\t\tfunction App() {\n\t\t\tconst [state, setState] = useState('initial');\n\t\t\tset = setState;\n\n\t\t\trenderSpy();\n\t\t\tuseEffect(() => {\n\t\t\t\tspy();\n\t\t\t\treturn () => {\n\t\t\t\t\tcleanupSpy();\n\t\t\t\t};\n\t\t\t});\n\t\t\treturn <p>{state}</p>;\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(renderSpy).toHaveBeenCalledOnce();\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(cleanupSpy).not.toHaveBeenCalled();\n\n\t\tact(() => {\n\t\t\tset('updated');\n\t\t\tset('initial');\n\t\t});\n\n\t\texpect(renderSpy).toHaveBeenCalledTimes(1);\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(cleanupSpy).not.toHaveBeenCalled();\n\t});\n\n\t// see preactjs/preact#3731\n\tit('respects updates initiated from the parent', () => {\n\t\tlet setChild, setParent;\n\t\tconst Child = props => {\n\t\t\tconst [, setState] = useState(false);\n\t\t\tsetChild = setState;\n\t\t\treturn <p>{props.text}</p>;\n\t\t};\n\n\t\tconst Parent = () => {\n\t\t\tconst [state, setState] = useState('hello world');\n\t\t\tsetParent = setState;\n\t\t\treturn <Child text={state} />;\n\t\t};\n\n\t\trender(<Parent />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>hello world</p>');\n\n\t\tsetParent('hello world!!!');\n\t\tsetChild(true);\n\t\tsetChild(false);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>hello world!!!</p>');\n\t});\n\n\tit('should limit rerenders when setting state to NaN', () => {\n\t\tconst calls = [];\n\t\tconst App = ({ i }) => {\n\t\t\tcalls.push('rendering' + i);\n\t\t\tconst [greeting, setGreeting] = useState(0);\n\n\t\t\tif (i === 2) {\n\t\t\t\tsetGreeting(NaN);\n\t\t\t}\n\n\t\t\treturn <p>{greeting}</p>;\n\t\t};\n\n\t\tact(() => {\n\t\t\trender(<App i={1} />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls).to.deep.equal(['rendering1']);\n\n\t\tact(() => {\n\t\t\trender(<App i={2} />, scratch);\n\t\t});\n\t\texpect(calls.length).to.equal(3);\n\t\texpect(calls.slice(1).every(c => c === 'rendering2')).to.equal(true);\n\t});\n\n\tdescribe('Global sCU', () => {\n\t\tlet prevScu;\n\t\tbeforeAll(() => {\n\t\t\tprevScu = Component.prototype.shouldComponentUpdate;\n\t\t\tComponent.prototype.shouldComponentUpdate = () => {\n\t\t\t\treturn true;\n\t\t\t};\n\t\t});\n\n\t\tafterAll(() => {\n\t\t\tComponent.prototype.shouldComponentUpdate = prevScu;\n\t\t});\n\n\t\tit('correctly updates with multiple state updates', () => {\n\t\t\tlet simulateClick;\n\n\t\t\tlet renders = 0;\n\t\t\tfunction TestWidget() {\n\t\t\t\trenders++;\n\t\t\t\tconst [saved, setSaved] = useState(false);\n\n\t\t\t\tsimulateClick = () => {\n\t\t\t\t\tsetSaved(true);\n\t\t\t\t\tsetSaved(false);\n\t\t\t\t};\n\n\t\t\t\treturn <div>{saved ? 'Saved!' : 'Unsaved!'}</div>;\n\t\t\t}\n\n\t\t\trender(<TestWidget />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Unsaved!</div>');\n\t\t\texpect(renders).to.equal(1);\n\n\t\t\tact(() => {\n\t\t\t\tsimulateClick();\n\t\t\t});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Unsaved!</div>');\n\t\t\texpect(renders).to.equal(2);\n\t\t});\n\t});\n\n\tit('Works when we combine strict equality, signals bail and state settling', () => {\n\t\t// In signals we bail when we are using no signals/computeds/....\n\t\tComponent.prototype.shouldComponentUpdate = function (\n\t\t\tnextProps,\n\t\t\tnextState\n\t\t) {\n\t\t\treturn false;\n\t\t};\n\t\tlet setA, setB;\n\n\t\tconst fooContext = createContext();\n\t\tconst barContext = createContext();\n\n\t\tfunction FooProvider({ children }) {\n\t\t\tconst [a, _setA] = useState(0);\n\t\t\tsetA = _setA;\n\t\t\treturn <fooContext.Provider value={a}>{children}</fooContext.Provider>;\n\t\t}\n\n\t\tfunction BarProvider({ children }) {\n\t\t\tconst [b, _setB] = useState(0);\n\t\t\tsetB = _setB;\n\t\t\treturn <barContext.Provider value={b}>{children}</barContext.Provider>;\n\t\t}\n\n\t\tfunction Child() {\n\t\t\tconst a = useContext(fooContext);\n\t\t\tconst b = useContext(barContext);\n\t\t\treturn (\n\t\t\t\t<p>\n\t\t\t\t\t{a}-{b}\n\t\t\t\t</p>\n\t\t\t);\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<FooProvider>\n\t\t\t\t\t<BarProvider>\n\t\t\t\t\t\t<Child />\n\t\t\t\t\t</BarProvider>\n\t\t\t\t</FooProvider>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>0-0</p>');\n\n\t\tact(() => {\n\t\t\t// We update A first so that we have a top-down render going on\n\t\t\tsetA(1);\n\t\t\t// The update will bail at B, we don't want sCU to run because\n\t\t\t// else we risk the state's _nextValue being settled too early\n\t\t\t// and thus applying the update too early and bailing on the subsequent\n\t\t\t// render due to the values already being applied.\n\t\t\tsetB(1);\n\t\t});\n\t\texpect(scratch.innerHTML).to.equal('<p>1-1</p>');\n\t});\n});\n"
  },
  {
    "path": "jsconfig-lint.json",
    "content": "{\n  \"extends\": \"./jsconfig.json\",\n  \"compilerOptions\": {\n    // More modern settings as Vite & Vitest require them and TS doesn't allow\n    // silencing errors from `node_modules` alone.\n    \"moduleResolution\": \"Node16\",\n    \"target\": \"ES2015\",\n    \"module\": \"Node16\",\n    \"checkJs\": false\n  },\n  \"include\": [\n    \"src/**/*\",\n    \"hooks/src/**/*\",\n    \"compat/**/*.d.ts\",\n    \"jsx-runtime/**/*.d.ts\",\n    \"types/**/*.d.ts\"\n  ],\n  \"exclude\": [\"**/node_modules/**\", \"node_modules\"]\n}\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"checkJs\": true,\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"createElement\",\n    \"jsxFragmentFactory\": \"Fragment\",\n    \"lib\": [\"dom\", \"es5\"],\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"paths\": {\n      \"preact\": [\".\"],\n      \"preact/*\": [\"./*\"]\n    },\n    \"target\": \"es5\",\n    \"noEmit\": true,\n    \"skipLibCheck\": false,\n    \"types\": [\"vitest/globals\"]\n  },\n  \"exclude\": [\"**/node_modules/**\", \"**/dist/**\", \"coverage\", \"demo\"]\n}\n"
  },
  {
    "path": "jsx-runtime/LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015-present Jason Miller\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": "jsx-runtime/mangle.json",
    "content": "{\n  \"help\": {\n    \"what is this file?\": \"It controls protected/private property mangling so that minified builds have consistent property names.\",\n    \"why are there duplicate minified properties?\": \"Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size.\"\n  },\n  \"minify\": {\n    \"mangle\": {\n      \"properties\": {\n        \"regex\": \"^_[^_]\",\n        \"reserved\": [\n          \"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\",\n          \"__REACT_DEVTOOLS_GLOBAL_HOOK__\",\n          \"__PREACT_DEVTOOLS__\",\n          \"_renderers\",\n          \"__source\",\n          \"__self\"\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "jsx-runtime/package.json",
    "content": "{\n  \"name\": \"jsx-runtime\",\n  \"amdName\": \"jsxRuntime\",\n  \"private\": true,\n  \"description\": \"Preact JSX runtime\",\n  \"main\": \"dist/jsxRuntime.js\",\n  \"module\": \"dist/jsxRuntime.mjs\",\n  \"umd:main\": \"dist/jsxRuntime.umd.js\",\n  \"source\": \"src/index.js\",\n  \"types\": \"src/index.d.ts\",\n  \"license\": \"MIT\",\n  \"mangle\": {\n    \"regex\": \"^_\"\n  },\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "jsx-runtime/src/index.d.ts",
    "content": "export { Fragment } from '../../src/index';\nimport {\n\tComponentType,\n\tComponentChild,\n\tComponentChildren,\n\tVNode,\n\tAttributes,\n\tHTMLAttributes,\n\tSVGAttributes\n} from '../../src/index';\nimport { JSXInternal } from '../../src/jsx';\n\nexport function jsx(\n\ttype: string,\n\tprops: HTMLAttributes &\n\t\tSVGAttributes &\n\t\tRecord<string, any> & { children?: ComponentChild },\n\tkey?: string\n): VNode<any>;\nexport function jsx<P>(\n\ttype: ComponentType<P>,\n\tprops: Attributes & P & { children?: ComponentChild },\n\tkey?: string\n): VNode<any>;\n\nexport function jsxs(\n\ttype: string,\n\tprops: HTMLAttributes &\n\t\tSVGAttributes &\n\t\tRecord<string, any> & { children?: ComponentChild[] },\n\tkey?: string\n): VNode<any>;\nexport function jsxs<P>(\n\ttype: ComponentType<P>,\n\tprops: Attributes & P & { children?: ComponentChild[] },\n\tkey?: string\n): VNode<any>;\n\nexport function jsxDEV(\n\ttype: string,\n\tprops: HTMLAttributes &\n\t\tSVGAttributes &\n\t\tRecord<string, any> & { children?: ComponentChildren },\n\tkey?: string\n): VNode<any>;\nexport function jsxDEV<P>(\n\ttype: ComponentType<P>,\n\tprops: Attributes & P & { children?: ComponentChildren },\n\tkey?: string\n): VNode<any>;\n\n// These are not expected to be used manually, but by a JSX transform\nexport function jsxTemplate(\n\ttemplate: string[],\n\t...expressions: any[]\n): VNode<any>;\nexport function jsxAttr(name: string, value: any): string | null;\nexport function jsxEscape<T>(\n\tvalue: T\n): string | null | VNode<any> | Array<string | null | VNode>;\n\nexport { JSXInternal as JSX };\n"
  },
  {
    "path": "jsx-runtime/src/index.js",
    "content": "import { options, Fragment } from 'preact';\nimport { encodeEntities } from './utils';\n\nlet vnodeId = 0;\n\nconst isArray = Array.isArray;\n\n/**\n * @fileoverview\n * This file exports various methods that implement Babel's \"automatic\" JSX runtime API:\n * - jsx(type, props, key)\n * - jsxs(type, props, key)\n * - jsxDEV(type, props, key, __source, __self)\n *\n * The implementation of createVNode here is optimized for performance.\n * Benchmarks: https://esbench.com/bench/5f6b54a0b4632100a7dcd2b3\n */\n\n/**\n * JSX.Element factory used by Babel's {runtime:\"automatic\"} JSX transform\n * @param {import('../../src/internal').VNode['type']} type\n * @param {import('preact').VNode['props']} props\n * @param {import('preact').VNode['key']} [key]\n * @param {unknown} [isStaticChildren]\n * @param {unknown} [__source]\n * @param {unknown} [__self]\n */\nfunction createVNode(type, props, key, isStaticChildren, __source, __self) {\n\tif (!props) props = {};\n\t// We'll want to preserve `ref` in props to get rid of the need for\n\t// forwardRef components in the future, but that should happen via\n\t// a separate PR.\n\tlet normalizedProps = props,\n\t\tref,\n\t\ti;\n\n\tif ('ref' in normalizedProps && typeof type != 'function') {\n\t\tnormalizedProps = {};\n\t\tfor (i in props) {\n\t\t\tif (i == 'ref') {\n\t\t\t\tref = props[i];\n\t\t\t} else {\n\t\t\t\tnormalizedProps[i] = props[i];\n\t\t\t}\n\t\t}\n\t}\n\n\t/** @type {import('../../src/internal').VNode & { __source: any; __self: any }} */\n\tconst vnode = {\n\t\ttype,\n\t\tprops: normalizedProps,\n\t\tkey,\n\t\tref,\n\t\t_children: null,\n\t\t_parent: null,\n\t\t_depth: 0,\n\t\t_dom: null,\n\t\t_component: null,\n\t\tconstructor: undefined,\n\t\t_original: --vnodeId,\n\t\t_index: -1,\n\t\t_flags: 0,\n\t\t__source,\n\t\t__self\n\t};\n\n\tif (options.vnode) options.vnode(vnode);\n\treturn vnode;\n}\n\n/**\n * Create a template vnode. This function is not expected to be\n * used directly, but rather through a precompile JSX transform\n * @param {string[]} templates\n * @param  {Array<string | null | import('preact').VNode>} exprs\n * @returns {import('preact').VNode}\n */\nfunction jsxTemplate(templates, ...exprs) {\n\tconst vnode = createVNode(Fragment, { tpl: templates, exprs });\n\t// Bypass render to string top level Fragment optimization\n\t// @ts-ignore\n\tvnode.key = vnode._vnode;\n\treturn vnode;\n}\n\nconst JS_TO_CSS = {};\nconst CSS_REGEX = /[A-Z]/g;\n\n/**\n * Unwrap potential signals.\n * @param {*} value\n * @returns {*}\n */\nfunction normalizeAttrValue(value) {\n\treturn value !== null &&\n\t\ttypeof value === 'object' &&\n\t\ttypeof value.valueOf === 'function'\n\t\t? value.valueOf()\n\t\t: value;\n}\n\n/**\n * Serialize an HTML attribute to a string. This function is not\n * expected to be used directly, but rather through a precompile\n * JSX transform\n * @param {string} name The attribute name\n * @param {*} value The attribute value\n * @returns {string}\n */\nfunction jsxAttr(name, value) {\n\tif (options.attr) {\n\t\tconst result = options.attr(name, value);\n\t\tif (typeof result === 'string') return result;\n\t}\n\n\tvalue = normalizeAttrValue(value);\n\n\tif (name === 'ref' || name === 'key') return '';\n\tif (name === 'style' && typeof value === 'object') {\n\t\tlet str = '';\n\t\tfor (let prop in value) {\n\t\t\tlet val = value[prop];\n\t\t\tif (val != null && val !== '') {\n\t\t\t\tconst name =\n\t\t\t\t\tprop[0] == '-'\n\t\t\t\t\t\t? prop\n\t\t\t\t\t\t: JS_TO_CSS[prop] ||\n\t\t\t\t\t\t\t(JS_TO_CSS[prop] = prop.replace(CSS_REGEX, '-$&').toLowerCase());\n\n\t\t\t\tstr = str + name + ':' + val + ';';\n\t\t\t}\n\t\t}\n\t\treturn name + '=\"' + encodeEntities(str) + '\"';\n\t}\n\n\tif (\n\t\tvalue == null ||\n\t\tvalue === false ||\n\t\ttypeof value === 'function' ||\n\t\ttypeof value === 'object'\n\t) {\n\t\treturn '';\n\t} else if (value === true) return name;\n\n\treturn name + '=\"' + encodeEntities('' + value) + '\"';\n}\n\n/**\n * Escape a dynamic child passed to `jsxTemplate`. This function\n * is not expected to be used directly, but rather through a\n * precompile JSX transform\n * @param {*} value\n * @returns {string | null | import('preact').VNode | Array<string | null | import('preact').VNode>}\n */\nfunction jsxEscape(value) {\n\tif (\n\t\tvalue == null ||\n\t\ttypeof value === 'boolean' ||\n\t\ttypeof value === 'function'\n\t) {\n\t\treturn null;\n\t}\n\n\tif (typeof value === 'object') {\n\t\t// Check for VNode\n\t\tif (value.constructor === undefined) return value;\n\n\t\tif (isArray(value)) {\n\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\tvalue[i] = jsxEscape(value[i]);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t}\n\n\treturn encodeEntities('' + value);\n}\n\nexport {\n\tcreateVNode as jsx,\n\tcreateVNode as jsxs,\n\tcreateVNode as jsxDEV,\n\tFragment,\n\t// precompiled JSX transform\n\tjsxTemplate,\n\tjsxAttr,\n\tjsxEscape\n};\n"
  },
  {
    "path": "jsx-runtime/src/utils.js",
    "content": "const ENCODED_ENTITIES = /[\"&<]/;\n\n/** @param {string} str */\nexport function encodeEntities(str) {\n\t// Skip all work for strings with no entities needing encoding:\n\tif (str.length === 0 || ENCODED_ENTITIES.test(str) === false) return str;\n\n\tlet last = 0,\n\t\ti = 0,\n\t\tout = '',\n\t\tch = '';\n\n\t// Seek forward in str until the next entity char:\n\tfor (; i < str.length; i++) {\n\t\tswitch (str.charCodeAt(i)) {\n\t\t\tcase 34:\n\t\t\t\tch = '&quot;';\n\t\t\t\tbreak;\n\t\t\tcase 38:\n\t\t\t\tch = '&amp;';\n\t\t\t\tbreak;\n\t\t\tcase 60:\n\t\t\t\tch = '&lt;';\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tcontinue;\n\t\t}\n\t\t// Append skipped/buffered characters and the encoded entity:\n\t\tif (i !== last) out += str.slice(last, i);\n\t\tout += ch;\n\t\t// Start the next seek/buffer after the entity's offset:\n\t\tlast = i + 1;\n\t}\n\tif (i !== last) out += str.slice(last, i);\n\treturn out;\n}\n"
  },
  {
    "path": "jsx-runtime/test/browser/jsx-runtime.test.js",
    "content": "import { Component, createElement, createRef, options } from 'preact';\nimport {\n\tjsx,\n\tjsxs,\n\tjsxDEV,\n\tFragment,\n\tjsxAttr,\n\tjsxTemplate,\n\tjsxEscape\n} from 'preact/jsx-runtime';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { encodeEntities } from '../../src/utils';\nimport { vi } from 'vitest';\n\nfunction createSignal(value) {\n\treturn {\n\t\tvalue,\n\t\tpeek() {\n\t\t\treturn value;\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn () => {};\n\t\t},\n\t\tvalueOf() {\n\t\t\treturn value;\n\t\t},\n\t\ttoString() {\n\t\t\treturn String(value);\n\t\t}\n\t};\n}\n\ndescribe('Babel jsx/jsxDEV', () => {\n\tlet scratch;\n\tlet prevVNodeOption;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\tprevVNodeOption = options.vnode;\n\t});\n\n\tafterEach(() => {\n\t\toptions.vnode = prevVNodeOption;\n\t\tteardown(scratch);\n\t});\n\n\tit('should have needed exports', () => {\n\t\texpect(typeof jsx).to.equal('function');\n\t\texpect(typeof jsxs).to.equal('function');\n\t\texpect(typeof jsxDEV).to.equal('function');\n\t\texpect(typeof Fragment).to.equal('function');\n\t});\n\n\tit('should keep ref in props', () => {\n\t\tconst ref = () => null;\n\t\tconst props = { ref };\n\t\tconst vnode = jsx('div', props);\n\t\texpect(vnode.ref).to.equal(ref);\n\t\texpect(vnode.props).to.not.equal(props);\n\t});\n\n\tit('should not copy props wen there is no ref in props', () => {\n\t\tconst props = { x: 'y' };\n\t\tconst vnode = jsx('div', props);\n\t\texpect(vnode.props).to.equal(props);\n\t});\n\n\tit('should add keys', () => {\n\t\tconst vnode = jsx('div', null, 'foo');\n\t\texpect(vnode.key).to.equal('foo');\n\t});\n\n\tit('should set __source and __self', () => {\n\t\tconst vnode = jsx('div', { class: 'foo' }, 'key', false, 'source', 'self');\n\t\texpect(vnode.__source).to.equal('source');\n\t\texpect(vnode.__self).to.equal('self');\n\t});\n\n\tit('should return a vnode like createElement', () => {\n\t\tconst elementVNode = createElement('div', {\n\t\t\tclass: 'foo',\n\t\t\tkey: 'key'\n\t\t});\n\t\tconst jsxVNode = jsx('div', { class: 'foo' }, 'key');\n\t\tdelete jsxVNode.__self;\n\t\tdelete jsxVNode.__source;\n\t\tdelete jsxVNode._original;\n\t\tdelete elementVNode._original;\n\t\texpect(jsxVNode).to.deep.equal(elementVNode);\n\t});\n\n\t// #2839\n\tit('should remove ref from props', () => {\n\t\tconst ref = createRef();\n\t\tconst vnode = jsx('div', { ref }, null);\n\t\texpect(vnode.props).to.deep.equal({});\n\t\texpect(vnode.ref).to.equal(ref);\n\t});\n\n\tit('should call options.vnode with the vnode', () => {\n\t\toptions.vnode = vi.fn();\n\t\tconst vnode = jsx('div', { class: 'foo' }, 'key');\n\t\texpect(options.vnode).toHaveBeenCalledWith(vnode);\n\t});\n});\n\ndescribe('encodeEntities', () => {\n\tit('should encode', () => {\n\t\texpect(encodeEntities(\"&<'\")).to.equal(\"&amp;&lt;'\");\n\t});\n});\n\ndescribe('precompiled JSX', () => {\n\tdescribe('jsxAttr', () => {\n\t\tbeforeEach(() => {\n\t\t\toptions.attr = undefined;\n\t\t});\n\n\t\tafterEach(() => {\n\t\t\toptions.attr = undefined;\n\t\t});\n\n\t\tit('should render simple values', () => {\n\t\t\texpect(jsxAttr('foo', 'bar')).to.equal('foo=\"bar\"');\n\t\t});\n\n\t\tit('should render boolean values', () => {\n\t\t\texpect(jsxAttr('foo', true)).to.equal('foo');\n\t\t\texpect(jsxAttr('foo', false)).to.equal('');\n\t\t});\n\n\t\tit('should ignore invalid values', () => {\n\t\t\texpect(jsxAttr('foo', false)).to.equal('');\n\t\t\texpect(jsxAttr('foo', null)).to.equal('');\n\t\t\texpect(jsxAttr('foo', undefined)).to.equal('');\n\t\t\texpect(jsxAttr('foo', () => null)).to.equal('');\n\t\t\texpect(jsxAttr('foo', [])).to.equal('');\n\t\t\texpect(jsxAttr('key', 'foo')).to.equal('');\n\t\t\texpect(jsxAttr('ref', 'foo')).to.equal('');\n\t\t});\n\n\t\tit('should escape values', () => {\n\t\t\texpect(jsxAttr('foo', \"&<'\")).to.equal('foo=\"&amp;&lt;\\'\"');\n\t\t\texpect(jsxAttr('style', { foo: `\"&<'\"` })).to.equal(\n\t\t\t\t'style=\"foo:&quot;&amp;&lt;\\'&quot;;\"'\n\t\t\t);\n\t\t});\n\n\t\tit('should support signals', () => {\n\t\t\tconst sig = createSignal(`&<'\"`);\n\t\t\texpect(jsxAttr('foo', sig)).to.equal(`foo=\"&amp;&lt;'&quot;\"`);\n\t\t\texpect(jsxAttr('style', sig)).to.equal(`style=\"&amp;&lt;'&quot;\"`);\n\t\t});\n\n\t\tit('should call options.attr()', () => {\n\t\t\toptions.attr = (name, value) => {\n\t\t\t\treturn `data-${name}=\"foo${value}\"`;\n\t\t\t};\n\n\t\t\texpect(jsxAttr('foo', 'bar')).to.equal('data-foo=\"foobar\"');\n\t\t});\n\n\t\tit('should serialize style object', () => {\n\t\t\texpect(jsxAttr('style', { padding: '3px' })).to.equal(\n\t\t\t\t'style=\"padding:3px;\"'\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('jsxTemplate', () => {\n\t\tit('should construct basic template vnode', () => {\n\t\t\tconst tpl = [`<div>foo</div>`];\n\t\t\tconst vnode = jsxTemplate(tpl);\n\t\t\texpect(vnode.props.tpl).to.equal(tpl);\n\t\t\texpect(vnode.type).to.equal(Fragment);\n\t\t\texpect(vnode.key).not.to.equal(null);\n\t\t});\n\n\t\tit('should constructe template vnode with expressions', () => {\n\t\t\tconst tpl = [`<div>foo`, '</div>'];\n\t\t\tconst vnode = jsxTemplate(tpl, 'bar');\n\t\t\texpect(vnode.props.tpl).to.equal(tpl);\n\t\t\texpect(vnode.props.exprs).to.deep.equal(['bar']);\n\t\t\texpect(vnode.type).to.equal(Fragment);\n\t\t\texpect(vnode.key).not.to.equal(null);\n\t\t});\n\t});\n\n\tdescribe('jsxEscape', () => {\n\t\tit('should escape string children', () => {\n\t\t\texpect(jsxEscape('foo')).to.equal('foo');\n\t\t\texpect(jsxEscape(2)).to.equal('2');\n\t\t\texpect(jsxEscape('&\"<')).to.equal('&amp;&quot;&lt;');\n\t\t\texpect(jsxEscape(null)).to.equal(null);\n\t\t\texpect(jsxEscape(undefined)).to.equal(null);\n\t\t\texpect(jsxEscape(true)).to.equal(null);\n\t\t\texpect(jsxEscape(false)).to.equal(null);\n\t\t});\n\n\t\tit(\"should leave VNode's as is\", () => {\n\t\t\tconst vnode = jsx('div', null);\n\t\t\texpect(jsxEscape(vnode)).to.equal(vnode);\n\t\t});\n\n\t\tit('should escape arrays', () => {\n\t\t\tconst vnode = jsx('div', null);\n\t\t\texpect(\n\t\t\t\tjsxEscape([vnode, 'foo&\"<', null, undefined, true, false, 2, 'foo'])\n\t\t\t).to.deep.equal([\n\t\t\t\tvnode,\n\t\t\t\t'foo&amp;&quot;&lt;',\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\t'2',\n\t\t\t\t'foo'\n\t\t\t]);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "mangle.json",
    "content": "{\n  \"help\": {\n    \"what is this file?\": \"It controls protected/private property mangling so that minified builds have consistent property names.\",\n    \"why are there duplicate minified properties?\": \"Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size.\"\n  },\n  \"minify\": {\n    \"mangle\": {\n      \"properties\": {\n        \"regex\": \"^_[^_]\",\n        \"reserved\": [\n          \"__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\",\n          \"__REACT_DEVTOOLS_GLOBAL_HOOK__\",\n          \"__PREACT_DEVTOOLS__\",\n          \"_renderers\",\n          \"__source\",\n          \"__self\"\n        ]\n      }\n    },\n    \"compress\": {\n      \"hoist_vars\": true,\n      \"reduce_funcs\": false\n    }\n  },\n  \"props\": {\n    \"cname\": 6,\n    \"props\": {\n      \"$_hasScuFromHooks\": \"__f\",\n      \"$_listeners\": \"__l\",\n      \"$_cleanup\": \"__c\",\n      \"$__hooks\": \"__H\",\n      \"$_hydrationMismatch\": \"__m\",\n      \"$_list\": \"__\",\n      \"$_pendingEffects\": \"__h\",\n      \"$_value\": \"__\",\n      \"$_nextValue\": \"__N\",\n      \"$_original\": \"__v\",\n      \"$_args\": \"__H\",\n      \"$_factory\": \"__h\",\n      \"$_depth\": \"__b\",\n      \"$_mask\": \"__m\",\n      \"$_detachOnNextRender\": \"__b\",\n      \"$_excess\": \"__z\",\n      \"$_nextState\": \"__s\",\n      \"$_renderCallbacks\": \"__h\",\n      \"$_stateCallbacks\": \"_sb\",\n      \"$_vnode\": \"__v\",\n      \"$_children\": \"__k\",\n      \"$_pendingSuspensionCount\": \"__u\",\n      \"$_childDidSuspend\": \"__c\",\n      \"$_unmounted\": \"__z\",\n      \"$_onResolve\": \"__R\",\n      \"$_suspended\": \"__a\",\n      \"$_dom\": \"__e\",\n      \"$_component\": \"__c\",\n      \"$_index\": \"__i\",\n      \"$_flags\": \"__u\",\n      \"$__html\": \"__html\",\n      \"$_parent\": \"__\",\n      \"$_globalContext\": \"__n\",\n      \"$_context\": \"c\",\n      \"$_defaultValue\": \"__\",\n      \"$_id\": \"__c\",\n      \"$_contextRef\": \"__l\",\n      \"$_parentDom\": \"__P\",\n      \"$_originalParentDom\": \"__O\",\n      \"$_prevState\": \"__u\",\n      \"$_root\": \"__\",\n      \"$_diff\": \"__b\",\n      \"$_commit\": \"__c\",\n      \"$_addHookName\": \"__a\",\n      \"$_render\": \"__r\",\n      \"$_hook\": \"__h\",\n      \"$_catchError\": \"__e\",\n      \"$_unmount\": \"__u\",\n      \"$_owner\": \"__o\",\n      \"$_skipEffects\": \"__s\",\n      \"$_forwarded\": \"__f\",\n      \"$_isSuspended\": \"__i\",\n      \"$_bits\": \"__g\"\n    }\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"preact\",\n  \"amdName\": \"preact\",\n  \"version\": \"11.0.0-beta.1\",\n  \"private\": false,\n  \"description\": \"Fast 4kb React-compatible Virtual DOM library.\",\n  \"main\": \"dist/preact.js\",\n  \"module\": \"dist/preact.mjs\",\n  \"umd:main\": \"dist/preact.umd.js\",\n  \"source\": \"src/index.js\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./src/index.d.ts\",\n      \"module\": \"./dist/preact.mjs\",\n      \"umd\": \"./dist/preact.umd.js\",\n      \"import\": \"./dist/preact.mjs\",\n      \"require\": \"./dist/preact.js\"\n    },\n    \"./compat\": {\n      \"types\": \"./compat/src/index.d.ts\",\n      \"module\": \"./compat/dist/compat.mjs\",\n      \"umd\": \"./compat/dist/compat.umd.js\",\n      \"import\": \"./compat/dist/compat.mjs\",\n      \"require\": \"./compat/dist/compat.js\"\n    },\n    \"./debug\": {\n      \"types\": \"./debug/src/index.d.ts\",\n      \"module\": \"./debug/dist/debug.mjs\",\n      \"umd\": \"./debug/dist/debug.umd.js\",\n      \"import\": \"./debug/dist/debug.mjs\",\n      \"require\": \"./debug/dist/debug.js\"\n    },\n    \"./devtools\": {\n      \"types\": \"./devtools/src/index.d.ts\",\n      \"module\": \"./devtools/dist/devtools.mjs\",\n      \"umd\": \"./devtools/dist/devtools.umd.js\",\n      \"import\": \"./devtools/dist/devtools.mjs\",\n      \"require\": \"./devtools/dist/devtools.js\"\n    },\n    \"./hooks\": {\n      \"types\": \"./hooks/src/index.d.ts\",\n      \"module\": \"./hooks/dist/hooks.mjs\",\n      \"umd\": \"./hooks/dist/hooks.umd.js\",\n      \"import\": \"./hooks/dist/hooks.mjs\",\n      \"require\": \"./hooks/dist/hooks.js\"\n    },\n    \"./test-utils\": {\n      \"types\": \"./test-utils/src/index.d.ts\",\n      \"module\": \"./test-utils/dist/testUtils.mjs\",\n      \"umd\": \"./test-utils/dist/testUtils.umd.js\",\n      \"import\": \"./test-utils/dist/testUtils.mjs\",\n      \"require\": \"./test-utils/dist/testUtils.js\"\n    },\n    \"./compat/test-utils\": {\n      \"types\": \"./test-utils/src/index.d.ts\",\n      \"module\": \"./test-utils/dist/testUtils.mjs\",\n      \"umd\": \"./test-utils/dist/testUtils.umd.js\",\n      \"import\": \"./test-utils/dist/testUtils.mjs\",\n      \"require\": \"./test-utils/dist/testUtils.js\"\n    },\n    \"./jsx-runtime\": {\n      \"types\": \"./jsx-runtime/src/index.d.ts\",\n      \"module\": \"./jsx-runtime/dist/jsxRuntime.mjs\",\n      \"umd\": \"./jsx-runtime/dist/jsxRuntime.umd.js\",\n      \"import\": \"./jsx-runtime/dist/jsxRuntime.mjs\",\n      \"require\": \"./jsx-runtime/dist/jsxRuntime.js\"\n    },\n    \"./jsx-dev-runtime\": {\n      \"types\": \"./jsx-runtime/src/index.d.ts\",\n      \"module\": \"./jsx-runtime/dist/jsxRuntime.mjs\",\n      \"umd\": \"./jsx-runtime/dist/jsxRuntime.umd.js\",\n      \"import\": \"./jsx-runtime/dist/jsxRuntime.mjs\",\n      \"require\": \"./jsx-runtime/dist/jsxRuntime.js\"\n    },\n    \"./compat/client\": {\n      \"types\": \"./compat/client.d.ts\",\n      \"import\": \"./compat/client.mjs\",\n      \"require\": \"./compat/client.js\"\n    },\n    \"./compat/server\": {\n      \"types\": \"./compat/server.d.ts\",\n      \"browser\": \"./compat/server.browser.js\",\n      \"import\": \"./compat/server.mjs\",\n      \"require\": \"./compat/server.js\"\n    },\n    \"./compat/server.browser\": {\n      \"types\": \"./compat/server.d.ts\",\n      \"default\": \"./compat/server.browser.js\"\n    },\n    \"./compat/jsx-runtime\": {\n      \"types\": \"./jsx-runtime/src/index.d.ts\",\n      \"import\": \"./compat/jsx-runtime.mjs\",\n      \"require\": \"./compat/jsx-runtime.js\"\n    },\n    \"./compat/jsx-dev-runtime\": {\n      \"types\": \"./jsx-runtime/src/index.d.ts\",\n      \"import\": \"./compat/jsx-dev-runtime.mjs\",\n      \"require\": \"./compat/jsx-dev-runtime.js\"\n    },\n    \"./compat/scheduler\": {\n      \"types\": \"./compat/scheduler.d.ts\",\n      \"import\": \"./compat/scheduler.mjs\",\n      \"require\": \"./compat/scheduler.js\"\n    },\n    \"./package.json\": \"./package.json\",\n    \"./compat/package.json\": \"./compat/package.json\",\n    \"./debug/package.json\": \"./debug/package.json\",\n    \"./devtools/package.json\": \"./devtools/package.json\",\n    \"./hooks/package.json\": \"./hooks/package.json\",\n    \"./test-utils/package.json\": \"./test-utils/package.json\",\n    \"./jsx-runtime/package.json\": \"./jsx-runtime/package.json\"\n  },\n  \"license\": \"MIT\",\n  \"funding\": {\n    \"type\": \"opencollective\",\n    \"url\": \"https://opencollective.com/preact\"\n  },\n  \"types\": \"src/index.d.ts\",\n  \"scripts\": {\n    \"prepare\": \"husky && npm run test:install && run-s build\",\n    \"build\": \"npm-run-all --parallel 'build:*'\",\n    \"build:core\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd\",\n    \"build:debug\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd --cwd debug\",\n    \"build:devtools\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd --cwd devtools\",\n    \"build:hooks\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd --cwd hooks\",\n    \"build:test-utils\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd --cwd test-utils\",\n    \"build:compat\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd --cwd compat --globals 'preact/hooks=preactHooks'\",\n    \"build:jsx\": \"microbundle build --raw --no-generateTypes -f cjs,esm,umd --cwd jsx-runtime\",\n    \"postbuild\": \"node ./config/compat-entries.js\",\n    \"dev\": \"microbundle watch --raw --no-generateTypes --format cjs\",\n    \"dev:hooks\": \"microbundle watch --raw --no-generateTypes --format cjs --cwd hooks\",\n    \"dev:compat\": \"microbundle watch --raw --no-generateTypes --format cjs --cwd compat --globals 'preact/hooks=preactHooks'\",\n    \"test\": \"npm-run-all build lint test:unit\",\n    \"test:install\": \"playwright install chromium\",\n    \"test:unit\": \"run-p test:vitest:min test:ts\",\n    \"test:vitest\": \"cross-env COVERAGE=true vitest run\",\n    \"test:vitest:min\": \"cross-env MINIFY=true vitest run\",\n    \"test:vitest:watch\": \"vitest\",\n    \"test:ts\": \"run-p 'test:ts:*'\",\n    \"test:ts:core\": \"tsc -p test/ts/\",\n    \"test:ts:compat\": \"tsc -p compat/test/ts/\",\n    \"lint\": \"run-s oxlint tsc\",\n    \"tsc\": \"tsc -p jsconfig-lint.json\",\n    \"oxlint\": \"oxlint src test/browser test/node test/shared debug compat hooks test-utils\",\n    \"format\": \"biome format --write .\",\n    \"format:check\": \"biome format .\"\n  },\n  \"nano-staged\": {\n    \"**/*.{js,jsx,mjs,cjs,ts,tsx,yml,json,html,md,css,scss}\": [\n      \"biome format --write --no-errors-on-unmatched\"\n    ]\n  },\n  \"files\": [\n    \"src\",\n    \"dist\",\n    \"compat/dist\",\n    \"compat/src\",\n    \"compat/client.d.ts\",\n    \"compat/client.js\",\n    \"compat/client.mjs\",\n    \"compat/server.d.ts\",\n    \"compat/server.browser.js\",\n    \"compat/server.js\",\n    \"compat/server.mjs\",\n    \"compat/scheduler.d.ts\",\n    \"compat/scheduler.js\",\n    \"compat/scheduler.mjs\",\n    \"compat/test-utils.js\",\n    \"compat/test-utils.mjs\",\n    \"compat/jsx-runtime.js\",\n    \"compat/jsx-runtime.mjs\",\n    \"compat/jsx-dev-runtime.js\",\n    \"compat/jsx-dev-runtime.mjs\",\n    \"compat/package.json\",\n    \"debug/dist\",\n    \"debug/src\",\n    \"debug/package.json\",\n    \"devtools/dist\",\n    \"devtools/src\",\n    \"devtools/package.json\",\n    \"hooks/dist\",\n    \"hooks/src\",\n    \"hooks/package.json\",\n    \"jsx-runtime/dist\",\n    \"jsx-runtime/src\",\n    \"jsx-runtime/package.json\",\n    \"test-utils/src\",\n    \"test-utils/package.json\",\n    \"test-utils/dist\"\n  ],\n  \"keywords\": [\n    \"preact\",\n    \"react\",\n    \"ui\",\n    \"user interface\",\n    \"virtual dom\",\n    \"vdom\",\n    \"components\",\n    \"dom diff\",\n    \"front-end\",\n    \"framework\"\n  ],\n  \"authors\": [\n    \"The Preact Authors (https://github.com/preactjs/preact/contributors)\"\n  ],\n  \"repository\": \"preactjs/preact\",\n  \"bugs\": \"https://github.com/preactjs/preact/issues\",\n  \"homepage\": \"https://preactjs.com\",\n  \"devDependencies\": {\n    \"@actions/github\": \"^6.0.1\",\n    \"@actions/glob\": \"^0.5.0\",\n    \"@babel/core\": \"^7.28.0\",\n    \"@babel/plugin-transform-react-jsx\": \"^7.27.1\",\n    \"@babel/plugin-transform-react-jsx-source\": \"^7.27.1\",\n    \"@babel/preset-env\": \"^7.28.0\",\n    \"@babel/register\": \"^7.27.1\",\n    \"@biomejs/biome\": \"^2.1.2\",\n    \"@types/node\": \"^18.19.87\",\n    \"@vitest/browser\": \"^3.2.4\",\n    \"@vitest/coverage-v8\": \"^3.2.4\",\n    \"babel-plugin-transform-rename-properties\": \"0.1.0\",\n    \"chai\": \"^6.2.2\",\n    \"coveralls\": \"^3.1.1\",\n    \"cross-env\": \"^7.0.3\",\n    \"errorstacks\": \"^2.4.1\",\n    \"esbuild\": \"^0.25.8\",\n    \"husky\": \"^9.1.7\",\n    \"kolorist\": \"^1.8.0\",\n    \"microbundle\": \"^0.15.1\",\n    \"npm-run-all2\": \"^7.0.0\",\n    \"oxlint\": \"^1.8.0\",\n    \"playwright\": \"^1.54.1\",\n    \"preact-render-to-string\": \"^6.5.0\",\n    \"prop-types\": \"^15.8.1\",\n    \"sade\": \"^1.8.1\",\n    \"terser\": \"5.16.0\",\n    \"typescript\": \"5.1.6\",\n    \"undici\": \"^4.12.0\",\n    \"vite\": \"^6.2.0\",\n    \"vitest\": \"^3.2.4\"\n  },\n  \"volta\": {\n    \"node\": \"20.19.1\"\n  }\n}\n"
  },
  {
    "path": "scripts/release/create-gh-release.js",
    "content": "/**\n * @typedef {import('@octokit/openapi-types').components[\"schemas\"][\"release\"]} Release\n *\n * @typedef Params\n * @property {ReturnType<typeof import(\"@actions/github\").getOctokit>} github\n * @property {typeof import(\"@actions/github\").context} context\n *\n * @param {Params} params\n * @returns {Promise<Release>}\n */\nasync function create({ github, context }) {\n\tconst commitSha = process.env.GITHUB_SHA;\n\tconst tag_name = process.env.GITHUB_REF_NAME;\n\tconsole.log('tag:', tag_name);\n\n\tlet releaseResult;\n\n\tlet releasePages = github.paginate.iterator(\n\t\tgithub.rest.repos.listReleases,\n\t\tcontext.repo\n\t);\n\n\tfor await (const page of releasePages) {\n\t\tfor (let release of page.data) {\n\t\t\tif (release.tag_name == tag_name) {\n\t\t\t\tconsole.log('Existing release found:', release);\n\t\t\t\treleaseResult = release;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!releaseResult) {\n\t\tconsole.log('No existing release found. Creating a new draft...');\n\n\t\t// No existing release for this tag found so let's create a release\n\t\t// API Documentation: https://docs.github.com/en/rest/reference/repos#create-a-release\n\t\t// Octokit Documentation: https://octokit.github.io/rest.js/v18#repos-create-release\n\t\tconst createReleaseRes = await github.rest.repos.createRelease({\n\t\t\t...context.repo,\n\t\t\ttag_name,\n\t\t\tname: tag_name,\n\t\t\tbody: '', // TODO: Maybe run changelogged and prefill the body?\n\t\t\tdraft: true,\n\t\t\tprerelease: tag_name.includes('-'),\n\t\t\ttarget_commitish: commitSha\n\t\t});\n\n\t\tconsole.log('Created release:', createReleaseRes.data);\n\t\treleaseResult = createReleaseRes.data;\n\t} else if (!releaseResult.draft) {\n\t\tconsole.error('Found existing release but it was not in draft mode');\n\t\tprocess.exit(1);\n\t}\n\n\treturn releaseResult;\n}\n\nmodule.exports = create;\n"
  },
  {
    "path": "scripts/release/publish.mjs",
    "content": "import { execFileSync } from 'child_process';\nimport fs from 'fs';\nimport { fetch, stream } from 'undici';\nimport sade from 'sade';\n\nlet DEBUG = false;\nconst log = {\n\tdebug: (...msgs) => DEBUG && console.log(...msgs),\n\tinfo: (...msgs) => console.log(...msgs),\n\terror: (...msgs) => console.error(...msgs)\n};\n\n/**\n * @typedef {import('@octokit/openapi-types').components[\"schemas\"][\"release\"]} Release\n * @param {string} tag\n * @param {any} opts\n */\nasync function main(tag, opts) {\n\tDEBUG = opts.debug;\n\n\tlog.debug('Git tag:', tag);\n\tlog.debug('Options:', opts);\n\n\t// 1. Find a release with the matching tag\n\tconst getReleaseByTagUrl = `https://api.github.com/repos/preactjs/preact/releases/tags/${tag}`;\n\tconst response = await fetch(getReleaseByTagUrl);\n\tif (response.status == 404) {\n\t\tlog.error(\n\t\t\t`Could not find the GitHub release for tag ${tag}. Has the release workflow finished and the GitHub release published?`\n\t\t);\n\t\tprocess.exit(1);\n\t} else if (!response.ok) {\n\t\tlog.error('GitHub API returned an error:');\n\t\tlog.error(`${response.status} ${response.statusText}`);\n\t\tlog.error(await response.text());\n\t\tprocess.exit(1);\n\t}\n\n\tconst release = /** @type {Release} */ (await response.json());\n\tlog.debug('Release:', release);\n\tif (release) {\n\t\tlog.info('Found release', release.id, 'at', release.html_url);\n\t} else {\n\t\tlog.error(\n\t\t\t`Could not find a release with the tag ${tag}. Please publish that tag, wait for the release workflow to complete. Then publish the release, and re-run this script.`\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// 2. Find npm package release asset\n\t/** @type {Release[\"assets\"][0]} */\n\tlet packageAsset = null;\n\tconst artifactRegex = /^preact-.+\\.tgz$/;\n\tfor (let asset of release.assets) {\n\t\tif (artifactRegex.test(asset.name)) {\n\t\t\tpackageAsset = asset;\n\t\t}\n\t}\n\n\tif (packageAsset) {\n\t\tlog.info(`Found npm package asset: ${packageAsset.name}`);\n\t} else {\n\t\tlog.error(\n\t\t\t'Could not find asset matching package regex:',\n\t\t\tartifactRegex,\n\t\t\t'\\nPlease wait for release workflow to complete and upload npm package.'\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\t// 3. Download release asset\n\tlog.info(`\\nDownloading ${packageAsset.name}...`);\n\tawait stream(\n\t\tpackageAsset.browser_download_url,\n\t\t{\n\t\t\tmethod: 'GET',\n\t\t\tmaxRedirections: 30\n\t\t},\n\t\t() => fs.createWriteStream(packageAsset.name)\n\t);\n\n\t// 3. Run npm publish\n\tconst args = ['publish', packageAsset.name];\n\tif (opts['npm-tag']) {\n\t\targs.push('--tag', opts['npm-tag']);\n\t}\n\n\tlog.info(`Executing \\`npm ${args.join(' ')}\\``);\n\tif (!opts['dry-run']) {\n\t\texecFileSync('npm', args, { encoding: 'utf8', stdio: 'inherit' });\n\t}\n}\n\nsade('publish <git-tag>', true)\n\t.describe('Publish a tagged version of this package')\n\t.option('--npm-tag', 'The npm tag to publish this package under', '')\n\t.option(\n\t\t'--dry-run',\n\t\t\"Prepare the package for publishing but don't actually publish it\",\n\t\tfalse\n\t)\n\t.option('--debug -d', 'Log debugging information', false)\n\t.action(main)\n\t.parse(process.argv);\n"
  },
  {
    "path": "scripts/release/upload-gh-asset.js",
    "content": "/**\n * @typedef {import('@octokit/openapi-types').components[\"schemas\"][\"release\"]} Release\n *\n * @typedef Params\n * @property {typeof require} require\n * @property {ReturnType<typeof import(\"@actions/github\").getOctokit>} github\n * @property {typeof import(\"@actions/github\").context} context\n * @property {typeof import(\"@actions/glob\")} glob\n * @property {Release} release\n *\n * @param {Params} params\n */\nasync function upload({ require, github, context, glob, release }) {\n\tconst fs = require('fs');\n\n\t// Find artifact to upload\n\tconst artifactPattern = 'preact.tgz';\n\tconst globber = await glob.create(artifactPattern, {\n\t\tmatchDirectories: false\n\t});\n\n\tconst results = await globber.glob();\n\tif (results.length == 0) {\n\t\tthrow new Error(\n\t\t\t`No release artifact found matching pattern: ${artifactPattern}`\n\t\t);\n\t} else if (results.length > 1) {\n\t\tthrow new Error(\n\t\t\t`More than one artifact matching pattern found. Expected only one. Found ${results.length}.`\n\t\t);\n\t}\n\n\tconst assetPath = results[0];\n\tconst assetName = `preact-${release.tag_name.replace(/^v/, '')}.tgz`;\n\tconst assetRegex = /^preact-.+\\.tgz$/;\n\n\tfor (let asset of release.assets) {\n\t\tif (assetRegex.test(asset.name)) {\n\t\t\tconsole.log(\n\t\t\t\t`Found existing asset matching asset pattern: ${asset.name}. Removing...`\n\t\t\t);\n\t\t\tawait github.rest.repos.deleteReleaseAsset({\n\t\t\t\t...context.repo,\n\t\t\t\tasset_id: asset.id\n\t\t\t});\n\t\t}\n\t}\n\n\tconsole.log(`Uploading ${assetName} from ${assetPath}...`);\n\n\t// Upload a release asset\n\t// API Documentation: https://docs.github.com/en/rest/reference/repos#upload-a-release-asset\n\t// Octokit Documentation: https://octokit.github.io/rest.js/v18#repos-upload-release-asset\n\tconst uploadAssetResponse = await github.rest.repos.uploadReleaseAsset({\n\t\t...context.repo,\n\t\trelease_id: release.id,\n\t\tname: assetName,\n\t\tdata: fs.readFileSync(assetPath)\n\t});\n\n\tconsole.log('Asset:', uploadAssetResponse.data);\n\treturn uploadAssetResponse.data;\n}\n\nmodule.exports = upload;\n"
  },
  {
    "path": "src/clone-element.js",
    "content": "import { assign, slice } from './util';\nimport { createVNode } from './create-element';\nimport { NULL } from './constants';\n\n/**\n * Clones the given VNode, optionally adding attributes/props and replacing its\n * children.\n * @param {import('./internal').VNode} vnode The virtual DOM element to clone\n * @param {object} props Attributes/props to add when cloning\n * @param {Array<import('./internal').ComponentChildren>} rest Any additional arguments will be used\n * as replacement children.\n * @returns {import('./internal').VNode}\n */\nexport function cloneElement(vnode, props, children) {\n\tlet normalizedProps = assign({}, vnode.props),\n\t\tkey,\n\t\tref,\n\t\ti;\n\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref' && typeof vnode.type != 'function') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\treturn createVNode(\n\t\tvnode.type,\n\t\tnormalizedProps,\n\t\tkey || vnode.key,\n\t\tref || vnode.ref,\n\t\tNULL\n\t);\n}\n"
  },
  {
    "path": "src/component.js",
    "content": "import {\n\tCOMPONENT_DIRTY,\n\tCOMPONENT_FORCE,\n\tMODE_HYDRATE,\n\tNULL\n} from './constants';\nimport { Fragment } from './create-element';\nimport { commitRoot, diff } from './diff/index';\nimport options from './options';\nimport { assign } from './util';\n\n/**\n * Base Component class. Provides `setState()` and `forceUpdate()`, which\n * trigger rendering\n * @param {object} props The initial component props\n * @param {object} context The initial context from parent components'\n * getChildContext\n */\nexport function BaseComponent(props, context) {\n\tthis.props = props;\n\tthis.context = context;\n\tthis._bits = 0;\n}\n\n/**\n * Update component state and schedule a re-render.\n * @this {import('./internal').Component}\n * @param {object | ((s: object, p: object) => object)} update A hash of state\n * properties to update with new values or a function that given the current\n * state and props returns a new partial state\n * @param {() => void} [callback] A function to be called once component state is\n * updated\n */\nBaseComponent.prototype.setState = function (update, callback) {\n\t// only clone state when copying to nextState the first time.\n\tlet s;\n\tif (this._nextState != NULL && this._nextState != this.state) {\n\t\ts = this._nextState;\n\t} else {\n\t\ts = this._nextState = assign({}, this.state);\n\t}\n\n\tif (typeof update == 'function') {\n\t\t// Some libraries like `immer` mark the current state as readonly,\n\t\t// preventing us from mutating it, so we need to clone it. See #2716\n\t\tupdate = update(assign({}, s), this.props);\n\t}\n\n\tif (update) {\n\t\tassign(s, update);\n\t} else {\n\t\treturn;\n\t}\n\n\tif (this._vnode) {\n\t\tif (callback) {\n\t\t\tthis._stateCallbacks.push(callback);\n\t\t}\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Immediately perform a synchronous re-render of the component\n * @this {import('./internal').Component}\n * @param {() => void} [callback] A function to be called after component is\n * re-rendered\n */\nBaseComponent.prototype.forceUpdate = function (callback) {\n\tif (this._vnode) {\n\t\t// Set render mode so that we can differentiate where the render request\n\t\t// is coming from. We need this because forceUpdate should never call\n\t\t// shouldComponentUpdate\n\t\tthis._bits |= COMPONENT_FORCE;\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Accepts `props` and `state`, and returns a new Virtual DOM tree to build.\n * Virtual DOM is generally constructed via [JSX](https://jasonformat.com/wtf-is-jsx).\n * @param {object} props Props (eg: JSX attributes) received from parent\n * element/component\n * @param {object} state The component's current state\n * @param {object} context Context object, as returned by the nearest\n * ancestor's `getChildContext()`\n * @returns {ComponentChildren | void}\n */\nBaseComponent.prototype.render = Fragment;\n\n/**\n * @param {import('./internal').VNode} vnode\n * @param {number | null} [childIndex]\n */\nexport function getDomSibling(vnode, childIndex) {\n\tif (childIndex == NULL) {\n\t\t// Use childIndex==null as a signal to resume the search from the vnode's sibling\n\t\treturn vnode._parent\n\t\t\t? getDomSibling(vnode._parent, vnode._index + 1)\n\t\t\t: NULL;\n\t}\n\n\tlet sibling;\n\tfor (; childIndex < vnode._children.length; childIndex++) {\n\t\tsibling = vnode._children[childIndex];\n\n\t\tif (sibling != NULL && sibling._dom != NULL) {\n\t\t\t// Since updateParentDomPointers keeps _dom pointer correct,\n\t\t\t// we can rely on _dom to tell us if this subtree contains a\n\t\t\t// rendered DOM node, and what the first rendered DOM node is\n\t\t\treturn sibling._dom;\n\t\t}\n\t}\n\n\t// If we get here, we have not found a DOM node in this vnode's children.\n\t// We must resume from this vnode's sibling (in it's parent _children array)\n\t// Only climb up and search the parent if we aren't searching through a DOM\n\t// VNode (meaning we reached the DOM parent of the original vnode that began\n\t// the search)\n\treturn typeof vnode.type == 'function' ? getDomSibling(vnode) : NULL;\n}\n\n/**\n * Trigger in-place re-rendering of a component.\n * @param {import('./internal').Component} component The component to rerender\n */\nfunction renderComponent(component) {\n\tconst oldVNode = component._vnode,\n\t\toldDom = oldVNode._dom,\n\t\tcommitQueue = [],\n\t\trefQueue = [];\n\n\tconst parentDom = component._parentDom;\n\tif (parentDom) {\n\t\tconst newVNode = assign({}, oldVNode);\n\t\tnewVNode._original = oldVNode._original + 1;\n\t\tif (options.vnode) options.vnode(newVNode);\n\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tnewVNode,\n\t\t\toldVNode,\n\t\t\tcomponent._globalContext,\n\t\t\tparentDom.namespaceURI,\n\t\t\toldVNode._flags & MODE_HYDRATE ? [oldDom] : NULL,\n\t\t\tcommitQueue,\n\t\t\toldDom == NULL ? getDomSibling(oldVNode) : oldDom,\n\t\t\t!!(oldVNode._flags & MODE_HYDRATE),\n\t\t\trefQueue,\n\t\t\tparentDom.ownerDocument\n\t\t);\n\n\t\tnewVNode._original = oldVNode._original;\n\t\tnewVNode._parent._children[newVNode._index] = newVNode;\n\t\tcommitRoot(commitQueue, newVNode, refQueue);\n\t\toldVNode._parent = oldVNode._dom = NULL;\n\n\t\tif (newVNode._dom != oldDom) {\n\t\t\tupdateParentDomPointers(newVNode);\n\t\t}\n\t}\n}\n\n/**\n * @param {import('./internal').VNode} vnode\n */\nfunction updateParentDomPointers(vnode) {\n\tif ((vnode = vnode._parent) != NULL && vnode._component != NULL) {\n\t\tvnode._dom = NULL;\n\t\tvnode._children.some(child => {\n\t\t\tif (child != NULL && child._dom != NULL) {\n\t\t\t\treturn (vnode._dom = child._dom);\n\t\t\t}\n\t\t});\n\n\t\treturn updateParentDomPointers(vnode);\n\t}\n}\n\n/**\n * The render queue\n * @type {Array<import('./internal').Component>}\n */\nconst rerenderQueue = [];\n\n/*\n * The value of `Component.debounce` must asynchronously invoke the passed in callback. It is\n * important that contributors to Preact can consistently reason about what calls to `setState`, etc.\n * do, and when their effects will be applied. See the links below for some further reading on designing\n * asynchronous APIs.\n * * [Designing APIs for Asynchrony](https://blog.izs.me/2013/08/designing-apis-for-asynchrony)\n * * [Callbacks synchronous and asynchronous](https://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/)\n */\n\nlet prevDebounce,\n\trerenderCount = 0;\n\nexport function resetRenderCount() {\n\trerenderCount = 0;\n}\n\n/**\n * Enqueue a rerender of a component\n * @param {import('./internal').Component} c The component to rerender\n */\nexport function enqueueRender(c) {\n\tif (\n\t\t(!(c._bits & COMPONENT_DIRTY) &&\n\t\t\t(c._bits |= COMPONENT_DIRTY) &&\n\t\t\trerenderQueue.push(c) &&\n\t\t\t!rerenderCount++) ||\n\t\tprevDebounce != options.debounceRendering\n\t) {\n\t\tprevDebounce = options.debounceRendering;\n\t\t(prevDebounce || queueMicrotask)(process);\n\t}\n}\n\n/**\n * @param {import('./internal').Component} a\n * @param {import('./internal').Component} b\n */\nconst depthSort = (a, b) => a._vnode._depth - b._vnode._depth;\n\n/** Flush the render queue by rerendering all queued components */\nfunction process() {\n\ttry {\n\t\tlet c,\n\t\t\tl = 1;\n\n\t\t// Don't update `renderCount` yet. Keep its value non-zero to prevent unnecessary\n\t\t// process() calls from getting scheduled while `queue` is still being consumed.\n\t\twhile (rerenderQueue.length) {\n\t\t\t// Keep the rerender queue sorted by (depth, insertion order). The queue\n\t\t\t// will initially be sorted on the first iteration only if it has more than 1 item.\n\t\t\t//\n\t\t\t// New items can be added to the queue e.g. when rerendering a provider, so we want to\n\t\t\t// keep the order from top to bottom with those new items so we can handle them in a\n\t\t\t// single pass\n\t\t\tif (rerenderQueue.length > l) {\n\t\t\t\trerenderQueue.sort(depthSort);\n\t\t\t}\n\n\t\t\tc = rerenderQueue.shift();\n\t\t\tl = rerenderQueue.length;\n\n\t\t\tif (c._bits & COMPONENT_DIRTY) {\n\t\t\t\trenderComponent(c);\n\t\t\t}\n\t\t}\n\t} finally {\n\t\trerenderQueue.length = rerenderCount = 0;\n\t}\n}\n"
  },
  {
    "path": "src/constants.js",
    "content": "// Vnode._flags\n/** Normal hydration that attaches to a DOM tree but does not diff it. */\nexport const MODE_HYDRATE = 1 << 5;\n/** Signifies this VNode suspended on the previous render */\nexport const MODE_SUSPENDED = 1 << 7;\n/** Indicates that this node needs to be inserted while patching children */\nexport const INSERT_VNODE = 1 << 2;\n/** Indicates a VNode has been matched with another VNode in the diff */\nexport const MATCHED = 1 << 1;\n/** Indicates that this vnode has been unmounted before indicating the loss of event listeners */\nexport const FORCE_PROPS_REVALIDATE = 1 << 0;\n\n// component._bits\n/** Component is processing an exception */\nexport const COMPONENT_PROCESSING_EXCEPTION = 1 << 0;\n/** Component has a pending error */\nexport const COMPONENT_PENDING_ERROR = 1 << 1;\n/** Component should force update (skip shouldComponentUpdate) */\nexport const COMPONENT_FORCE = 1 << 2;\n/** Component is queued for update */\nexport const COMPONENT_DIRTY = 1 << 3;\n\n/** Reset all mode flags */\nexport const RESET_MODE = ~(MODE_HYDRATE | MODE_SUSPENDED);\n\nexport const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\nexport const XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\nexport const MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n\nexport const NULL = null;\nexport const UNDEFINED = undefined;\nexport const EMPTY_OBJ = /** @type {any} */ ({});\nexport const EMPTY_ARR = [];\n\nexport const MATHML_TOKEN_ELEMENTS = /(mi|mn|mo|ms$|mte|msp)/;\n"
  },
  {
    "path": "src/create-context.js",
    "content": "import { enqueueRender } from './component';\nimport { NULL, COMPONENT_FORCE } from './constants';\n\nexport let i = 0;\n\nexport function createContext(defaultValue) {\n\tfunction Context(props) {\n\t\tif (!this.getChildContext) {\n\t\t\t/** @type {Set<import('./internal').Component> | null} */\n\t\t\tlet subs = new Set();\n\t\t\tlet ctx = {};\n\t\t\tctx[Context._id] = this;\n\n\t\t\tthis.getChildContext = () => ctx;\n\n\t\t\tthis.componentWillUnmount = () => {\n\t\t\t\tsubs = NULL;\n\t\t\t};\n\n\t\t\tthis.shouldComponentUpdate = function (_props) {\n\t\t\t\t// @ts-expect-error even\n\t\t\t\tif (this.props.value != _props.value) {\n\t\t\t\t\tsubs.forEach(c => {\n\t\t\t\t\t\tc._bits |= COMPONENT_FORCE;\n\t\t\t\t\t\tenqueueRender(c);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tthis.sub = c => {\n\t\t\t\tsubs.add(c);\n\t\t\t\tlet old = c.componentWillUnmount;\n\t\t\t\tc.componentWillUnmount = () => {\n\t\t\t\t\tif (subs) {\n\t\t\t\t\t\tsubs.delete(c);\n\t\t\t\t\t}\n\t\t\t\t\tif (old) old.call(c);\n\t\t\t\t};\n\t\t\t};\n\t\t}\n\n\t\treturn props.children;\n\t}\n\n\tContext._id = '__cC' + i++;\n\tContext._defaultValue = defaultValue;\n\n\t/** @type {import('./internal').FunctionComponent} */\n\tContext.Consumer = (props, contextValue) => {\n\t\treturn props.children(contextValue);\n\t};\n\n\t// we could also get rid of _contextRef entirely\n\tContext.Provider =\n\t\tContext._contextRef =\n\t\tContext.Consumer.contextType =\n\t\t\tContext;\n\n\treturn Context;\n}\n"
  },
  {
    "path": "src/create-element.js",
    "content": "import { slice } from './util';\nimport options from './options';\nimport { NULL, UNDEFINED } from './constants';\n\nlet vnodeId = 0;\n\n/**\n * Create an virtual node (used for JSX)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component constructor for this\n * virtual node\n * @param {object | null | undefined} [props] The properties of the virtual node\n * @param {Array<import('.').ComponentChildren>} [children] The children of the\n * virtual node\n * @returns {import('./internal').VNode}\n */\nexport function createElement(type, props, children) {\n\tlet normalizedProps = {},\n\t\tkey,\n\t\tref,\n\t\ti;\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref' && typeof type != 'function') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\treturn createVNode(type, normalizedProps, key, ref, NULL);\n}\n\n/**\n * Create a VNode (used internally by Preact)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * Constructor for this virtual node\n * @param {object | string | number | null} props The properties of this virtual node.\n * If this virtual node represents a text node, this is the text of the node (string or number).\n * @param {string | number | null} key The key for this virtual node, used when\n * diffing it against its children\n * @param {import('./internal').VNode[\"ref\"]} ref The ref property that will\n * receive a reference to its created child\n * @returns {import('./internal').VNode}\n */\nexport function createVNode(type, props, key, ref, original) {\n\t// V8 seems to be better at detecting type shapes if the object is allocated from the same call site\n\t// Do not inline into createElement and coerceToVNode!\n\t/** @type {import('./internal').VNode} */\n\tconst vnode = {\n\t\ttype,\n\t\tprops,\n\t\tkey,\n\t\tref,\n\t\t_children: NULL,\n\t\t_parent: NULL,\n\t\t_depth: 0,\n\t\t_dom: NULL,\n\t\t_component: NULL,\n\t\tconstructor: UNDEFINED,\n\t\t_original: original == NULL ? ++vnodeId : original,\n\t\t_index: -1,\n\t\t_flags: 0\n\t};\n\n\t// Only invoke the vnode hook if this was *not* a direct copy:\n\tif (original == NULL && options.vnode != NULL) options.vnode(vnode);\n\n\treturn vnode;\n}\n\nexport function createRef() {\n\treturn { current: NULL };\n}\n\nexport function Fragment(props) {\n\treturn props.children;\n}\n\n/**\n * Check if a the argument is a valid Preact VNode.\n * @param {*} vnode\n * @returns {vnode is VNode}\n */\nexport const isValidElement = vnode =>\n\tvnode != NULL && vnode.constructor === UNDEFINED;\n"
  },
  {
    "path": "src/diff/catch-error.js",
    "content": "import { resetRenderCount } from '../component';\nimport {\n\tNULL,\n\tCOMPONENT_DIRTY,\n\tCOMPONENT_PENDING_ERROR,\n\tCOMPONENT_PROCESSING_EXCEPTION,\n\tCOMPONENT_FORCE\n} from '../constants';\n\n/**\n * Find the closest error boundary to a thrown error and call it\n * @param {object} error The thrown value\n * @param {import('../internal').VNode} vnode The vnode that threw the error that was caught (except\n * for unmounting when this parameter is the highest parent that was being\n * unmounted)\n * @param {import('../internal').VNode} [oldVNode]\n * @param {import('../internal').ErrorInfo} [errorInfo]\n */\nexport function _catchError(error, vnode, oldVNode, errorInfo) {\n\t/** @type {import('../internal').Component} */\n\tlet component,\n\t\t/** @type {import('../internal').ComponentType} */\n\t\tctor,\n\t\t/** @type {number} */\n\t\thandled;\n\n\tfor (; (vnode = vnode._parent); ) {\n\t\tif (\n\t\t\t(component = vnode._component) &&\n\t\t\t!(component._bits & COMPONENT_PROCESSING_EXCEPTION)\n\t\t) {\n\t\t\tcomponent._bits |= COMPONENT_FORCE;\n\t\t\ttry {\n\t\t\t\tctor = component.constructor;\n\n\t\t\t\tif (ctor && ctor.getDerivedStateFromError != NULL) {\n\t\t\t\t\tcomponent.setState(ctor.getDerivedStateFromError(error));\n\t\t\t\t\thandled = component._bits & COMPONENT_DIRTY;\n\t\t\t\t}\n\n\t\t\t\tif (component.componentDidCatch != NULL) {\n\t\t\t\t\tcomponent.componentDidCatch(error, errorInfo || {});\n\t\t\t\t\thandled = component._bits & COMPONENT_DIRTY;\n\t\t\t\t}\n\n\t\t\t\t// This is an error boundary. Mark it as having bailed out, and whether it was mid-hydration.\n\t\t\t\tif (handled) {\n\t\t\t\t\tcomponent._bits |= COMPONENT_PENDING_ERROR;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\terror = e;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Reset rerender count to 0, so that the next render will not be skipped\n\t// when we leverage prefresh\n\tresetRenderCount();\n\tthrow error;\n}\n"
  },
  {
    "path": "src/diff/children.js",
    "content": "import { diff, unmount, applyRef } from './index';\nimport { createVNode, Fragment } from '../create-element';\nimport {\n\tEMPTY_OBJ,\n\tEMPTY_ARR,\n\tINSERT_VNODE,\n\tMATCHED,\n\tUNDEFINED,\n\tNULL\n} from '../constants';\nimport { isArray } from '../util';\nimport { getDomSibling } from '../component';\n\n/**\n * @typedef {import('../internal').ComponentChildren} ComponentChildren\n * @typedef {import('../internal').Component} Component\n * @typedef {import('../internal').PreactElement} PreactElement\n * @typedef {import('../internal').VNode} VNode\n */\n\n/**\n * Diff the children of a virtual node\n * @param {PreactElement} parentDom The DOM element whose children are being\n * diffed\n * @param {ComponentChildren[]} renderResult\n * @param {VNode} newParentVNode The new virtual node whose children should be\n * diff'ed against oldParentVNode\n * @param {VNode} oldParentVNode The old virtual node whose children should be\n * diff'ed against newParentVNode\n * @param {object} globalContext The current context object - modified by\n * getChildContext\n * @param {string} namespace Current namespace of the DOM node (HTML, SVG, or MathML)\n * @param {Array<PreactElement>} excessDomChildren\n * @param {Array<Component>} commitQueue List of components which have callbacks\n * to invoke in commitRoot\n * @param {PreactElement} oldDom The current attached DOM element any new dom\n * elements should be placed around. Likely `null` on first render (except when\n * hydrating). Can be a sibling DOM element when diffing Fragments that have\n * siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} isHydrating Whether or not we are in hydration\n * @param {any[]} refQueue an array of elements needed to invoke refs\n * @param {Document} doc The document object to use for creating elements\n * @returns {PreactElement} The next sibling DOM element to insert new elements\n */\nexport function diffChildren(\n\tparentDom,\n\trenderResult,\n\tnewParentVNode,\n\toldParentVNode,\n\tglobalContext,\n\tnamespace,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating,\n\trefQueue,\n\tdoc\n) {\n\tlet i,\n\t\t/** @type {VNode} */\n\t\toldVNode,\n\t\t/** @type {VNode} */\n\t\tchildVNode,\n\t\t/** @type {PreactElement} */\n\t\tnewDom,\n\t\t/** @type {PreactElement} */\n\t\tfirstChildDom;\n\n\t// This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR\n\t// as EMPTY_OBJ._children should be `undefined`.\n\t/** @type {VNode[]} */\n\tlet oldChildren = (oldParentVNode && oldParentVNode._children) || EMPTY_ARR;\n\n\tlet newChildrenLength = renderResult.length;\n\n\toldDom = constructNewChildrenArray(\n\t\tnewParentVNode,\n\t\trenderResult,\n\t\toldChildren,\n\t\toldDom,\n\t\tnewChildrenLength\n\t);\n\n\tfor (i = 0; i < newChildrenLength; i++) {\n\t\tchildVNode = newParentVNode._children[i];\n\t\tif (childVNode == NULL) continue;\n\n\t\t// At this point, constructNewChildrenArray has assigned _index to be the\n\t\t// matchingIndex for this VNode's oldVNode (or -1 if there is no oldVNode).\n\t\toldVNode =\n\t\t\t(childVNode._index != -1 && oldChildren[childVNode._index]) || EMPTY_OBJ;\n\n\t\t// Update childVNode._index to its final index\n\t\tchildVNode._index = i;\n\n\t\t// Morph the old element into the new one, but don't append it to the dom yet\n\t\tlet result = diff(\n\t\t\tparentDom,\n\t\t\tchildVNode,\n\t\t\toldVNode,\n\t\t\tglobalContext,\n\t\t\tnamespace,\n\t\t\texcessDomChildren,\n\t\t\tcommitQueue,\n\t\t\toldDom,\n\t\t\tisHydrating,\n\t\t\trefQueue,\n\t\t\tdoc\n\t\t);\n\n\t\t// Adjust DOM nodes\n\t\tnewDom = childVNode._dom;\n\t\tif (childVNode.ref && oldVNode.ref != childVNode.ref) {\n\t\t\tif (oldVNode.ref) {\n\t\t\t\tapplyRef(oldVNode.ref, NULL, childVNode);\n\t\t\t}\n\t\t\trefQueue.push(\n\t\t\t\tchildVNode.ref,\n\t\t\t\tchildVNode._component || newDom,\n\t\t\t\tchildVNode\n\t\t\t);\n\t\t}\n\n\t\tif (firstChildDom == NULL && newDom != NULL) {\n\t\t\tfirstChildDom = newDom;\n\t\t}\n\n\t\tlet shouldPlace = childVNode._flags & INSERT_VNODE;\n\t\tif (shouldPlace || oldVNode._children === childVNode._children) {\n\t\t\toldDom = insert(childVNode, oldDom, parentDom, shouldPlace);\n\t\t} else if (typeof childVNode.type == 'function' && result !== UNDEFINED) {\n\t\t\toldDom = result;\n\t\t} else if (newDom) {\n\t\t\toldDom = newDom.nextSibling;\n\t\t}\n\n\t\t// Unset diffing flags\n\t\tchildVNode._flags &= ~(INSERT_VNODE | MATCHED);\n\t}\n\n\tnewParentVNode._dom = firstChildDom;\n\n\treturn oldDom;\n}\n\n/**\n * @param {VNode} newParentVNode\n * @param {ComponentChildren[]} renderResult\n * @param {VNode[]} oldChildren\n */\nfunction constructNewChildrenArray(\n\tnewParentVNode,\n\trenderResult,\n\toldChildren,\n\toldDom,\n\tnewChildrenLength\n) {\n\t/** @type {number} */\n\tlet i;\n\t/** @type {VNode} */\n\tlet childVNode;\n\t/** @type {VNode} */\n\tlet oldVNode;\n\n\tlet oldChildrenLength = oldChildren.length,\n\t\tremainingOldChildren = oldChildrenLength;\n\n\tlet skew = 0;\n\n\tnewParentVNode._children = new Array(newChildrenLength);\n\tfor (i = 0; i < newChildrenLength; i++) {\n\t\t// @ts-expect-error We are reusing the childVNode variable to hold both the\n\t\t// pre and post normalized childVNode\n\t\tchildVNode = renderResult[i];\n\n\t\tif (\n\t\t\tchildVNode == NULL ||\n\t\t\ttypeof childVNode == 'boolean' ||\n\t\t\ttypeof childVNode == 'function'\n\t\t) {\n\t\t\tnewParentVNode._children[i] = NULL;\n\t\t\tcontinue;\n\t\t}\n\t\t// If this newVNode is being reused (e.g. <div>{reuse}{reuse}</div>) in the same diff,\n\t\t// or we are rendering a component (e.g. setState) copy the oldVNodes so it can have\n\t\t// it's own DOM & etc. pointers\n\t\telse if (\n\t\t\ttypeof childVNode == 'string' ||\n\t\t\ttypeof childVNode == 'number' ||\n\t\t\t// eslint-disable-next-line valid-typeof\n\t\t\ttypeof childVNode == 'bigint' ||\n\t\t\tchildVNode.constructor == String\n\t\t) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tNULL,\n\t\t\t\tchildVNode,\n\t\t\t\tNULL,\n\t\t\t\tNULL,\n\t\t\t\tNULL\n\t\t\t);\n\t\t} else if (isArray(childVNode)) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tFragment,\n\t\t\t\t{ children: childVNode },\n\t\t\t\tNULL,\n\t\t\t\tNULL,\n\t\t\t\tNULL\n\t\t\t);\n\t\t} else if (childVNode.constructor === UNDEFINED && childVNode._depth > 0) {\n\t\t\t// VNode is already in use, clone it. This can happen in the following\n\t\t\t// scenario:\n\t\t\t//   const reuse = <div />\n\t\t\t//   <div>{reuse}<span />{reuse}</div>\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tchildVNode.type,\n\t\t\t\tchildVNode.props,\n\t\t\t\tchildVNode.key,\n\t\t\t\tchildVNode.ref ? childVNode.ref : NULL,\n\t\t\t\tchildVNode._original\n\t\t\t);\n\t\t} else {\n\t\t\tnewParentVNode._children[i] = childVNode;\n\t\t}\n\n\t\tconst skewedIndex = i + skew;\n\t\tchildVNode._parent = newParentVNode;\n\t\tchildVNode._depth = newParentVNode._depth + 1;\n\n\t\t// Temporarily store the matchingIndex on the _index property so we can pull\n\t\t// out the oldVNode in diffChildren. We'll override this to the VNode's\n\t\t// final index after using this property to get the oldVNode\n\t\tconst matchingIndex = (childVNode._index = findMatchingIndex(\n\t\t\tchildVNode,\n\t\t\toldChildren,\n\t\t\tskewedIndex,\n\t\t\tremainingOldChildren\n\t\t));\n\n\t\toldVNode = NULL;\n\t\tif (matchingIndex != -1) {\n\t\t\toldVNode = oldChildren[matchingIndex];\n\t\t\tremainingOldChildren--;\n\t\t\tif (oldVNode) {\n\t\t\t\toldVNode._flags |= MATCHED;\n\t\t\t}\n\t\t}\n\n\t\t// Here, we define isMounting for the purposes of the skew diffing\n\t\t// algorithm. Nodes that are unsuspending are considered mounting and we detect\n\t\t// this by checking if oldVNode._original == null\n\t\tif (oldVNode == NULL || oldVNode._original == NULL) {\n\t\t\tif (matchingIndex == -1) {\n\t\t\t\t// When the array of children is growing we need to decrease the skew\n\t\t\t\t// as we are adding a new element to the array.\n\t\t\t\t// Example:\n\t\t\t\t// [1, 2, 3] --> [0, 1, 2, 3]\n\t\t\t\t// oldChildren   newChildren\n\t\t\t\t//\n\t\t\t\t// The new element is at index 0, so our skew is 0,\n\t\t\t\t// we need to decrease the skew as we are adding a new element.\n\t\t\t\t// The decrease will cause us to compare the element at position 1\n\t\t\t\t// with value 1 with the element at position 0 with value 0.\n\t\t\t\t//\n\t\t\t\t// A linear concept is applied when the array is shrinking,\n\t\t\t\t// if the length is unchanged we can assume that no skew\n\t\t\t\t// changes are needed.\n\t\t\t\tif (newChildrenLength > oldChildrenLength) {\n\t\t\t\t\tskew--;\n\t\t\t\t} else if (newChildrenLength < oldChildrenLength) {\n\t\t\t\t\tskew++;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we are mounting a DOM VNode, mark it for insertion\n\t\t\tif (typeof childVNode.type != 'function') {\n\t\t\t\tchildVNode._flags |= INSERT_VNODE;\n\t\t\t}\n\t\t} else if (matchingIndex != skewedIndex) {\n\t\t\t// When we move elements around i.e. [0, 1, 2] --> [1, 0, 2]\n\t\t\t// --> we diff 1, we find it at position 1 while our skewed index is 0 and our skew is 0\n\t\t\t//     we set the skew to 1 as we found an offset.\n\t\t\t// --> we diff 0, we find it at position 0 while our skewed index is at 2 and our skew is 1\n\t\t\t//     this makes us increase the skew again.\n\t\t\t// --> we diff 2, we find it at position 2 while our skewed index is at 4 and our skew is 2\n\t\t\t//\n\t\t\t// this becomes an optimization question where currently we see a 1 element offset as an insertion\n\t\t\t// or deletion i.e. we optimize for [0, 1, 2] --> [9, 0, 1, 2]\n\t\t\t// while a more than 1 offset we see as a swap.\n\t\t\t// We could probably build heuristics for having an optimized course of action here as well, but\n\t\t\t// might go at the cost of some bytes.\n\t\t\t//\n\t\t\t// If we wanted to optimize for i.e. only swaps we'd just do the last two code-branches and have\n\t\t\t// only the first item be a re-scouting and all the others fall in their skewed counter-part.\n\t\t\t// We could also further optimize for swaps\n\t\t\tif (matchingIndex == skewedIndex - 1) {\n\t\t\t\tskew--;\n\t\t\t} else if (matchingIndex == skewedIndex + 1) {\n\t\t\t\tskew++;\n\t\t\t} else {\n\t\t\t\tif (matchingIndex > skewedIndex) {\n\t\t\t\t\tskew--;\n\t\t\t\t} else {\n\t\t\t\t\tskew++;\n\t\t\t\t}\n\n\t\t\t\t// Move this VNode's DOM if the original index (matchingIndex) doesn't\n\t\t\t\t// match the new skew index (i + new skew)\n\t\t\t\t// In the former two branches we know that it matches after skewing\n\t\t\t\tchildVNode._flags |= INSERT_VNODE;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove remaining oldChildren if there are any. Loop forwards so that as we\n\t// unmount DOM from the beginning of the oldChildren, we can adjust oldDom to\n\t// point to the next child, which needs to be the first DOM node that won't be\n\t// unmounted.\n\tif (remainingOldChildren) {\n\t\tfor (i = 0; i < oldChildrenLength; i++) {\n\t\t\toldVNode = oldChildren[i];\n\t\t\tif (oldVNode != NULL && (oldVNode._flags & MATCHED) == 0) {\n\t\t\t\tif (oldVNode._dom == oldDom) {\n\t\t\t\t\toldDom = getDomSibling(oldVNode);\n\t\t\t\t}\n\n\t\t\t\tunmount(oldVNode, oldVNode);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldDom;\n}\n\n/**\n * @param {VNode} parentVNode\n * @param {PreactElement} oldDom\n * @param {PreactElement} parentDom\n * @param {number} shouldPlace\n * @returns {PreactElement}\n */\nfunction insert(parentVNode, oldDom, parentDom, shouldPlace) {\n\t// Note: VNodes in nested suspended trees may be missing _children.\n\tif (typeof parentVNode.type == 'function') {\n\t\tlet children = parentVNode._children;\n\t\tfor (let i = 0; children && i < children.length; i++) {\n\t\t\tif (children[i]) {\n\t\t\t\t// If we enter this code path on sCU bailout, where we copy\n\t\t\t\t// oldVNode._children to newVNode._children, we need to update the old\n\t\t\t\t// children's _parent pointer to point to the newVNode (parentVNode\n\t\t\t\t// here).\n\t\t\t\tchildren[i]._parent = parentVNode;\n\t\t\t\toldDom = insert(children[i], oldDom, parentDom, shouldPlace);\n\t\t\t}\n\t\t}\n\n\t\treturn oldDom;\n\t} else if (parentVNode._dom != oldDom) {\n\t\tif (shouldPlace) {\n\t\t\tif (oldDom && parentVNode.type && !oldDom.parentNode) {\n\t\t\t\toldDom = getDomSibling(parentVNode);\n\t\t\t}\n\t\t\tparentDom.insertBefore(parentVNode._dom, oldDom || NULL);\n\t\t}\n\t\toldDom = parentVNode._dom;\n\t}\n\n\tdo {\n\t\toldDom = oldDom && oldDom.nextSibling;\n\t} while (oldDom != NULL && oldDom.nodeType == 8);\n\n\treturn oldDom;\n}\n\n/**\n * Flatten and loop through the children of a virtual node\n * @param {ComponentChildren} children The unflattened children of a virtual\n * node\n * @returns {VNode[]}\n */\nexport function toChildArray(children, out) {\n\tout = out || [];\n\tif (children == NULL || typeof children == 'boolean') {\n\t} else if (isArray(children)) {\n\t\tchildren.some(child => {\n\t\t\ttoChildArray(child, out);\n\t\t});\n\t} else {\n\t\tout.push(children);\n\t}\n\treturn out;\n}\n\n/**\n * @param {VNode} childVNode\n * @param {VNode[]} oldChildren\n * @param {number} skewedIndex\n * @param {number} remainingOldChildren\n * @returns {number}\n */\nfunction findMatchingIndex(\n\tchildVNode,\n\toldChildren,\n\tskewedIndex,\n\tremainingOldChildren\n) {\n\tconst key = childVNode.key;\n\tconst type = childVNode.type;\n\tlet oldVNode = oldChildren[skewedIndex];\n\tconst matched = oldVNode != NULL && (oldVNode._flags & MATCHED) == 0;\n\n\t// We only need to perform a search if there are more children\n\t// (remainingOldChildren) to search. However, if the oldVNode we just looked\n\t// at skewedIndex was not already used in this diff, then there must be at\n\t// least 1 other (so greater than 1) remainingOldChildren to attempt to match\n\t// against. So the following condition checks that ensuring\n\t// remainingOldChildren > 1 if the oldVNode is not already used/matched. Else\n\t// if the oldVNode was null or matched, then there could needs to be at least\n\t// 1 (aka `remainingOldChildren > 0`) children to find and compare against.\n\t//\n\t// If there is an unkeyed functional VNode, that isn't a built-in like our Fragment,\n\t// we should not search as we risk re-using state of an unrelated VNode. (reverted for now)\n\tlet shouldSearch =\n\t\t// (typeof type != 'function' || type === Fragment || key) &&\n\t\tremainingOldChildren > (matched ? 1 : 0);\n\n\tif (\n\t\t(oldVNode === NULL && key == null) ||\n\t\t(matched && key == oldVNode.key && type == oldVNode.type)\n\t) {\n\t\treturn skewedIndex;\n\t} else if (shouldSearch) {\n\t\tlet x = skewedIndex - 1;\n\t\tlet y = skewedIndex + 1;\n\t\twhile (x >= 0 || y < oldChildren.length) {\n\t\t\tconst childIndex = x >= 0 ? x-- : y++;\n\t\t\toldVNode = oldChildren[childIndex];\n\t\t\tif (\n\t\t\t\toldVNode != NULL &&\n\t\t\t\t(oldVNode._flags & MATCHED) == 0 &&\n\t\t\t\tkey == oldVNode.key &&\n\t\t\t\ttype == oldVNode.type\n\t\t\t) {\n\t\t\t\treturn childIndex;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn -1;\n}\n"
  },
  {
    "path": "src/diff/index.js",
    "content": "import { BaseComponent, getDomSibling } from '../component';\nimport {\n\tCOMPONENT_DIRTY,\n\tCOMPONENT_FORCE,\n\tCOMPONENT_PENDING_ERROR,\n\tCOMPONENT_PROCESSING_EXCEPTION,\n\tEMPTY_ARR,\n\tEMPTY_OBJ,\n\tFORCE_PROPS_REVALIDATE,\n\tMATHML_TOKEN_ELEMENTS,\n\tMATH_NAMESPACE,\n\tMODE_HYDRATE,\n\tMODE_SUSPENDED,\n\tNULL,\n\tRESET_MODE,\n\tSVG_NAMESPACE,\n\tUNDEFINED,\n\tXHTML_NAMESPACE\n} from '../constants';\nimport { Fragment } from '../create-element';\nimport options from '../options';\nimport { assign, isArray, removeNode, slice } from '../util';\nimport { diffChildren } from './children';\nimport { setProperty } from './props';\n\n/**\n * @typedef {import('../internal').ComponentType} ComponentType\n * @typedef {import('../internal').ComponentChildren} ComponentChildren\n * @typedef {import('../internal').Component} Component\n * @typedef {import('../internal').PreactElement} PreactElement\n * @typedef {import('../internal').VNode} VNode\n */\n\n/**\n * @template {any} T\n * @typedef {import('../internal').Ref<T>} Ref<T>\n */\n\n/**\n * Diff two virtual nodes and apply proper changes to the DOM\n * @param {PreactElement} parentDom The parent of the DOM element\n * @param {VNode} newVNode The new virtual node\n * @param {VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object. Modified by\n * getChildContext\n * @param {string} namespace Current namespace of the DOM node (HTML, SVG, or MathML)\n * @param {Array<PreactElement>} excessDomChildren\n * @param {Array<Component>} commitQueue List of components which have callbacks\n * to invoke in commitRoot\n * @param {PreactElement} oldDom The current attached DOM element any new dom\n * elements should be placed around. Likely `null` on first render (except when\n * hydrating). Can be a sibling DOM element when diffing Fragments that have\n * siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} isHydrating Whether or not we are in hydration\n * @param {any[]} refQueue an array of elements needed to invoke refs\n * @param {Document} doc The document object to use for creating elements\n */\nexport function diff(\n\tparentDom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tnamespace,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating,\n\trefQueue,\n\tdoc\n) {\n\t/** @type {any} */\n\tlet tmp,\n\t\tnewType = newVNode.type;\n\n\t// When passing through createElement it assigns the object\n\t// constructor as undefined. This to prevent JSON-injection.\n\tif (newVNode.constructor !== UNDEFINED) return NULL;\n\n\t// If the previous diff bailed out, resume creating/hydrating.\n\tif (\n\t\toldVNode._flags & MODE_SUSPENDED &&\n\t\t// @ts-expect-error This is 1 or 0 (true or false)\n\t\t(isHydrating = oldVNode._flags & MODE_HYDRATE) &&\n\t\toldVNode._component._excess\n\t) {\n\t\texcessDomChildren = oldVNode._component._excess;\n\t\toldDom = excessDomChildren[0];\n\t\toldVNode._component._excess = NULL;\n\t}\n\n\tif ((tmp = options._diff)) tmp(newVNode);\n\n\touter: if (typeof newType == 'function') {\n\t\ttry {\n\t\t\tlet c,\n\t\t\t\toldProps,\n\t\t\t\toldState,\n\t\t\t\tsnapshot,\n\t\t\t\tnewProps = newVNode.props;\n\t\t\tconst isClassComponent = newType.prototype && newType.prototype.render;\n\n\t\t\t// Necessary for createContext api. Setting this property will pass\n\t\t\t// the context value as `this.context` just for this component.\n\t\t\ttmp = newType.contextType;\n\t\t\tconst provider = tmp && globalContext[tmp._id];\n\t\t\tconst componentContext = tmp\n\t\t\t\t? provider\n\t\t\t\t\t? provider.props.value\n\t\t\t\t\t: tmp._defaultValue\n\t\t\t\t: globalContext;\n\n\t\t\t// Get component and set it to `c`\n\t\t\tif (oldVNode._component) {\n\t\t\t\tc = newVNode._component = oldVNode._component;\n\t\t\t\tif (c._bits & COMPONENT_PENDING_ERROR) {\n\t\t\t\t\tc._bits |= COMPONENT_PROCESSING_EXCEPTION;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Instantiate the new component\n\t\t\t\tif (isClassComponent) {\n\t\t\t\t\t// @ts-expect-error Trust me, Component implements the interface we want\n\t\t\t\t\tnewVNode._component = c = new newType(newProps, componentContext); // eslint-disable-line new-cap\n\t\t\t\t} else {\n\t\t\t\t\t// @ts-expect-error Trust me, Component implements the interface we want\n\t\t\t\t\tnewVNode._component = c = new BaseComponent(\n\t\t\t\t\t\tnewProps,\n\t\t\t\t\t\tcomponentContext\n\t\t\t\t\t);\n\n\t\t\t\t\tc.constructor = newType;\n\t\t\t\t\tc.render = doRender;\n\t\t\t\t}\n\t\t\t\tif (provider) provider.sub(c);\n\n\t\t\t\tif (!c.state) c.state = {};\n\t\t\t\tc._globalContext = globalContext;\n\t\t\t\tc._bits |= COMPONENT_DIRTY;\n\t\t\t\tc._renderCallbacks = [];\n\t\t\t\tc._stateCallbacks = [];\n\t\t\t}\n\n\t\t\t// Invoke getDerivedStateFromProps\n\t\t\tif (isClassComponent && c._nextState == NULL) {\n\t\t\t\tc._nextState = c.state;\n\t\t\t}\n\n\t\t\tif (isClassComponent && newType.getDerivedStateFromProps != NULL) {\n\t\t\t\tif (c._nextState == c.state) {\n\t\t\t\t\tc._nextState = assign({}, c._nextState);\n\t\t\t\t}\n\n\t\t\t\tassign(\n\t\t\t\t\tc._nextState,\n\t\t\t\t\tnewType.getDerivedStateFromProps(newProps, c._nextState)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\toldProps = c.props;\n\t\t\toldState = c.state;\n\t\t\tc._vnode = newVNode;\n\n\t\t\t// Invoke pre-render lifecycle methods\n\t\t\tif (!oldVNode._component) {\n\t\t\t\tif (\n\t\t\t\t\tisClassComponent &&\n\t\t\t\t\tnewType.getDerivedStateFromProps == NULL &&\n\t\t\t\t\tc.componentWillMount != NULL\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillMount();\n\t\t\t\t}\n\n\t\t\t\tif (isClassComponent && c.componentDidMount != NULL) {\n\t\t\t\t\tc._renderCallbacks.push(c.componentDidMount);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tisClassComponent &&\n\t\t\t\t\tnewType.getDerivedStateFromProps == NULL &&\n\t\t\t\t\tnewProps !== oldProps &&\n\t\t\t\t\tc.componentWillReceiveProps != NULL\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillReceiveProps(newProps, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tnewVNode._original == oldVNode._original ||\n\t\t\t\t\t(!(c._bits & COMPONENT_FORCE) &&\n\t\t\t\t\t\tc.shouldComponentUpdate != NULL &&\n\t\t\t\t\t\tc.shouldComponentUpdate(\n\t\t\t\t\t\t\tnewProps,\n\t\t\t\t\t\t\tc._nextState,\n\t\t\t\t\t\t\tcomponentContext\n\t\t\t\t\t\t) === false)\n\t\t\t\t) {\n\t\t\t\t\t// More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8\n\t\t\t\t\tif (newVNode._original != oldVNode._original) {\n\t\t\t\t\t\t// When we are dealing with a bail because of sCU we have to update\n\t\t\t\t\t\t// the props, state and dirty-state.\n\t\t\t\t\t\t// when we are dealing with strict-equality we don't as the child could still\n\t\t\t\t\t\t// be dirtied see #3883\n\t\t\t\t\t\tc.props = newProps;\n\t\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t\t\tc._bits &= ~COMPONENT_DIRTY;\n\t\t\t\t\t}\n\n\t\t\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t\t\t\tnewVNode._children = oldVNode._children;\n\t\t\t\t\tnewVNode._children.some(vnode => {\n\t\t\t\t\t\tif (vnode) vnode._parent = newVNode;\n\t\t\t\t\t});\n\n\t\t\t\t\tEMPTY_ARR.push.apply(c._renderCallbacks, c._stateCallbacks);\n\t\t\t\t\tc._stateCallbacks = [];\n\n\t\t\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\t\t\tcommitQueue.push(c);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\n\t\t\t\tif (c.componentWillUpdate != NULL) {\n\t\t\t\t\tc.componentWillUpdate(newProps, c._nextState, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (isClassComponent && c.componentDidUpdate != NULL) {\n\t\t\t\t\tc._renderCallbacks.push(() => {\n\t\t\t\t\t\tc.componentDidUpdate(oldProps, oldState, snapshot);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tc.context = componentContext;\n\t\t\tc.props = newProps;\n\t\t\tc._parentDom = parentDom;\n\t\t\tc._bits &= ~COMPONENT_FORCE;\n\n\t\t\tlet renderHook = options._render,\n\t\t\t\tcount = 0;\n\t\t\tif (isClassComponent) {\n\t\t\t\tc.state = c._nextState;\n\t\t\t\tc._bits &= ~COMPONENT_DIRTY;\n\n\t\t\t\tif (renderHook) renderHook(newVNode);\n\n\t\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t\tEMPTY_ARR.push.apply(c._renderCallbacks, c._stateCallbacks);\n\t\t\t\tc._stateCallbacks = [];\n\t\t\t} else {\n\t\t\t\tdo {\n\t\t\t\t\tc._bits &= ~COMPONENT_DIRTY;\n\t\t\t\t\tif (renderHook) renderHook(newVNode);\n\n\t\t\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t\t\t// Handle setState called in render, see #2553\n\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t} while (c._bits & COMPONENT_DIRTY && ++count < 25);\n\t\t\t}\n\n\t\t\t// Handle setState called in render, see #2553\n\t\t\tc.state = c._nextState;\n\n\t\t\tif (c.getChildContext != NULL) {\n\t\t\t\tglobalContext = assign({}, globalContext, c.getChildContext());\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tisClassComponent &&\n\t\t\t\toldVNode._component &&\n\t\t\t\tc.getSnapshotBeforeUpdate != NULL\n\t\t\t) {\n\t\t\t\tsnapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);\n\t\t\t}\n\n\t\t\tconst renderResult =\n\t\t\t\ttmp != NULL && tmp.type === Fragment && tmp.key == NULL\n\t\t\t\t\t? cloneNode(tmp.props.children)\n\t\t\t\t\t: tmp;\n\n\t\t\toldDom = diffChildren(\n\t\t\t\tparentDom,\n\t\t\t\tisArray(renderResult) ? renderResult : [renderResult],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tnamespace,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\toldDom,\n\t\t\t\tisHydrating,\n\t\t\t\trefQueue,\n\t\t\t\tdoc\n\t\t\t);\n\n\t\t\t// We successfully rendered this VNode, unset any stored hydration/bailout state:\n\t\t\tnewVNode._flags &= RESET_MODE;\n\n\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\tcommitQueue.push(c);\n\t\t\t}\n\n\t\t\tif (c._bits & COMPONENT_PENDING_ERROR) {\n\t\t\t\tc._bits &= ~(COMPONENT_PROCESSING_EXCEPTION | COMPONENT_PENDING_ERROR);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tnewVNode._original = NULL;\n\t\t\t// if hydrating or creating initial tree, bailout preserves DOM:\n\t\t\tif (isHydrating || excessDomChildren != NULL) {\n\t\t\t\tif (e.then) {\n\t\t\t\t\tlet commentMarkersToFind = 0,\n\t\t\t\t\t\tdone;\n\n\t\t\t\t\tnewVNode._flags |= isHydrating\n\t\t\t\t\t\t? MODE_HYDRATE | MODE_SUSPENDED\n\t\t\t\t\t\t: MODE_SUSPENDED;\n\n\t\t\t\t\tnewVNode._component._excess = [];\n\t\t\t\t\tfor (let i = 0; i < excessDomChildren.length; i++) {\n\t\t\t\t\t\tconst child = excessDomChildren[i];\n\t\t\t\t\t\tif (child == NULL || done) continue;\n\n\t\t\t\t\t\t// When we encounter a boundary with $s we are opening\n\t\t\t\t\t\t// a boundary, this implies that we need to bump\n\t\t\t\t\t\t// the amount of markers we need to find before closing\n\t\t\t\t\t\t// the outer boundary.\n\t\t\t\t\t\t// We exclude the open and closing marker from\n\t\t\t\t\t\t// the future excessDomChildren but any nested one\n\t\t\t\t\t\t// needs to be included for future suspensions.\n\t\t\t\t\t\tif (child.nodeType == 8) {\n\t\t\t\t\t\t\tif (child.data == '$s') {\n\t\t\t\t\t\t\t\tif (commentMarkersToFind) {\n\t\t\t\t\t\t\t\t\tnewVNode._component._excess.push(child);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcommentMarkersToFind++;\n\t\t\t\t\t\t\t} else if (child.data == '/$s') {\n\t\t\t\t\t\t\t\tcommentMarkersToFind--;\n\t\t\t\t\t\t\t\tif (commentMarkersToFind) {\n\t\t\t\t\t\t\t\t\tnewVNode._component._excess.push(child);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdone = commentMarkersToFind == 0;\n\t\t\t\t\t\t\t\toldDom = excessDomChildren[i];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\texcessDomChildren[i] = NULL;\n\t\t\t\t\t\t} else if (commentMarkersToFind) {\n\t\t\t\t\t\t\tnewVNode._component._excess.push(child);\n\t\t\t\t\t\t\texcessDomChildren[i] = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!done) {\n\t\t\t\t\t\twhile (oldDom && oldDom.nodeType == 8 && oldDom.nextSibling) {\n\t\t\t\t\t\t\toldDom = oldDom.nextSibling;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\texcessDomChildren[excessDomChildren.indexOf(oldDom)] = NULL;\n\t\t\t\t\t\tnewVNode._component._excess = [oldDom];\n\t\t\t\t\t}\n\n\t\t\t\t\tnewVNode._dom = oldDom;\n\t\t\t\t} else {\n\t\t\t\t\tfor (let i = excessDomChildren.length; i--; ) {\n\t\t\t\t\t\tremoveNode(excessDomChildren[i]);\n\t\t\t\t\t}\n\t\t\t\t\tmarkAsForce(newVNode);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t\t\tnewVNode._children = oldVNode._children;\n\t\t\t\tif (!e.then) markAsForce(newVNode);\n\t\t\t}\n\t\t\toptions._catchError(e, newVNode, oldVNode);\n\t\t}\n\t} else {\n\t\toldDom = newVNode._dom = diffElementNodes(\n\t\t\toldVNode._dom,\n\t\t\tnewVNode,\n\t\t\toldVNode,\n\t\t\tglobalContext,\n\t\t\tnamespace,\n\t\t\texcessDomChildren,\n\t\t\tcommitQueue,\n\t\t\tisHydrating,\n\t\t\trefQueue,\n\t\t\tdoc\n\t\t);\n\t}\n\n\tif ((tmp = options.diffed)) tmp(newVNode);\n\n\treturn newVNode._flags & MODE_SUSPENDED ? UNDEFINED : oldDom;\n}\n\nfunction markAsForce(vnode) {\n\tif (vnode && vnode._component) vnode._component._bits |= COMPONENT_FORCE;\n\tif (vnode && vnode._children) vnode._children.forEach(markAsForce);\n}\n\n/**\n * @param {Array<Component>} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {VNode} root\n */\nexport function commitRoot(commitQueue, root, refQueue) {\n\tfor (let i = 0; i < refQueue.length; i++) {\n\t\tapplyRef(refQueue[i], refQueue[++i], refQueue[++i]);\n\t}\n\n\tif (options._commit) options._commit(root, commitQueue);\n\n\tcommitQueue.some(c => {\n\t\ttry {\n\t\t\t// @ts-expect-error Reuse the commitQueue variable here so the type changes\n\t\t\tcommitQueue = c._renderCallbacks;\n\t\t\tc._renderCallbacks = [];\n\t\t\tcommitQueue.some(cb => {\n\t\t\t\t// @ts-expect-error See above comment on commitQueue\n\t\t\t\tcb.call(c);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\toptions._catchError(e, c._vnode);\n\t\t}\n\t});\n}\n\nfunction cloneNode(node) {\n\tif (typeof node != 'object' || node == NULL || node._depth > 0) {\n\t\treturn node;\n\t}\n\n\tif (isArray(node)) {\n\t\treturn node.map(cloneNode);\n\t}\n\n\treturn assign({}, node);\n}\n\n/**\n * Diff two virtual nodes representing DOM element\n * @param {PreactElement} dom The DOM element representing the virtual nodes\n * being diffed\n * @param {VNode} newVNode The new virtual node\n * @param {VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object\n * @param {string} namespace Current namespace of the DOM node (HTML, SVG, or MathML)\n * @param {Array<PreactElement>} excessDomChildren\n * @param {Array<Component>} commitQueue List of components which have callbacks\n * to invoke in commitRoot\n * @param {boolean} isHydrating Whether or not we are in hydration\n * @param {any[]} refQueue an array of elements needed to invoke refs\n * @param {Document} doc The document object to use for creating elements\n * @returns {PreactElement}\n */\nfunction diffElementNodes(\n\tdom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tnamespace,\n\texcessDomChildren,\n\tcommitQueue,\n\tisHydrating,\n\trefQueue,\n\tdoc\n) {\n\tlet oldProps = oldVNode.props || EMPTY_OBJ;\n\tconst newProps = newVNode.props;\n\tconst nodeType = /** @type {string} */ (newVNode.type);\n\t/** @type {any} */\n\tlet i;\n\t/** @type {{ __html?: string }} */\n\tlet newHtml;\n\t/** @type {{ __html?: string }} */\n\tlet oldHtml;\n\t/** @type {ComponentChildren} */\n\tlet newChildren;\n\tlet value;\n\tlet inputValue;\n\tlet checked;\n\n\t// Tracks entering and exiting namespaces when descending through the tree.\n\tif (nodeType == 'svg') namespace = SVG_NAMESPACE;\n\telse if (nodeType == 'math') namespace = MATH_NAMESPACE;\n\telse if (!namespace) namespace = XHTML_NAMESPACE;\n\n\tif (excessDomChildren != NULL) {\n\t\tfor (i = 0; i < excessDomChildren.length; i++) {\n\t\t\tvalue = excessDomChildren[i];\n\n\t\t\t// if newVNode matches an element in excessDomChildren or the `dom`\n\t\t\t// argument matches an element in excessDomChildren, remove it from\n\t\t\t// excessDomChildren so it isn't later removed in diffChildren\n\t\t\tif (\n\t\t\t\tvalue &&\n\t\t\t\t'setAttribute' in value == !!nodeType &&\n\t\t\t\t(nodeType ? value.localName == nodeType : value.nodeType == 3)\n\t\t\t) {\n\t\t\t\tdom = value;\n\t\t\t\texcessDomChildren[i] = NULL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (dom == NULL) {\n\t\tif (nodeType == NULL) {\n\t\t\treturn doc.createTextNode(newProps);\n\t\t}\n\n\t\tdom = doc.createElementNS(namespace, nodeType, newProps.is && newProps);\n\n\t\t// we are creating a new node, so we can assume this is a new subtree (in\n\t\t// case we are hydrating), this deopts the hydrate\n\t\tif (isHydrating) {\n\t\t\tif (options._hydrationMismatch)\n\t\t\t\toptions._hydrationMismatch(newVNode, excessDomChildren);\n\t\t\tisHydrating = false;\n\t\t}\n\t\t// we created a new parent, so none of the previously attached children can be reused:\n\t\texcessDomChildren = NULL;\n\t}\n\n\tif (nodeType == NULL) {\n\t\t// During hydration, we still have to split merged text from SSR'd HTML.\n\t\tif (oldProps !== newProps && (!isHydrating || dom.data != newProps)) {\n\t\t\tdom.data = newProps;\n\t\t}\n\t} else {\n\t\t// If excessDomChildren was not null, repopulate it with the current element's children:\n\t\texcessDomChildren = excessDomChildren && slice.call(dom.childNodes);\n\n\t\t// If we are in a situation where we are not hydrating but are using\n\t\t// existing DOM (e.g. replaceNode) we should read the existing DOM\n\t\t// attributes to diff them\n\t\tif (!isHydrating && excessDomChildren != NULL) {\n\t\t\toldProps = {};\n\t\t\tfor (i = 0; i < dom.attributes.length; i++) {\n\t\t\t\tvalue = dom.attributes[i];\n\t\t\t\toldProps[value.name] = value.value;\n\t\t\t}\n\t\t}\n\n\t\tfor (i in oldProps) {\n\t\t\tvalue = oldProps[i];\n\t\t\tif (i == 'dangerouslySetInnerHTML') {\n\t\t\t\toldHtml = value;\n\t\t\t} else if (\n\t\t\t\ti != 'children' &&\n\t\t\t\t!(i in newProps) &&\n\t\t\t\t!(i == 'value' && 'defaultValue' in newProps) &&\n\t\t\t\t!(i == 'checked' && 'defaultChecked' in newProps)\n\t\t\t) {\n\t\t\t\tsetProperty(dom, i, NULL, value, namespace);\n\t\t\t}\n\t\t}\n\n\t\t// During hydration, props are not diffed at all (including dangerouslySetInnerHTML)\n\t\t// @TODO we should warn in debug mode when props don't match here.\n\t\tconst shouldRevalidateProps = oldVNode._flags & FORCE_PROPS_REVALIDATE;\n\t\tfor (i in newProps) {\n\t\t\tvalue = newProps[i];\n\t\t\tif (i == 'children') {\n\t\t\t\tnewChildren = value;\n\t\t\t} else if (i == 'dangerouslySetInnerHTML') {\n\t\t\t\tnewHtml = value;\n\t\t\t} else if (i == 'value') {\n\t\t\t\tinputValue = value;\n\t\t\t} else if (i == 'checked') {\n\t\t\t\tchecked = value;\n\t\t\t} else if (\n\t\t\t\t(!isHydrating || typeof value == 'function') &&\n\t\t\t\t(oldProps[i] !== value || shouldRevalidateProps)\n\t\t\t) {\n\t\t\t\tsetProperty(dom, i, value, oldProps[i], namespace);\n\t\t\t}\n\t\t}\n\n\t\t// If the new vnode didn't have dangerouslySetInnerHTML, diff its children\n\t\tif (newHtml) {\n\t\t\t// Avoid re-applying the same '__html' if it did not changed between re-render\n\t\t\tif (\n\t\t\t\t!isHydrating &&\n\t\t\t\t(!oldHtml ||\n\t\t\t\t\t(newHtml.__html != oldHtml.__html && newHtml.__html != dom.innerHTML))\n\t\t\t) {\n\t\t\t\tdom.innerHTML = newHtml.__html;\n\t\t\t}\n\n\t\t\tnewVNode._children = [];\n\t\t} else {\n\t\t\tif (oldHtml) dom.innerHTML = '';\n\n\t\t\tif (\n\t\t\t\tnodeType == 'foreignObject' ||\n\t\t\t\t(namespace == MATH_NAMESPACE && MATHML_TOKEN_ELEMENTS.test(nodeType))\n\t\t\t) {\n\t\t\t\tnamespace = XHTML_NAMESPACE;\n\t\t\t}\n\n\t\t\tdiffChildren(\n\t\t\t\t// @ts-expect-error\n\t\t\t\tnodeType == 'template' ? dom.content : dom,\n\t\t\t\tisArray(newChildren) ? newChildren : [newChildren],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tnamespace,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\texcessDomChildren\n\t\t\t\t\t? excessDomChildren[0]\n\t\t\t\t\t: oldVNode._children && getDomSibling(oldVNode, 0),\n\t\t\t\tisHydrating,\n\t\t\t\trefQueue,\n\t\t\t\tdoc\n\t\t\t);\n\n\t\t\t// Remove children that are not part of any vnode.\n\t\t\tif (excessDomChildren != NULL) {\n\t\t\t\tfor (i = excessDomChildren.length; i--; ) {\n\t\t\t\t\tremoveNode(excessDomChildren[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// As above, don't diff props during hydration\n\t\tif (!isHydrating) {\n\t\t\ti = 'value';\n\t\t\tif (nodeType == 'progress' && inputValue == NULL) {\n\t\t\t\tdom.removeAttribute('value');\n\t\t\t} else if (\n\t\t\t\tinputValue != UNDEFINED &&\n\t\t\t\t// #2756 For the <progress>-element the initial value is 0,\n\t\t\t\t// despite the attribute not being present. When the attribute\n\t\t\t\t// is missing the progress bar is treated as indeterminate.\n\t\t\t\t// To fix that we'll always update it when it is 0 for progress elements\n\t\t\t\t(inputValue !== dom[i] || (nodeType === 'progress' && !inputValue))\n\t\t\t) {\n\t\t\t\tsetProperty(dom, i, inputValue, oldProps[i], namespace);\n\t\t\t}\n\n\t\t\ti = 'checked';\n\t\t\tif (checked != UNDEFINED && checked != dom[i]) {\n\t\t\t\tsetProperty(dom, i, checked, oldProps[i], namespace);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dom;\n}\n\n/**\n * Invoke or update a ref, depending on whether it is a function or object ref.\n * @param {Ref<any> & { _unmount?: unknown }} ref\n * @param {any} value\n * @param {VNode} vnode\n */\nexport function applyRef(ref, value, vnode) {\n\ttry {\n\t\tif (typeof ref == 'function') {\n\t\t\tif (typeof ref._unmount == 'function') {\n\t\t\t\tref._unmount();\n\t\t\t}\n\n\t\t\tif (typeof ref._unmount != 'function' || value != NULL) {\n\t\t\t\t// Store the cleanup function on the function\n\t\t\t\t// instance object itself to avoid shape\n\t\t\t\t// transitioning vnode\n\t\t\t\tref._unmount = ref(value);\n\t\t\t}\n\t\t} else ref.current = value;\n\t} catch (e) {\n\t\toptions._catchError(e, vnode);\n\t}\n}\n\n/**\n * Unmount a virtual node from the tree and apply DOM changes\n * @param {VNode} vnode The virtual node to unmount\n * @param {VNode} parentVNode The parent of the VNode that initiated the unmount\n * @param {boolean} [skipRemove] Flag that indicates that a parent node of the\n * current element is already detached from the DOM.\n */\nexport function unmount(vnode, parentVNode, skipRemove) {\n\tlet r;\n\tif (options.unmount) options.unmount(vnode);\n\n\tif ((r = vnode.ref) && (!r.current || r.current == vnode._dom)) {\n\t\tapplyRef(r, NULL, parentVNode);\n\t}\n\n\tif ((r = vnode._component) != NULL) {\n\t\tif (r.componentWillUnmount) {\n\t\t\ttry {\n\t\t\t\tr.componentWillUnmount();\n\t\t\t} catch (e) {\n\t\t\t\toptions._catchError(e, parentVNode);\n\t\t\t}\n\t\t}\n\n\t\tr._parentDom = NULL;\n\t}\n\n\tif ((r = vnode._children)) {\n\t\tfor (let i = 0; i < r.length; i++) {\n\t\t\tif (r[i]) {\n\t\t\t\tunmount(\n\t\t\t\t\tr[i],\n\t\t\t\t\tparentVNode,\n\t\t\t\t\tskipRemove || typeof vnode.type != 'function'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!skipRemove) {\n\t\tremoveNode(vnode._dom);\n\t}\n\n\tif (vnode._dom && vnode._dom._listeners) {\n\t\tvnode._dom._listeners = NULL;\n\t}\n\n\tvnode._dom = vnode._component = vnode._parent = NULL;\n}\n\n/** The `.render()` method for a PFC backing instance. */\nfunction doRender(props, state, context) {\n\treturn this.constructor(props, context);\n}\n"
  },
  {
    "path": "src/diff/props.js",
    "content": "import { NULL, SVG_NAMESPACE } from '../constants';\nimport options from '../options';\n\nfunction setStyle(style, key, value) {\n\tif (key[0] == '-') {\n\t\tstyle.setProperty(key, value == NULL ? '' : value);\n\t} else if (value == NULL) {\n\t\tstyle[key] = '';\n\t} else {\n\t\tstyle[key] = value;\n\t}\n}\n\nconst CAPTURE_REGEX = /(PointerCapture)$|Capture$/i;\n\n// A logical clock to solve issues like https://github.com/preactjs/preact/issues/3927.\n// When the DOM performs an event it leaves micro-ticks in between bubbling up which means that\n// an event can trigger on a newly reated DOM-node while the event bubbles up.\n//\n// Originally inspired by Vue\n// (https://github.com/vuejs/core/blob/caeb8a68811a1b0f79/packages/runtime-dom/src/modules/events.ts#L90-L101),\n// but modified to use a logical clock instead of Date.now() in case event handlers get attached\n// and events get dispatched during the same millisecond.\n//\n// The clock is incremented after each new event dispatch. This allows 1 000 000 new events\n// per second for over 280 years before the value reaches Number.MAX_SAFE_INTEGER (2**53 - 1).\nlet eventClock = 0;\n\n/**\n * Set a property value on a DOM node\n * @param {import('../internal').PreactElement} dom The DOM node to modify\n * @param {string} name The name of the property to set\n * @param {*} value The value to set the property to\n * @param {*} oldValue The old value the property had\n * @param {string} namespace Whether or not this DOM node is an SVG node or not\n */\nexport function setProperty(dom, name, value, oldValue, namespace) {\n\tlet useCapture;\n\n\to: if (name == 'style') {\n\t\tif (typeof value == 'string') {\n\t\t\tdom.style.cssText = value;\n\t\t} else {\n\t\t\tif (typeof oldValue == 'string') {\n\t\t\t\tdom.style.cssText = oldValue = '';\n\t\t\t}\n\n\t\t\tif (oldValue) {\n\t\t\t\tfor (name in oldValue) {\n\t\t\t\t\tif (!(value && name in value)) {\n\t\t\t\t\t\tsetStyle(dom.style, name, '');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (value) {\n\t\t\t\tfor (name in value) {\n\t\t\t\t\tif (!oldValue || value[name] != oldValue[name]) {\n\t\t\t\t\t\tsetStyle(dom.style, name, value[name]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6\n\telse if (name[0] == 'o' && name[1] == 'n') {\n\t\tuseCapture = name != (name = name.replace(CAPTURE_REGEX, '$1'));\n\n\t\t// Infer correct casing for DOM built-in events:\n\t\tname = name.slice(2).toLowerCase();\n\n\t\tif (!dom._listeners) dom._listeners = {};\n\t\tdom._listeners[name + useCapture] = value;\n\n\t\tif (value) {\n\t\t\tif (!oldValue) {\n\t\t\t\tvalue._attached = eventClock;\n\t\t\t\tdom.addEventListener(\n\t\t\t\t\tname,\n\t\t\t\t\tuseCapture ? eventProxyCapture : eventProxy,\n\t\t\t\t\tuseCapture\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tvalue._attached = oldValue._attached;\n\t\t\t}\n\t\t} else {\n\t\t\tdom.removeEventListener(\n\t\t\t\tname,\n\t\t\t\tuseCapture ? eventProxyCapture : eventProxy,\n\t\t\t\tuseCapture\n\t\t\t);\n\t\t}\n\t} else {\n\t\tif (namespace == SVG_NAMESPACE) {\n\t\t\t// Normalize incorrect prop usage for SVG:\n\t\t\t// - xlink:href / xlinkHref --> href (xlink:href was removed from SVG and isn't needed)\n\t\t\t// - className --> class\n\t\t\tname = name.replace(/xlink(H|:h)/, 'h').replace(/sName$/, 's');\n\t\t} else if (\n\t\t\tname != 'width' &&\n\t\t\tname != 'height' &&\n\t\t\tname != 'href' &&\n\t\t\tname != 'list' &&\n\t\t\tname != 'form' &&\n\t\t\t// Default value in browsers is `-1` and an empty string is\n\t\t\t// cast to `0` instead\n\t\t\tname != 'tabIndex' &&\n\t\t\tname != 'download' &&\n\t\t\tname != 'rowSpan' &&\n\t\t\tname != 'colSpan' &&\n\t\t\tname != 'role' &&\n\t\t\tname != 'popover' &&\n\t\t\tname in dom\n\t\t) {\n\t\t\ttry {\n\t\t\t\tdom[name] = value == NULL ? '' : value;\n\t\t\t\t// labelled break is 1b smaller here than a return statement (sorry)\n\t\t\t\tbreak o;\n\t\t\t} catch (e) {}\n\t\t}\n\n\t\t// aria- and data- attributes have no boolean representation.\n\t\t// A `false` value is different from the attribute not being\n\t\t// present, so we can't remove it. For non-boolean aria\n\t\t// attributes we could treat false as a removal, but the\n\t\t// amount of exceptions would cost too many bytes. On top of\n\t\t// that other frameworks generally stringify `false`.\n\n\t\tif (typeof value == 'function') {\n\t\t\t// never serialize functions as attribute values\n\t\t} else if (value != NULL && (value !== false || name[4] == '-')) {\n\t\t\tdom.setAttribute(name, name == 'popover' && value == true ? '' : value);\n\t\t} else {\n\t\t\tdom.removeAttribute(name);\n\t\t}\n\t}\n}\n\n/**\n * Create an event proxy function.\n * @param {boolean} useCapture Is the event handler for the capture phase.\n * @private\n */\nfunction createEventProxy(useCapture) {\n\t/**\n\t * Proxy an event to hooked event handlers\n\t * @param {import('../internal').PreactEvent} e The event object from the browser\n\t * @private\n\t */\n\treturn function (e) {\n\t\tif (this._listeners) {\n\t\t\tconst eventHandler = this._listeners[e.type + useCapture];\n\t\t\tif (e._dispatched == NULL) {\n\t\t\t\te._dispatched = eventClock++;\n\n\t\t\t\t// When `e._dispatched` is smaller than the time when the targeted event\n\t\t\t\t// handler was attached we know we have bubbled up to an element that was added\n\t\t\t\t// during patching the DOM.\n\t\t\t} else if (e._dispatched < eventHandler._attached) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn eventHandler(options.event ? options.event(e) : e);\n\t\t}\n\t};\n}\n\nconst eventProxy = createEventProxy(false);\nconst eventProxyCapture = createEventProxy(true);\n"
  },
  {
    "path": "src/dom.d.ts",
    "content": "// Most of our DOM-ish types\n\nimport { ClassAttributes, PreactDOMAttributes } from './index';\n\n// Implementations of some DOM events that are not available in TS 5.1\ninterface ToggleEvent extends Event {\n\treadonly newState: string;\n\treadonly oldState: string;\n}\n\ndeclare var ToggleEvent: {\n\tprototype: ToggleEvent;\n\tnew (type: string, eventInitDict?: ToggleEventInit): ToggleEvent;\n};\n\ninterface ToggleEventInit extends EventInit {\n\tnewState?: string;\n\toldState?: string;\n}\n\ninterface CommandEvent extends Event {\n\treadonly source: Element | null;\n\treadonly command: string;\n}\n\ndeclare var CommandEvent: {\n\tprototype: CommandEvent;\n\tnew (type: string, eventInitDict?: CommandEventInit): CommandEvent;\n};\n\ninterface CommandEventInit extends EventInit {\n\tsource: Element | null;\n\tcommand: string;\n}\n\n/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/SnapEvent) */\ninterface SnapEvent extends Event {\n  readonly snapTargetBlock: Element | null;\n  readonly snapTargetInline: Element | null;\n}\n\ndeclare var SnapEvent: {\n  prototype: SnapEvent;\n  new (type: string, eventInitDict?: SnapEventInit): SnapEvent;\n}\n\ninterface SnapEventInit extends EventInit {\n  snapTargetBlock?: Element | null;\n  snapTargetInline?: Element | null;\n}\n\ntype Booleanish = boolean | 'true' | 'false';\n\nexport interface SignalLike<T> {\n\tvalue: T;\n\tpeek(): T;\n\tsubscribe(fn: (value: T) => void): () => void;\n}\n\nexport type Signalish<T> = T | SignalLike<T>;\n\nexport type UnpackSignal<T> = T extends SignalLike<infer V> ? V : T;\n\nexport type DOMCSSProperties = {\n\t[key in keyof Omit<\n\t\tCSSStyleDeclaration,\n\t\t| 'item'\n\t\t| 'setProperty'\n\t\t| 'removeProperty'\n\t\t| 'getPropertyValue'\n\t\t| 'getPropertyPriority'\n\t>]?: string | number | null | undefined;\n};\nexport type AllCSSProperties = {\n\t[key: string]: string | number | null | undefined;\n};\nexport interface CSSProperties extends AllCSSProperties, DOMCSSProperties {\n\tcssText?: string | null;\n}\n\nexport interface SVGAttributes<Target extends EventTarget = SVGElement>\n\textends HTMLAttributes<Target> {\n\taccentHeight?: Signalish<number | string | undefined>;\n\taccumulate?: Signalish<'none' | 'sum' | undefined>;\n\tadditive?: Signalish<'replace' | 'sum' | undefined>;\n\talignmentBaseline?: Signalish<\n\t\t| 'auto'\n\t\t| 'baseline'\n\t\t| 'before-edge'\n\t\t| 'text-before-edge'\n\t\t| 'middle'\n\t\t| 'central'\n\t\t| 'after-edge'\n\t\t| 'text-after-edge'\n\t\t| 'ideographic'\n\t\t| 'alphabetic'\n\t\t| 'hanging'\n\t\t| 'mathematical'\n\t\t| 'inherit'\n\t\t| undefined\n\t>;\n\t'alignment-baseline'?: Signalish<\n\t\t| 'auto'\n\t\t| 'baseline'\n\t\t| 'before-edge'\n\t\t| 'text-before-edge'\n\t\t| 'middle'\n\t\t| 'central'\n\t\t| 'after-edge'\n\t\t| 'text-after-edge'\n\t\t| 'ideographic'\n\t\t| 'alphabetic'\n\t\t| 'hanging'\n\t\t| 'mathematical'\n\t\t| 'inherit'\n\t\t| undefined\n\t>;\n\tallowReorder?: Signalish<'no' | 'yes' | undefined>;\n\t'allow-reorder'?: Signalish<'no' | 'yes' | undefined>;\n\talphabetic?: Signalish<number | string | undefined>;\n\tamplitude?: Signalish<number | string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/arabic-form */\n\tarabicForm?: Signalish<\n\t\t'initial' | 'medial' | 'terminal' | 'isolated' | undefined\n\t>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/arabic-form */\n\t'arabic-form'?: Signalish<\n\t\t'initial' | 'medial' | 'terminal' | 'isolated' | undefined\n\t>;\n\tascent?: Signalish<number | string | undefined>;\n\tattributeName?: Signalish<string | undefined>;\n\tattributeType?: Signalish<string | undefined>;\n\tazimuth?: Signalish<number | string | undefined>;\n\tbaseFrequency?: Signalish<number | string | undefined>;\n\tbaselineShift?: Signalish<number | string | undefined>;\n\t'baseline-shift'?: Signalish<number | string | undefined>;\n\tbaseProfile?: Signalish<number | string | undefined>;\n\tbbox?: Signalish<number | string | undefined>;\n\tbegin?: Signalish<number | string | undefined>;\n\tbias?: Signalish<number | string | undefined>;\n\tby?: Signalish<number | string | undefined>;\n\tcalcMode?: Signalish<number | string | undefined>;\n\tcapHeight?: Signalish<number | string | undefined>;\n\t'cap-height'?: Signalish<number | string | undefined>;\n\tclip?: Signalish<number | string | undefined>;\n\tclipPath?: Signalish<string | undefined>;\n\t'clip-path'?: Signalish<string | undefined>;\n\tclipPathUnits?: Signalish<number | string | undefined>;\n\tclipRule?: Signalish<number | string | undefined>;\n\t'clip-rule'?: Signalish<number | string | undefined>;\n\tcolorInterpolation?: Signalish<number | string | undefined>;\n\t'color-interpolation'?: Signalish<number | string | undefined>;\n\tcolorInterpolationFilters?: Signalish<\n\t\t'auto' | 'sRGB' | 'linearRGB' | 'inherit' | undefined\n\t>;\n\t'color-interpolation-filters'?: Signalish<\n\t\t'auto' | 'sRGB' | 'linearRGB' | 'inherit' | undefined\n\t>;\n\tcolorProfile?: Signalish<number | string | undefined>;\n\t'color-profile'?: Signalish<number | string | undefined>;\n\tcolorRendering?: Signalish<number | string | undefined>;\n\t'color-rendering'?: Signalish<number | string | undefined>;\n\tcontentScriptType?: Signalish<number | string | undefined>;\n\t'content-script-type'?: Signalish<number | string | undefined>;\n\tcontentStyleType?: Signalish<number | string | undefined>;\n\t'content-style-type'?: Signalish<number | string | undefined>;\n\tcursor?: Signalish<number | string | undefined>;\n\tcx?: Signalish<number | string | undefined>;\n\tcy?: Signalish<number | string | undefined>;\n\td?: Signalish<string | undefined>;\n\tdecelerate?: Signalish<number | string | undefined>;\n\tdescent?: Signalish<number | string | undefined>;\n\tdiffuseConstant?: Signalish<number | string | undefined>;\n\tdirection?: Signalish<number | string | undefined>;\n\tdisplay?: Signalish<number | string | undefined>;\n\tdivisor?: Signalish<number | string | undefined>;\n\tdominantBaseline?: Signalish<number | string | undefined>;\n\t'dominant-baseline'?: Signalish<number | string | undefined>;\n\tdur?: Signalish<number | string | undefined>;\n\tdx?: Signalish<number | string | undefined>;\n\tdy?: Signalish<number | string | undefined>;\n\tedgeMode?: Signalish<number | string | undefined>;\n\televation?: Signalish<number | string | undefined>;\n\tenableBackground?: Signalish<number | string | undefined>;\n\t'enable-background'?: Signalish<number | string | undefined>;\n\tend?: Signalish<number | string | undefined>;\n\texponent?: Signalish<number | string | undefined>;\n\texternalResourcesRequired?: Signalish<number | string | undefined>;\n\tfill?: Signalish<string | undefined>;\n\tfillOpacity?: Signalish<number | string | undefined>;\n\t'fill-opacity'?: Signalish<number | string | undefined>;\n\tfillRule?: Signalish<'nonzero' | 'evenodd' | 'inherit' | undefined>;\n\t'fill-rule'?: Signalish<'nonzero' | 'evenodd' | 'inherit' | undefined>;\n\tfilter?: Signalish<string | undefined>;\n\tfilterRes?: Signalish<number | string | undefined>;\n\tfilterUnits?: Signalish<number | string | undefined>;\n\tfloodColor?: Signalish<number | string | undefined>;\n\t'flood-color'?: Signalish<number | string | undefined>;\n\tfloodOpacity?: Signalish<number | string | undefined>;\n\t'flood-opacity'?: Signalish<number | string | undefined>;\n\tfocusable?: Signalish<number | string | undefined>;\n\tfontFamily?: Signalish<string | undefined>;\n\t'font-family'?: Signalish<string | undefined>;\n\tfontSize?: Signalish<number | string | undefined>;\n\t'font-size'?: Signalish<number | string | undefined>;\n\tfontSizeAdjust?: Signalish<number | string | undefined>;\n\t'font-size-adjust'?: Signalish<number | string | undefined>;\n\tfontStretch?: Signalish<number | string | undefined>;\n\t'font-stretch'?: Signalish<number | string | undefined>;\n\tfontStyle?: Signalish<number | string | undefined>;\n\t'font-style'?: Signalish<number | string | undefined>;\n\tfontVariant?: Signalish<number | string | undefined>;\n\t'font-variant'?: Signalish<number | string | undefined>;\n\tfontWeight?: Signalish<number | string | undefined>;\n\t'font-weight'?: Signalish<number | string | undefined>;\n\tformat?: Signalish<number | string | undefined>;\n\tfrom?: Signalish<number | string | undefined>;\n\tfx?: Signalish<number | string | undefined>;\n\tfy?: Signalish<number | string | undefined>;\n\tg1?: Signalish<number | string | undefined>;\n\tg2?: Signalish<number | string | undefined>;\n\tglyphName?: Signalish<number | string | undefined>;\n\t'glyph-name'?: Signalish<number | string | undefined>;\n\tglyphOrientationHorizontal?: Signalish<number | string | undefined>;\n\t'glyph-orientation-horizontal'?: Signalish<number | string | undefined>;\n\tglyphOrientationVertical?: Signalish<number | string | undefined>;\n\t'glyph-orientation-vertical'?: Signalish<number | string | undefined>;\n\tglyphRef?: Signalish<number | string | undefined>;\n\tgradientTransform?: Signalish<string | undefined>;\n\tgradientUnits?: Signalish<string | undefined>;\n\thanging?: Signalish<number | string | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\thorizAdvX?: Signalish<number | string | undefined>;\n\t'horiz-adv-x'?: Signalish<number | string | undefined>;\n\thorizOriginX?: Signalish<number | string | undefined>;\n\t'horiz-origin-x'?: Signalish<number | string | undefined>;\n\thref?: Signalish<string | undefined>;\n\threflang?: Signalish<string | undefined>;\n\threfLang?: Signalish<string | undefined>;\n\tideographic?: Signalish<number | string | undefined>;\n\timageRendering?: Signalish<number | string | undefined>;\n\t'image-rendering'?: Signalish<number | string | undefined>;\n\tin2?: Signalish<number | string | undefined>;\n\tin?: Signalish<string | undefined>;\n\tintercept?: Signalish<number | string | undefined>;\n\tk1?: Signalish<number | string | undefined>;\n\tk2?: Signalish<number | string | undefined>;\n\tk3?: Signalish<number | string | undefined>;\n\tk4?: Signalish<number | string | undefined>;\n\tk?: Signalish<number | string | undefined>;\n\tkernelMatrix?: Signalish<number | string | undefined>;\n\tkernelUnitLength?: Signalish<number | string | undefined>;\n\tkerning?: Signalish<number | string | undefined>;\n\tkeyPoints?: Signalish<number | string | undefined>;\n\tkeySplines?: Signalish<number | string | undefined>;\n\tkeyTimes?: Signalish<number | string | undefined>;\n\tlengthAdjust?: Signalish<number | string | undefined>;\n\tletterSpacing?: Signalish<number | string | undefined>;\n\t'letter-spacing'?: Signalish<number | string | undefined>;\n\tlightingColor?: Signalish<number | string | undefined>;\n\t'lighting-color'?: Signalish<number | string | undefined>;\n\tlimitingConeAngle?: Signalish<number | string | undefined>;\n\tlocal?: Signalish<number | string | undefined>;\n\tmarkerEnd?: Signalish<string | undefined>;\n\t'marker-end'?: Signalish<string | undefined>;\n\tmarkerHeight?: Signalish<number | string | undefined>;\n\tmarkerMid?: Signalish<string | undefined>;\n\t'marker-mid'?: Signalish<string | undefined>;\n\tmarkerStart?: Signalish<string | undefined>;\n\t'marker-start'?: Signalish<string | undefined>;\n\tmarkerUnits?: Signalish<number | string | undefined>;\n\tmarkerWidth?: Signalish<number | string | undefined>;\n\tmask?: Signalish<string | undefined>;\n\tmaskContentUnits?: Signalish<number | string | undefined>;\n\tmaskUnits?: Signalish<number | string | undefined>;\n\tmathematical?: Signalish<number | string | undefined>;\n\tmode?: Signalish<number | string | undefined>;\n\tnumOctaves?: Signalish<number | string | undefined>;\n\toffset?: Signalish<number | string | undefined>;\n\topacity?: Signalish<number | string | undefined>;\n\toperator?: Signalish<number | string | undefined>;\n\torder?: Signalish<number | string | undefined>;\n\torient?: Signalish<number | string | undefined>;\n\torientation?: Signalish<number | string | undefined>;\n\torigin?: Signalish<number | string | undefined>;\n\toverflow?: Signalish<number | string | undefined>;\n\toverlinePosition?: Signalish<number | string | undefined>;\n\t'overline-position'?: Signalish<number | string | undefined>;\n\toverlineThickness?: Signalish<number | string | undefined>;\n\t'overline-thickness'?: Signalish<number | string | undefined>;\n\tpaintOrder?: Signalish<number | string | undefined>;\n\t'paint-order'?: Signalish<number | string | undefined>;\n\tpanose1?: Signalish<number | string | undefined>;\n\t'panose-1'?: Signalish<number | string | undefined>;\n\tpathLength?: Signalish<number | string | undefined>;\n\tpatternContentUnits?: Signalish<string | undefined>;\n\tpatternTransform?: Signalish<number | string | undefined>;\n\tpatternUnits?: Signalish<string | undefined>;\n\tpointerEvents?: Signalish<number | string | undefined>;\n\t'pointer-events'?: Signalish<number | string | undefined>;\n\tpoints?: Signalish<string | undefined>;\n\tpointsAtX?: Signalish<number | string | undefined>;\n\tpointsAtY?: Signalish<number | string | undefined>;\n\tpointsAtZ?: Signalish<number | string | undefined>;\n\tpreserveAlpha?: Signalish<number | string | undefined>;\n\tpreserveAspectRatio?: Signalish<string | undefined>;\n\tprimitiveUnits?: Signalish<number | string | undefined>;\n\tr?: Signalish<number | string | undefined>;\n\tradius?: Signalish<number | string | undefined>;\n\trefX?: Signalish<number | string | undefined>;\n\trefY?: Signalish<number | string | undefined>;\n\trenderingIntent?: Signalish<number | string | undefined>;\n\t'rendering-intent'?: Signalish<number | string | undefined>;\n\trepeatCount?: Signalish<number | string | undefined>;\n\t'repeat-count'?: Signalish<number | string | undefined>;\n\trepeatDur?: Signalish<number | string | undefined>;\n\t'repeat-dur'?: Signalish<number | string | undefined>;\n\trequiredExtensions?: Signalish<number | string | undefined>;\n\trequiredFeatures?: Signalish<number | string | undefined>;\n\trestart?: Signalish<number | string | undefined>;\n\tresult?: Signalish<string | undefined>;\n\trotate?: Signalish<number | string | undefined>;\n\trx?: Signalish<number | string | undefined>;\n\try?: Signalish<number | string | undefined>;\n\tscale?: Signalish<number | string | undefined>;\n\tseed?: Signalish<number | string | undefined>;\n\tshapeRendering?: Signalish<number | string | undefined>;\n\t'shape-rendering'?: Signalish<number | string | undefined>;\n\tslope?: Signalish<number | string | undefined>;\n\tspacing?: Signalish<number | string | undefined>;\n\tspecularConstant?: Signalish<number | string | undefined>;\n\tspecularExponent?: Signalish<number | string | undefined>;\n\tspeed?: Signalish<number | string | undefined>;\n\tspreadMethod?: Signalish<string | undefined>;\n\tstartOffset?: Signalish<number | string | undefined>;\n\tstdDeviation?: Signalish<number | string | undefined>;\n\tstemh?: Signalish<number | string | undefined>;\n\tstemv?: Signalish<number | string | undefined>;\n\tstitchTiles?: Signalish<number | string | undefined>;\n\tstopColor?: Signalish<string | undefined>;\n\t'stop-color'?: Signalish<string | undefined>;\n\tstopOpacity?: Signalish<number | string | undefined>;\n\t'stop-opacity'?: Signalish<number | string | undefined>;\n\tstrikethroughPosition?: Signalish<number | string | undefined>;\n\t'strikethrough-position'?: Signalish<number | string | undefined>;\n\tstrikethroughThickness?: Signalish<number | string | undefined>;\n\t'strikethrough-thickness'?: Signalish<number | string | undefined>;\n\tstring?: Signalish<number | string | undefined>;\n\tstroke?: Signalish<string | undefined>;\n\tstrokeDasharray?: Signalish<string | number | undefined>;\n\t'stroke-dasharray'?: Signalish<string | number | undefined>;\n\tstrokeDashoffset?: Signalish<string | number | undefined>;\n\t'stroke-dashoffset'?: Signalish<string | number | undefined>;\n\tstrokeLinecap?: Signalish<\n\t\t'butt' | 'round' | 'square' | 'inherit' | undefined\n\t>;\n\t'stroke-linecap'?: Signalish<\n\t\t'butt' | 'round' | 'square' | 'inherit' | undefined\n\t>;\n\tstrokeLinejoin?: Signalish<\n\t\t'miter' | 'round' | 'bevel' | 'inherit' | undefined\n\t>;\n\t'stroke-linejoin'?: Signalish<\n\t\t'miter' | 'round' | 'bevel' | 'inherit' | undefined\n\t>;\n\tstrokeMiterlimit?: Signalish<string | number | undefined>;\n\t'stroke-miterlimit'?: Signalish<string | number | undefined>;\n\tstrokeOpacity?: Signalish<number | string | undefined>;\n\t'stroke-opacity'?: Signalish<number | string | undefined>;\n\tstrokeWidth?: Signalish<number | string | undefined>;\n\t'stroke-width'?: Signalish<number | string | undefined>;\n\tsurfaceScale?: Signalish<number | string | undefined>;\n\tsystemLanguage?: Signalish<number | string | undefined>;\n\ttableValues?: Signalish<number | string | undefined>;\n\ttargetX?: Signalish<number | string | undefined>;\n\ttargetY?: Signalish<number | string | undefined>;\n\ttextAnchor?: Signalish<string | undefined>;\n\t'text-anchor'?: Signalish<string | undefined>;\n\ttextDecoration?: Signalish<number | string | undefined>;\n\t'text-decoration'?: Signalish<number | string | undefined>;\n\ttextLength?: Signalish<number | string | undefined>;\n\ttextRendering?: Signalish<number | string | undefined>;\n\t'text-rendering'?: Signalish<number | string | undefined>;\n\tto?: Signalish<number | string | undefined>;\n\ttransform?: Signalish<string | undefined>;\n\ttransformOrigin?: Signalish<string | undefined>;\n\t'transform-origin'?: Signalish<string | undefined>;\n\ttype?: Signalish<string | undefined>;\n\tu1?: Signalish<number | string | undefined>;\n\tu2?: Signalish<number | string | undefined>;\n\tunderlinePosition?: Signalish<number | string | undefined>;\n\t'underline-position'?: Signalish<number | string | undefined>;\n\tunderlineThickness?: Signalish<number | string | undefined>;\n\t'underline-thickness'?: Signalish<number | string | undefined>;\n\tunicode?: Signalish<number | string | undefined>;\n\tunicodeBidi?: Signalish<number | string | undefined>;\n\t'unicode-bidi'?: Signalish<number | string | undefined>;\n\tunicodeRange?: Signalish<number | string | undefined>;\n\t'unicode-range'?: Signalish<number | string | undefined>;\n\tunitsPerEm?: Signalish<number | string | undefined>;\n\t'units-per-em'?: Signalish<number | string | undefined>;\n\tvAlphabetic?: Signalish<number | string | undefined>;\n\t'v-alphabetic'?: Signalish<number | string | undefined>;\n\tvalues?: Signalish<string | undefined>;\n\tvectorEffect?: Signalish<number | string | undefined>;\n\t'vector-effect'?: Signalish<number | string | undefined>;\n\tversion?: Signalish<string | undefined>;\n\tvertAdvY?: Signalish<number | string | undefined>;\n\t'vert-adv-y'?: Signalish<number | string | undefined>;\n\tvertOriginX?: Signalish<number | string | undefined>;\n\t'vert-origin-x'?: Signalish<number | string | undefined>;\n\tvertOriginY?: Signalish<number | string | undefined>;\n\t'vert-origin-y'?: Signalish<number | string | undefined>;\n\tvHanging?: Signalish<number | string | undefined>;\n\t'v-hanging'?: Signalish<number | string | undefined>;\n\tvIdeographic?: Signalish<number | string | undefined>;\n\t'v-ideographic'?: Signalish<number | string | undefined>;\n\tviewBox?: Signalish<string | undefined>;\n\tviewTarget?: Signalish<number | string | undefined>;\n\tvisibility?: Signalish<number | string | undefined>;\n\tvMathematical?: Signalish<number | string | undefined>;\n\t'v-mathematical'?: Signalish<number | string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n\twordSpacing?: Signalish<number | string | undefined>;\n\t'word-spacing'?: Signalish<number | string | undefined>;\n\twritingMode?: Signalish<number | string | undefined>;\n\t'writing-mode'?: Signalish<number | string | undefined>;\n\tx1?: Signalish<number | string | undefined>;\n\tx2?: Signalish<number | string | undefined>;\n\tx?: Signalish<number | string | undefined>;\n\txChannelSelector?: Signalish<string | undefined>;\n\txHeight?: Signalish<number | string | undefined>;\n\t'x-height'?: Signalish<number | string | undefined>;\n\txlinkActuate?: Signalish<string | undefined>;\n\t'xlink:actuate'?: Signalish<SVGAttributes['xlinkActuate']>;\n\txlinkArcrole?: Signalish<string | undefined>;\n\t'xlink:arcrole'?: Signalish<string | undefined>;\n\txlinkHref?: Signalish<string | undefined>;\n\t'xlink:href'?: Signalish<string | undefined>;\n\txlinkRole?: Signalish<string | undefined>;\n\t'xlink:role'?: Signalish<string | undefined>;\n\txlinkShow?: Signalish<string | undefined>;\n\t'xlink:show'?: Signalish<string | undefined>;\n\txlinkTitle?: Signalish<string | undefined>;\n\t'xlink:title'?: Signalish<string | undefined>;\n\txlinkType?: Signalish<string | undefined>;\n\t'xlink:type'?: Signalish<string | undefined>;\n\txmlBase?: Signalish<string | undefined>;\n\t'xml:base'?: Signalish<string | undefined>;\n\txmlLang?: Signalish<string | undefined>;\n\t'xml:lang'?: Signalish<string | undefined>;\n\txmlns?: Signalish<string | undefined>;\n\txmlnsXlink?: Signalish<string | undefined>;\n\txmlSpace?: Signalish<string | undefined>;\n\t'xml:space'?: Signalish<string | undefined>;\n\ty1?: Signalish<number | string | undefined>;\n\ty2?: Signalish<number | string | undefined>;\n\ty?: Signalish<number | string | undefined>;\n\tyChannelSelector?: Signalish<string | undefined>;\n\tz?: Signalish<number | string | undefined>;\n\tzoomAndPan?: Signalish<string | undefined>;\n}\n\nexport interface PathAttributes {\n\td: string;\n}\n\nexport type TargetedEvent<\n\tTarget extends EventTarget = EventTarget,\n\tTypedEvent extends Event = Event\n> = Omit<TypedEvent, 'currentTarget'> & {\n\treadonly currentTarget: Target;\n};\n\nexport type TargetedAnimationEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tAnimationEvent\n>;\nexport type TargetedClipboardEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tClipboardEvent\n>;\nexport type TargetedCommandEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tCommandEvent\n>;\nexport type TargetedCompositionEvent<Target extends EventTarget> =\n\tTargetedEvent<Target, CompositionEvent>;\nexport type TargetedDragEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tDragEvent\n>;\nexport type TargetedFocusEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tFocusEvent\n>;\nexport type TargetedInputEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tInputEvent\n>;\nexport type TargetedKeyboardEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tKeyboardEvent\n>;\nexport type TargetedMouseEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tMouseEvent\n>;\nexport type TargetedPointerEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tPointerEvent\n>;\nexport type TargetedSnapEvent<Target extends EventTarget> = TargetedEvent<\n    Target,\n    SnapEvent\n>;\nexport type TargetedSubmitEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tSubmitEvent\n>;\nexport type TargetedTouchEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tTouchEvent\n>;\nexport type TargetedToggleEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tToggleEvent\n>;\nexport type TargetedTransitionEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tTransitionEvent\n>;\nexport type TargetedUIEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tUIEvent\n>;\nexport type TargetedWheelEvent<Target extends EventTarget> = TargetedEvent<\n\tTarget,\n\tWheelEvent\n>;\nexport type TargetedPictureInPictureEvent<Target extends EventTarget> =\n\tTargetedEvent<Target, PictureInPictureEvent>;\n\nexport type EventHandler<E extends TargetedEvent> = {\n\tbivarianceHack(event: E): void;\n}['bivarianceHack'];\n\nexport type AnimationEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedAnimationEvent<Target>\n>;\nexport type ClipboardEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedClipboardEvent<Target>\n>;\nexport type CommandEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedCommandEvent<Target>\n>;\nexport type CompositionEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedCompositionEvent<Target>\n>;\nexport type DragEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedDragEvent<Target>\n>;\nexport type ToggleEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedToggleEvent<Target>\n>;\nexport type FocusEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedFocusEvent<Target>\n>;\nexport type GenericEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedEvent<Target>\n>;\nexport type InputEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedInputEvent<Target>\n>;\nexport type KeyboardEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedKeyboardEvent<Target>\n>;\nexport type MouseEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedMouseEvent<Target>\n>;\nexport type PointerEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedPointerEvent<Target>\n>;\nexport type SnapEventHandler<Target extends EventTarget> = EventHandler<\n    TargetedSnapEvent<Target>\n>;\nexport type SubmitEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedSubmitEvent<Target>\n>;\nexport type TouchEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedTouchEvent<Target>\n>;\nexport type TransitionEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedTransitionEvent<Target>\n>;\nexport type UIEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedUIEvent<Target>\n>;\nexport type WheelEventHandler<Target extends EventTarget> = EventHandler<\n\tTargetedWheelEvent<Target>\n>;\nexport type PictureInPictureEventHandler<Target extends EventTarget> =\n\tEventHandler<TargetedPictureInPictureEvent<Target>>;\n\nexport interface DOMAttributes<Target extends EventTarget>\n\textends PreactDOMAttributes {\n\t// Image Events\n\tonLoad?: GenericEventHandler<Target> | undefined;\n\tonLoadCapture?: GenericEventHandler<Target> | undefined;\n\tonError?: GenericEventHandler<Target> | undefined;\n\tonErrorCapture?: GenericEventHandler<Target> | undefined;\n\n\t// Clipboard Events\n\tonCopy?: ClipboardEventHandler<Target> | undefined;\n\tonCopyCapture?: ClipboardEventHandler<Target> | undefined;\n\tonCut?: ClipboardEventHandler<Target> | undefined;\n\tonCutCapture?: ClipboardEventHandler<Target> | undefined;\n\tonPaste?: ClipboardEventHandler<Target> | undefined;\n\tonPasteCapture?: ClipboardEventHandler<Target> | undefined;\n\n\t// Composition Events\n\tonCompositionEnd?: CompositionEventHandler<Target> | undefined;\n\tonCompositionEndCapture?: CompositionEventHandler<Target> | undefined;\n\tonCompositionStart?: CompositionEventHandler<Target> | undefined;\n\tonCompositionStartCapture?: CompositionEventHandler<Target> | undefined;\n\tonCompositionUpdate?: CompositionEventHandler<Target> | undefined;\n\tonCompositionUpdateCapture?: CompositionEventHandler<Target> | undefined;\n\n\t// Popover Events\n\tonBeforeToggle?: ToggleEventHandler<Target> | undefined;\n\tonToggle?: ToggleEventHandler<Target> | undefined;\n\n\t// Dialog Events\n\tonClose?: GenericEventHandler<Target> | undefined;\n\tonCancel?: GenericEventHandler<Target> | undefined;\n\n\t// Focus Events\n\tonFocus?: FocusEventHandler<Target> | undefined;\n\tonFocusCapture?: FocusEventHandler<Target> | undefined;\n\tonFocusIn?: FocusEventHandler<Target> | undefined;\n\tonFocusInCapture?: FocusEventHandler<Target> | undefined;\n\tonFocusOut?: FocusEventHandler<Target> | undefined;\n\tonFocusOutCapture?: FocusEventHandler<Target> | undefined;\n\tonBlur?: FocusEventHandler<Target> | undefined;\n\tonBlurCapture?: FocusEventHandler<Target> | undefined;\n\n\t// Form Events\n\tonChange?: GenericEventHandler<Target> | undefined;\n\tonChangeCapture?: GenericEventHandler<Target> | undefined;\n\tonInput?: InputEventHandler<Target> | undefined;\n\tonInputCapture?: InputEventHandler<Target> | undefined;\n\tonBeforeInput?: InputEventHandler<Target> | undefined;\n\tonBeforeInputCapture?: InputEventHandler<Target> | undefined;\n\tonSearch?: GenericEventHandler<Target> | undefined;\n\tonSearchCapture?: GenericEventHandler<Target> | undefined;\n\tonSubmit?: SubmitEventHandler<Target> | undefined;\n\tonSubmitCapture?: SubmitEventHandler<Target> | undefined;\n\tonInvalid?: GenericEventHandler<Target> | undefined;\n\tonInvalidCapture?: GenericEventHandler<Target> | undefined;\n\tonReset?: GenericEventHandler<Target> | undefined;\n\tonResetCapture?: GenericEventHandler<Target> | undefined;\n\tonFormData?: GenericEventHandler<Target> | undefined;\n\tonFormDataCapture?: GenericEventHandler<Target> | undefined;\n\n\t// Keyboard Events\n\tonKeyDown?: KeyboardEventHandler<Target> | undefined;\n\tonKeyDownCapture?: KeyboardEventHandler<Target> | undefined;\n\tonKeyPress?: KeyboardEventHandler<Target> | undefined;\n\tonKeyPressCapture?: KeyboardEventHandler<Target> | undefined;\n\tonKeyUp?: KeyboardEventHandler<Target> | undefined;\n\tonKeyUpCapture?: KeyboardEventHandler<Target> | undefined;\n\n\t// Media Events\n\tonAbort?: GenericEventHandler<Target> | undefined;\n\tonAbortCapture?: GenericEventHandler<Target> | undefined;\n\tonCanPlay?: GenericEventHandler<Target> | undefined;\n\tonCanPlayCapture?: GenericEventHandler<Target> | undefined;\n\tonCanPlayThrough?: GenericEventHandler<Target> | undefined;\n\tonCanPlayThroughCapture?: GenericEventHandler<Target> | undefined;\n\tonDurationChange?: GenericEventHandler<Target> | undefined;\n\tonDurationChangeCapture?: GenericEventHandler<Target> | undefined;\n\tonEmptied?: GenericEventHandler<Target> | undefined;\n\tonEmptiedCapture?: GenericEventHandler<Target> | undefined;\n\tonEncrypted?: GenericEventHandler<Target> | undefined;\n\tonEncryptedCapture?: GenericEventHandler<Target> | undefined;\n\tonEnded?: GenericEventHandler<Target> | undefined;\n\tonEndedCapture?: GenericEventHandler<Target> | undefined;\n\tonLoadedData?: GenericEventHandler<Target> | undefined;\n\tonLoadedDataCapture?: GenericEventHandler<Target> | undefined;\n\tonLoadedMetadata?: GenericEventHandler<Target> | undefined;\n\tonLoadedMetadataCapture?: GenericEventHandler<Target> | undefined;\n\tonLoadStart?: GenericEventHandler<Target> | undefined;\n\tonLoadStartCapture?: GenericEventHandler<Target> | undefined;\n\tonPause?: GenericEventHandler<Target> | undefined;\n\tonPauseCapture?: GenericEventHandler<Target> | undefined;\n\tonPlay?: GenericEventHandler<Target> | undefined;\n\tonPlayCapture?: GenericEventHandler<Target> | undefined;\n\tonPlaying?: GenericEventHandler<Target> | undefined;\n\tonPlayingCapture?: GenericEventHandler<Target> | undefined;\n\tonProgress?: GenericEventHandler<Target> | undefined;\n\tonProgressCapture?: GenericEventHandler<Target> | undefined;\n\tonRateChange?: GenericEventHandler<Target> | undefined;\n\tonRateChangeCapture?: GenericEventHandler<Target> | undefined;\n\tonSeeked?: GenericEventHandler<Target> | undefined;\n\tonSeekedCapture?: GenericEventHandler<Target> | undefined;\n\tonSeeking?: GenericEventHandler<Target> | undefined;\n\tonSeekingCapture?: GenericEventHandler<Target> | undefined;\n\tonStalled?: GenericEventHandler<Target> | undefined;\n\tonStalledCapture?: GenericEventHandler<Target> | undefined;\n\tonSuspend?: GenericEventHandler<Target> | undefined;\n\tonSuspendCapture?: GenericEventHandler<Target> | undefined;\n\tonTimeUpdate?: GenericEventHandler<Target> | undefined;\n\tonTimeUpdateCapture?: GenericEventHandler<Target> | undefined;\n\tonVolumeChange?: GenericEventHandler<Target> | undefined;\n\tonVolumeChangeCapture?: GenericEventHandler<Target> | undefined;\n\tonWaiting?: GenericEventHandler<Target> | undefined;\n\tonWaitingCapture?: GenericEventHandler<Target> | undefined;\n\n\t// MouseEvents\n\tonClick?: MouseEventHandler<Target> | undefined;\n\tonClickCapture?: MouseEventHandler<Target> | undefined;\n\tonContextMenu?: MouseEventHandler<Target> | undefined;\n\tonContextMenuCapture?: MouseEventHandler<Target> | undefined;\n\tonDblClick?: MouseEventHandler<Target> | undefined;\n\tonDblClickCapture?: MouseEventHandler<Target> | undefined;\n\tonDrag?: DragEventHandler<Target> | undefined;\n\tonDragCapture?: DragEventHandler<Target> | undefined;\n\tonDragEnd?: DragEventHandler<Target> | undefined;\n\tonDragEndCapture?: DragEventHandler<Target> | undefined;\n\tonDragEnter?: DragEventHandler<Target> | undefined;\n\tonDragEnterCapture?: DragEventHandler<Target> | undefined;\n\tonDragExit?: DragEventHandler<Target> | undefined;\n\tonDragExitCapture?: DragEventHandler<Target> | undefined;\n\tonDragLeave?: DragEventHandler<Target> | undefined;\n\tonDragLeaveCapture?: DragEventHandler<Target> | undefined;\n\tonDragOver?: DragEventHandler<Target> | undefined;\n\tonDragOverCapture?: DragEventHandler<Target> | undefined;\n\tonDragStart?: DragEventHandler<Target> | undefined;\n\tonDragStartCapture?: DragEventHandler<Target> | undefined;\n\tonDrop?: DragEventHandler<Target> | undefined;\n\tonDropCapture?: DragEventHandler<Target> | undefined;\n\tonMouseDown?: MouseEventHandler<Target> | undefined;\n\tonMouseDownCapture?: MouseEventHandler<Target> | undefined;\n\tonMouseEnter?: MouseEventHandler<Target> | undefined;\n\tonMouseEnterCapture?: MouseEventHandler<Target> | undefined;\n\tonMouseLeave?: MouseEventHandler<Target> | undefined;\n\tonMouseLeaveCapture?: MouseEventHandler<Target> | undefined;\n\tonMouseMove?: MouseEventHandler<Target> | undefined;\n\tonMouseMoveCapture?: MouseEventHandler<Target> | undefined;\n\tonMouseOut?: MouseEventHandler<Target> | undefined;\n\tonMouseOutCapture?: MouseEventHandler<Target> | undefined;\n\tonMouseOver?: MouseEventHandler<Target> | undefined;\n\tonMouseOverCapture?: MouseEventHandler<Target> | undefined;\n\tonMouseUp?: MouseEventHandler<Target> | undefined;\n\tonMouseUpCapture?: MouseEventHandler<Target> | undefined;\n\t// TODO: Spec for `auxclick` events was changed to make it a PointerEvent but only\n\t// Chrome has support for it yet. When more browsers align we should change this.\n\t// https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event#browser_compatibility\n\tonAuxClick?: MouseEventHandler<Target> | undefined;\n\tonAuxClickCapture?: MouseEventHandler<Target> | undefined;\n\n\t// Selection Events\n\tonSelect?: GenericEventHandler<Target> | undefined;\n\tonSelectCapture?: GenericEventHandler<Target> | undefined;\n\n\t// Touch Events\n\tonTouchCancel?: TouchEventHandler<Target> | undefined;\n\tonTouchCancelCapture?: TouchEventHandler<Target> | undefined;\n\tonTouchEnd?: TouchEventHandler<Target> | undefined;\n\tonTouchEndCapture?: TouchEventHandler<Target> | undefined;\n\tonTouchMove?: TouchEventHandler<Target> | undefined;\n\tonTouchMoveCapture?: TouchEventHandler<Target> | undefined;\n\tonTouchStart?: TouchEventHandler<Target> | undefined;\n\tonTouchStartCapture?: TouchEventHandler<Target> | undefined;\n\n\t// Pointer Events\n\tonPointerOver?: PointerEventHandler<Target> | undefined;\n\tonPointerOverCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerEnter?: PointerEventHandler<Target> | undefined;\n\tonPointerEnterCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerDown?: PointerEventHandler<Target> | undefined;\n\tonPointerDownCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerMove?: PointerEventHandler<Target> | undefined;\n\tonPointerMoveCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerUp?: PointerEventHandler<Target> | undefined;\n\tonPointerUpCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerCancel?: PointerEventHandler<Target> | undefined;\n\tonPointerCancelCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerOut?: PointerEventHandler<Target> | undefined;\n\tonPointerOutCapture?: PointerEventHandler<Target> | undefined;\n\tonPointerLeave?: PointerEventHandler<Target> | undefined;\n\tonPointerLeaveCapture?: PointerEventHandler<Target> | undefined;\n\tonGotPointerCapture?: PointerEventHandler<Target> | undefined;\n\tonGotPointerCaptureCapture?: PointerEventHandler<Target> | undefined;\n\tonLostPointerCapture?: PointerEventHandler<Target> | undefined;\n\tonLostPointerCaptureCapture?: PointerEventHandler<Target> | undefined;\n\n\t// Scroll Events\n\tonScroll?: GenericEventHandler<Target> | undefined;\n\tonScrollCapture?: GenericEventHandler<Target> | undefined;\n\tonScrollEnd?: GenericEventHandler<Target> | undefined;\n\tonScrollEndCapture?: GenericEventHandler<Target> | undefined;\n\tonScrollSnapChange?: SnapEventHandler<Target> | undefined;\n\tonScrollSnapChangeCapture?: SnapEventHandler<Target> | undefined;\n\tonScrollSnapChanging?: SnapEventHandler<Target> | undefined;\n\tonScrollSnapChangingCapture?: SnapEventHandler<Target> | undefined;\n\n\t// Wheel Events\n\tonWheel?: WheelEventHandler<Target> | undefined;\n\tonWheelCapture?: WheelEventHandler<Target> | undefined;\n\n\t// Animation Events\n\tonAnimationStart?: AnimationEventHandler<Target> | undefined;\n\tonAnimationStartCapture?: AnimationEventHandler<Target> | undefined;\n\tonAnimationEnd?: AnimationEventHandler<Target> | undefined;\n\tonAnimationEndCapture?: AnimationEventHandler<Target> | undefined;\n\tonAnimationIteration?: AnimationEventHandler<Target> | undefined;\n\tonAnimationIterationCapture?: AnimationEventHandler<Target> | undefined;\n\n\t// Transition Events\n\tonTransitionCancel?: TransitionEventHandler<Target>;\n\tonTransitionCancelCapture?: TransitionEventHandler<Target>;\n\tonTransitionEnd?: TransitionEventHandler<Target>;\n\tonTransitionEndCapture?: TransitionEventHandler<Target>;\n\tonTransitionRun?: TransitionEventHandler<Target>;\n\tonTransitionRunCapture?: TransitionEventHandler<Target>;\n\tonTransitionStart?: TransitionEventHandler<Target>;\n\tonTransitionStartCapture?: TransitionEventHandler<Target>;\n\n\t// PictureInPicture Events\n\tonEnterPictureInPicture?: PictureInPictureEventHandler<Target>;\n\tonEnterPictureInPictureCapture?: PictureInPictureEventHandler<Target>;\n\tonLeavePictureInPicture?: PictureInPictureEventHandler<Target>;\n\tonLeavePictureInPictureCapture?: PictureInPictureEventHandler<Target>;\n\tonResize?: PictureInPictureEventHandler<Target>;\n\tonResizeCapture?: PictureInPictureEventHandler<Target>;\n\n\tonCommand?: CommandEventHandler<Target>;\n}\n\n// All the WAI-ARIA 1.1 attributes from https://www.w3.org/TR/wai-aria-1.1/\nexport interface AriaAttributes {\n\t/** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */\n\t'aria-activedescendant'?: Signalish<string | undefined>;\n\t/** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */\n\t'aria-atomic'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be\n\t * presented if they are made.\n\t */\n\t'aria-autocomplete'?: Signalish<\n\t\t'none' | 'inline' | 'list' | 'both' | undefined\n\t>;\n\t/**\n\t * Defines a string value that labels the current element, which is intended to be converted into Braille.\n\t * @see aria-label.\n\t */\n\t'aria-braillelabel'?: Signalish<string | undefined>;\n\t/**\n\t * Defines a human-readable, author-localized abbreviated description for the role of an element, which is intended to be converted into Braille.\n\t * @see aria-roledescription.\n\t */\n\t'aria-brailleroledescription'?: Signalish<string | undefined>;\n\t/** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */\n\t'aria-busy'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Indicates the current \"checked\" state of checkboxes, radio buttons, and other widgets.\n\t * @see aria-pressed\n\t * @see aria-selected.\n\t */\n\t'aria-checked'?: Signalish<Booleanish | 'mixed' | undefined>;\n\t/**\n\t * Defines the total number of columns in a table, grid, or treegrid.\n\t * @see aria-colindex.\n\t */\n\t'aria-colcount'?: Signalish<number | undefined>;\n\t/**\n\t * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid.\n\t * @see aria-colcount\n\t * @see aria-colspan.\n\t */\n\t'aria-colindex'?: Signalish<number | undefined>;\n\t/**\n\t * Defines a human readable text alternative of aria-colindex.\n\t * @see aria-rowindextext.\n\t */\n\t'aria-colindextext'?: Signalish<string | undefined>;\n\t/**\n\t * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid.\n\t * @see aria-colindex\n\t * @see aria-rowspan.\n\t */\n\t'aria-colspan'?: Signalish<number | undefined>;\n\t/**\n\t * Identifies the element (or elements) whose contents or presence are controlled by the current element.\n\t * @see aria-owns.\n\t */\n\t'aria-controls'?: Signalish<string | undefined>;\n\t/** Indicates the element that represents the current item within a container or set of related elements. */\n\t'aria-current'?: Signalish<\n\t\tBooleanish | 'page' | 'step' | 'location' | 'date' | 'time' | undefined\n\t>;\n\t/**\n\t * Identifies the element (or elements) that describes the object.\n\t * @see aria-labelledby\n\t */\n\t'aria-describedby'?: Signalish<string | undefined>;\n\t/**\n\t * Defines a string value that describes or annotates the current element.\n\t * @see related aria-describedby.\n\t */\n\t'aria-description'?: Signalish<string | undefined>;\n\t/**\n\t * Identifies the element that provides a detailed, extended description for the object.\n\t * @see aria-describedby.\n\t */\n\t'aria-details'?: Signalish<string | undefined>;\n\t/**\n\t * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.\n\t * @see aria-hidden\n\t * @see aria-readonly.\n\t */\n\t'aria-disabled'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Indicates what functions can be performed when a dragged object is released on the drop target.\n\t * @deprecated in ARIA 1.1\n\t */\n\t'aria-dropeffect'?: Signalish<\n\t\t'none' | 'copy' | 'execute' | 'link' | 'move' | 'popup' | undefined\n\t>;\n\t/**\n\t * Identifies the element that provides an error message for the object.\n\t * @see aria-invalid\n\t * @see aria-describedby.\n\t */\n\t'aria-errormessage'?: Signalish<string | undefined>;\n\t/** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */\n\t'aria-expanded'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion,\n\t * allows assistive technology to override the general default of reading in document source order.\n\t */\n\t'aria-flowto'?: Signalish<string | undefined>;\n\t/**\n\t * Indicates an element's \"grabbed\" state in a drag-and-drop operation.\n\t * @deprecated in ARIA 1.1\n\t */\n\t'aria-grabbed'?: Signalish<Booleanish | undefined>;\n\t/** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */\n\t'aria-haspopup'?: Signalish<\n\t\tBooleanish | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | undefined\n\t>;\n\t/**\n\t * Indicates whether the element is exposed to an accessibility API.\n\t * @see aria-disabled.\n\t */\n\t'aria-hidden'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Indicates the entered value does not conform to the format expected by the application.\n\t * @see aria-errormessage.\n\t */\n\t'aria-invalid'?: Signalish<Booleanish | 'grammar' | 'spelling' | undefined>;\n\t/** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */\n\t'aria-keyshortcuts'?: Signalish<string | undefined>;\n\t/**\n\t * Defines a string value that labels the current element.\n\t * @see aria-labelledby.\n\t */\n\t'aria-label'?: Signalish<string | undefined>;\n\t/**\n\t * Identifies the element (or elements) that labels the current element.\n\t * @see aria-describedby.\n\t */\n\t'aria-labelledby'?: Signalish<string | undefined>;\n\t/** Defines the hierarchical level of an element within a structure. */\n\t'aria-level'?: Signalish<number | undefined>;\n\t/** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */\n\t'aria-live'?: Signalish<'off' | 'assertive' | 'polite' | undefined>;\n\t/** Indicates whether an element is modal when displayed. */\n\t'aria-modal'?: Signalish<Booleanish | undefined>;\n\t/** Indicates whether a text box accepts multiple lines of input or only a single line. */\n\t'aria-multiline'?: Signalish<Booleanish | undefined>;\n\t/** Indicates that the user may select more than one item from the current selectable descendants. */\n\t'aria-multiselectable'?: Signalish<Booleanish | undefined>;\n\t/** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */\n\t'aria-orientation'?: Signalish<'horizontal' | 'vertical' | undefined>;\n\t/**\n\t * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship\n\t * between DOM elements where the DOM hierarchy cannot be used to represent the relationship.\n\t * @see aria-controls.\n\t */\n\t'aria-owns'?: Signalish<string | undefined>;\n\t/**\n\t * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value.\n\t * A hint could be a sample value or a brief description of the expected format.\n\t */\n\t'aria-placeholder'?: Signalish<string | undefined>;\n\t/**\n\t * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.\n\t * @see aria-setsize.\n\t */\n\t'aria-posinset'?: Signalish<number | undefined>;\n\t/**\n\t * Indicates the current \"pressed\" state of toggle buttons.\n\t * @see aria-checked\n\t * @see aria-selected.\n\t */\n\t'aria-pressed'?: Signalish<Booleanish | 'mixed' | undefined>;\n\t/**\n\t * Indicates that the element is not editable, but is otherwise operable.\n\t * @see aria-disabled.\n\t */\n\t'aria-readonly'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified.\n\t * @see aria-atomic.\n\t */\n\t'aria-relevant'?: Signalish<\n\t\t| 'additions'\n\t\t| 'additions removals'\n\t\t| 'additions text'\n\t\t| 'all'\n\t\t| 'removals'\n\t\t| 'removals additions'\n\t\t| 'removals text'\n\t\t| 'text'\n\t\t| 'text additions'\n\t\t| 'text removals'\n\t\t| undefined\n\t>;\n\t/** Indicates that user input is required on the element before a form may be submitted. */\n\t'aria-required'?: Signalish<Booleanish | undefined>;\n\t/** Defines a human-readable, author-localized description for the role of an element. */\n\t'aria-roledescription'?: Signalish<string | undefined>;\n\t/**\n\t * Defines the total number of rows in a table, grid, or treegrid.\n\t * @see aria-rowindex.\n\t */\n\t'aria-rowcount'?: Signalish<number | undefined>;\n\t/**\n\t * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid.\n\t * @see aria-rowcount\n\t * @see aria-rowspan.\n\t */\n\t'aria-rowindex'?: Signalish<number | undefined>;\n\t/**\n\t * Defines a human readable text alternative of aria-rowindex.\n\t * @see aria-colindextext.\n\t */\n\t'aria-rowindextext'?: Signalish<string | undefined>;\n\t/**\n\t * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid.\n\t * @see aria-rowindex\n\t * @see aria-colspan.\n\t */\n\t'aria-rowspan'?: Signalish<number | undefined>;\n\t/**\n\t * Indicates the current \"selected\" state of various widgets.\n\t * @see aria-checked\n\t * @see aria-pressed.\n\t */\n\t'aria-selected'?: Signalish<Booleanish | undefined>;\n\t/**\n\t * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM.\n\t * @see aria-posinset.\n\t */\n\t'aria-setsize'?: Signalish<number | undefined>;\n\t/** Indicates if items in a table or grid are sorted in ascending or descending order. */\n\t'aria-sort'?: Signalish<\n\t\t'none' | 'ascending' | 'descending' | 'other' | undefined\n\t>;\n\t/** Defines the maximum allowed value for a range widget. */\n\t'aria-valuemax'?: Signalish<number | undefined>;\n\t/** Defines the minimum allowed value for a range widget. */\n\t'aria-valuemin'?: Signalish<number | undefined>;\n\t/**\n\t * Defines the current value for a range widget.\n\t * @see aria-valuetext.\n\t */\n\t'aria-valuenow'?: Signalish<number | undefined>;\n\t/** Defines the human readable text alternative of aria-valuenow for a range widget. */\n\t'aria-valuetext'?: Signalish<string | undefined>;\n}\n\n// All the WAI-ARIA 1.2 role attribute values from https://www.w3.org/TR/wai-aria-1.2/#role_definitions\nexport type WAIAriaRole =\n\t| 'alert'\n\t| 'alertdialog'\n\t| 'application'\n\t| 'article'\n\t| 'banner'\n\t| 'blockquote'\n\t| 'button'\n\t| 'caption'\n\t| 'cell'\n\t| 'checkbox'\n\t| 'code'\n\t| 'columnheader'\n\t| 'combobox'\n\t| 'command'\n\t| 'complementary'\n\t| 'composite'\n\t| 'contentinfo'\n\t| 'definition'\n\t| 'deletion'\n\t| 'dialog'\n\t| 'directory'\n\t| 'document'\n\t| 'emphasis'\n\t| 'feed'\n\t| 'figure'\n\t| 'form'\n\t| 'grid'\n\t| 'gridcell'\n\t| 'group'\n\t| 'heading'\n\t| 'img'\n\t| 'input'\n\t| 'insertion'\n\t| 'landmark'\n\t| 'link'\n\t| 'list'\n\t| 'listbox'\n\t| 'listitem'\n\t| 'log'\n\t| 'main'\n\t| 'marquee'\n\t| 'math'\n\t| 'meter'\n\t| 'menu'\n\t| 'menubar'\n\t| 'menuitem'\n\t| 'menuitemcheckbox'\n\t| 'menuitemradio'\n\t| 'navigation'\n\t| 'none'\n\t| 'note'\n\t| 'option'\n\t| 'paragraph'\n\t| 'presentation'\n\t| 'progressbar'\n\t| 'radio'\n\t| 'radiogroup'\n\t| 'range'\n\t| 'region'\n\t| 'roletype'\n\t| 'row'\n\t| 'rowgroup'\n\t| 'rowheader'\n\t| 'scrollbar'\n\t| 'search'\n\t| 'searchbox'\n\t| 'section'\n\t| 'sectionhead'\n\t| 'select'\n\t| 'separator'\n\t| 'slider'\n\t| 'spinbutton'\n\t| 'status'\n\t| 'strong'\n\t| 'structure'\n\t| 'subscript'\n\t| 'superscript'\n\t| 'switch'\n\t| 'tab'\n\t| 'table'\n\t| 'tablist'\n\t| 'tabpanel'\n\t| 'term'\n\t| 'textbox'\n\t| 'time'\n\t| 'timer'\n\t| 'toolbar'\n\t| 'tooltip'\n\t| 'tree'\n\t| 'treegrid'\n\t| 'treeitem'\n\t| 'widget'\n\t| 'window'\n\t| 'none presentation';\n\n// All the Digital Publishing WAI-ARIA 1.0 role attribute values from https://www.w3.org/TR/dpub-aria-1.0/#role_definitions\nexport type DPubAriaRole =\n\t| 'doc-abstract'\n\t| 'doc-acknowledgments'\n\t| 'doc-afterword'\n\t| 'doc-appendix'\n\t| 'doc-backlink'\n\t| 'doc-biblioentry'\n\t| 'doc-bibliography'\n\t| 'doc-biblioref'\n\t| 'doc-chapter'\n\t| 'doc-colophon'\n\t| 'doc-conclusion'\n\t| 'doc-cover'\n\t| 'doc-credit'\n\t| 'doc-credits'\n\t| 'doc-dedication'\n\t| 'doc-endnote'\n\t| 'doc-endnotes'\n\t| 'doc-epigraph'\n\t| 'doc-epilogue'\n\t| 'doc-errata'\n\t| 'doc-example'\n\t| 'doc-footnote'\n\t| 'doc-foreword'\n\t| 'doc-glossary'\n\t| 'doc-glossref'\n\t| 'doc-index'\n\t| 'doc-introduction'\n\t| 'doc-noteref'\n\t| 'doc-notice'\n\t| 'doc-pagebreak'\n\t| 'doc-pagelist'\n\t| 'doc-part'\n\t| 'doc-preface'\n\t| 'doc-prologue'\n\t| 'doc-pullquote'\n\t| 'doc-qna'\n\t| 'doc-subtitle'\n\t| 'doc-tip'\n\t| 'doc-toc';\n\nexport type AriaRole = WAIAriaRole | DPubAriaRole;\n\nexport interface AllHTMLAttributes<RefType extends EventTarget = EventTarget>\n\textends ClassAttributes<RefType>,\n\t\tDOMAttributes<RefType>,\n\t\tAriaAttributes {\n\t// Standard HTML Attributes\n\taccept?: Signalish<string | undefined>;\n\tacceptCharset?: Signalish<string | undefined>;\n\t'accept-charset'?: Signalish<AllHTMLAttributes['acceptCharset']>;\n\taccessKey?: Signalish<string | undefined>;\n\taccesskey?: Signalish<AllHTMLAttributes['accessKey']>;\n\taction?: Signalish<string | undefined>;\n\tallow?: Signalish<string | undefined>;\n\tallowFullScreen?: Signalish<boolean | undefined>;\n\tallowTransparency?: Signalish<boolean | undefined>;\n\talt?: Signalish<string | undefined>;\n\tas?: Signalish<string | undefined>;\n\tasync?: Signalish<boolean | undefined>;\n\tautocomplete?: Signalish<string | undefined>;\n\tautoComplete?: Signalish<string | undefined>;\n\tautocorrect?: Signalish<string | undefined>;\n\tautoCorrect?: Signalish<string | undefined>;\n\tautofocus?: Signalish<boolean | undefined>;\n\tautoFocus?: Signalish<boolean | undefined>;\n\tautoPlay?: Signalish<boolean | undefined>;\n\tautoplay?: Signalish<boolean | undefined>;\n\tcapture?: Signalish<boolean | string | undefined>;\n\tcellPadding?: Signalish<number | string | undefined>;\n\tcellSpacing?: Signalish<number | string | undefined>;\n\tcharSet?: Signalish<string | undefined>;\n\tcharset?: Signalish<string | undefined>;\n\tchallenge?: Signalish<string | undefined>;\n\tchecked?: Signalish<boolean | undefined>;\n\tcite?: Signalish<string | undefined>;\n\tclass?: Signalish<string | undefined>;\n\tclassName?: Signalish<string | undefined>;\n\tcols?: Signalish<number | undefined>;\n\tcolSpan?: Signalish<number | undefined>;\n\tcolspan?: Signalish<number | undefined>;\n\tcontent?: Signalish<string | undefined>;\n\tcontentEditable?: Signalish<\n\t\tBooleanish | '' | 'plaintext-only' | 'inherit' | undefined\n\t>;\n\tcontenteditable?: Signalish<AllHTMLAttributes['contentEditable']>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contextmenu */\n\tcontextMenu?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contextmenu */\n\tcontextmenu?: Signalish<string | undefined>;\n\tcontrols?: Signalish<boolean | undefined>;\n\tcontrolslist?: Signalish<string | undefined>;\n\tcontrolsList?: Signalish<string | undefined>;\n\tcoords?: Signalish<string | undefined>;\n\tcrossOrigin?: Signalish<string | undefined>;\n\tcrossorigin?: Signalish<string | undefined>;\n\tcurrentTime?: Signalish<number | undefined>;\n\tdata?: Signalish<string | undefined>;\n\tdateTime?: Signalish<string | undefined>;\n\tdatetime?: Signalish<string | undefined>;\n\tdefault?: Signalish<boolean | undefined>;\n\tdefaultChecked?: Signalish<boolean | undefined>;\n\tdefaultMuted?: Signalish<boolean | undefined>;\n\tdefaultPlaybackRate?: Signalish<number | undefined>;\n\tdefaultValue?: Signalish<string | undefined>;\n\tdefer?: Signalish<boolean | undefined>;\n\tdir?: Signalish<'auto' | 'rtl' | 'ltr' | undefined>;\n\tdisabled?: Signalish<boolean | undefined>;\n\tdisableremoteplayback?: Signalish<boolean | undefined>;\n\tdisableRemotePlayback?: Signalish<boolean | undefined>;\n\tdownload?: Signalish<any | undefined>;\n\tdecoding?: Signalish<'sync' | 'async' | 'auto' | undefined>;\n\tdraggable?: Signalish<boolean | undefined>;\n\tencType?: Signalish<string | undefined>;\n\tenctype?: Signalish<string | undefined>;\n\tenterkeyhint?: Signalish<\n\t\t| 'enter'\n\t\t| 'done'\n\t\t| 'go'\n\t\t| 'next'\n\t\t| 'previous'\n\t\t| 'search'\n\t\t| 'send'\n\t\t| undefined\n\t>;\n\telementTiming?: Signalish<string | undefined>;\n\telementtiming?: Signalish<AllHTMLAttributes['elementTiming']>;\n\texportparts?: Signalish<string | undefined>;\n\tfor?: Signalish<string | undefined>;\n\tform?: Signalish<string | undefined>;\n\tformAction?: Signalish<string | undefined>;\n\tformaction?: Signalish<string | undefined>;\n\tformEncType?: Signalish<string | undefined>;\n\tformenctype?: Signalish<string | undefined>;\n\tformMethod?: Signalish<string | undefined>;\n\tformmethod?: Signalish<string | undefined>;\n\tformNoValidate?: Signalish<boolean | undefined>;\n\tformnovalidate?: Signalish<boolean | undefined>;\n\tformTarget?: Signalish<string | undefined>;\n\tformtarget?: Signalish<string | undefined>;\n\tframeBorder?: Signalish<number | string | undefined>;\n\tframeborder?: Signalish<number | string | undefined>;\n\theaders?: Signalish<string | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\thidden?: Signalish<boolean | 'hidden' | 'until-found' | undefined>;\n\thigh?: Signalish<number | undefined>;\n\thref?: Signalish<string | undefined>;\n\threfLang?: Signalish<string | undefined>;\n\threflang?: Signalish<string | undefined>;\n\thtmlFor?: Signalish<string | undefined>;\n\thttpEquiv?: Signalish<string | undefined>;\n\t'http-equiv'?: Signalish<string | undefined>;\n\ticon?: Signalish<string | undefined>;\n\tid?: Signalish<string | undefined>;\n\tindeterminate?: Signalish<boolean | undefined>;\n\tinert?: Signalish<boolean | undefined>;\n\tinputMode?: Signalish<string | undefined>;\n\tinputmode?: Signalish<string | undefined>;\n\tintegrity?: Signalish<string | undefined>;\n\tis?: Signalish<string | undefined>;\n\tkeyParams?: Signalish<string | undefined>;\n\tkeyType?: Signalish<string | undefined>;\n\tkind?: Signalish<string | undefined>;\n\tlabel?: Signalish<string | undefined>;\n\tlang?: Signalish<string | undefined>;\n\tlist?: Signalish<string | undefined>;\n\tloading?: Signalish<'eager' | 'lazy' | undefined>;\n\tloop?: Signalish<boolean | undefined>;\n\tlow?: Signalish<number | undefined>;\n\tmanifest?: Signalish<string | undefined>;\n\tmarginHeight?: Signalish<number | undefined>;\n\tmarginWidth?: Signalish<number | undefined>;\n\tmax?: Signalish<number | string | undefined>;\n\tmaxLength?: Signalish<number | undefined>;\n\tmaxlength?: Signalish<number | undefined>;\n\tmedia?: Signalish<string | undefined>;\n\tmediaGroup?: Signalish<string | undefined>;\n\tmethod?: Signalish<string | undefined>;\n\tmin?: Signalish<number | string | undefined>;\n\tminLength?: Signalish<number | undefined>;\n\tminlength?: Signalish<number | undefined>;\n\tmultiple?: Signalish<boolean | undefined>;\n\tmuted?: Signalish<boolean | undefined>;\n\tname?: Signalish<string | undefined>;\n\tnomodule?: Signalish<boolean | undefined>;\n\tnonce?: Signalish<string | undefined>;\n\tnoValidate?: Signalish<boolean | undefined>;\n\tnovalidate?: Signalish<boolean | undefined>;\n\topen?: Signalish<boolean | undefined>;\n\toptimum?: Signalish<number | undefined>;\n\tpart?: Signalish<string | undefined>;\n\tpattern?: Signalish<string | undefined>;\n\tping?: Signalish<string | undefined>;\n\tplaceholder?: Signalish<string | undefined>;\n\tplaysInline?: Signalish<boolean | undefined>;\n\tplaysinline?: Signalish<boolean | undefined>;\n\tplaybackRate?: Signalish<number | undefined>;\n\tpopover?: Signalish<'auto' | 'hint' | 'manual' | boolean | undefined>;\n\tpopovertarget?: Signalish<string | undefined>;\n\tpopoverTarget?: Signalish<string | undefined>;\n\tpopovertargetaction?: Signalish<'hide' | 'show' | 'toggle' | undefined>;\n\tpopoverTargetAction?: Signalish<'hide' | 'show' | 'toggle' | undefined>;\n\tposter?: Signalish<string | undefined>;\n\tpreload?: Signalish<'auto' | 'metadata' | 'none' | undefined>;\n\tpreservesPitch?: Signalish<boolean | undefined>;\n\tradioGroup?: Signalish<string | undefined>;\n\treadonly?: Signalish<boolean | undefined>;\n\treadOnly?: Signalish<boolean | undefined>;\n\treferrerpolicy?: Signalish<\n\t\t| 'no-referrer'\n\t\t| 'no-referrer-when-downgrade'\n\t\t| 'origin'\n\t\t| 'origin-when-cross-origin'\n\t\t| 'same-origin'\n\t\t| 'strict-origin'\n\t\t| 'strict-origin-when-cross-origin'\n\t\t| 'unsafe-url'\n\t\t| undefined\n\t>;\n\trel?: Signalish<string | undefined>;\n\trequired?: Signalish<boolean | undefined>;\n\treversed?: Signalish<boolean | undefined>;\n\trole?: Signalish<AriaRole | undefined>;\n\trows?: Signalish<number | undefined>;\n\trowSpan?: Signalish<number | undefined>;\n\trowspan?: Signalish<number | undefined>;\n\tsandbox?: Signalish<string | undefined>;\n\tscope?: Signalish<string | undefined>;\n\tscoped?: Signalish<boolean | undefined>;\n\tscrolling?: Signalish<string | undefined>;\n\tseamless?: Signalish<boolean | undefined>;\n\tselected?: Signalish<boolean | undefined>;\n\tshape?: Signalish<string | undefined>;\n\tsize?: Signalish<number | undefined>;\n\tsizes?: Signalish<string | undefined>;\n\tslot?: Signalish<string | undefined>;\n\tspan?: Signalish<number | undefined>;\n\tspellcheck?: Signalish<boolean | undefined>;\n\tsrc?: Signalish<string | undefined>;\n\tsrcDoc?: Signalish<string | undefined>;\n\tsrcdoc?: Signalish<string | undefined>;\n\tsrcLang?: Signalish<string | undefined>;\n\tsrclang?: Signalish<string | undefined>;\n\tsrcSet?: Signalish<string | undefined>;\n\tsrcset?: Signalish<string | undefined>;\n\tsrcObject?: Signalish<MediaStream | MediaSource | Blob | File | null>;\n\tstart?: Signalish<number | undefined>;\n\tstep?: Signalish<number | string | undefined>;\n\tstyle?: Signalish<string | CSSProperties | undefined>;\n\tsummary?: Signalish<string | undefined>;\n\ttabIndex?: Signalish<number | undefined>;\n\ttabindex?: Signalish<number | undefined>;\n\ttarget?: Signalish<string | undefined>;\n\ttitle?: Signalish<string | undefined>;\n\ttype?: Signalish<string | undefined>;\n\tuseMap?: Signalish<string | undefined>;\n\tusemap?: Signalish<string | undefined>;\n\tvalue?: Signalish<string | string[] | number | undefined>;\n\tvolume?: Signalish<string | number | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n\twmode?: Signalish<string | undefined>;\n\twrap?: Signalish<string | undefined>;\n\n\t// Non-standard Attributes\n\tautocapitalize?: Signalish<\n\t\t'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters' | undefined\n\t>;\n\tautoCapitalize?: Signalish<\n\t\t'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters' | undefined\n\t>;\n\tdisablePictureInPicture?: Signalish<boolean | undefined>;\n\tresults?: Signalish<number | undefined>;\n\ttranslate?: Signalish<boolean | undefined>;\n\n\t// RDFa Attributes\n\tabout?: Signalish<string | undefined>;\n\tdatatype?: Signalish<string | undefined>;\n\tinlist?: Signalish<any>;\n\tprefix?: Signalish<string | undefined>;\n\tproperty?: Signalish<string | undefined>;\n\tresource?: Signalish<string | undefined>;\n\ttypeof?: Signalish<string | undefined>;\n\tvocab?: Signalish<string | undefined>;\n\n\t// Microdata Attributes\n\titemProp?: Signalish<string | undefined>;\n\titemprop?: Signalish<string | undefined>;\n\titemScope?: Signalish<boolean | undefined>;\n\titemscope?: Signalish<boolean | undefined>;\n\titemType?: Signalish<string | undefined>;\n\titemtype?: Signalish<string | undefined>;\n\titemID?: Signalish<string | undefined>;\n\titemid?: Signalish<string | undefined>;\n\titemRef?: Signalish<string | undefined>;\n\titemref?: Signalish<string | undefined>;\n}\n\nexport interface HTMLAttributes<RefType extends EventTarget = EventTarget>\n\textends ClassAttributes<RefType>,\n\t\tDOMAttributes<RefType>,\n\t\tAriaAttributes {\n\t// Standard HTML Attributes\n\taccesskey?: Signalish<string | undefined>;\n\taccessKey?: Signalish<string | undefined>;\n\tautocapitalize?: Signalish<\n\t\t'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters' | undefined\n\t>;\n\tautoCapitalize?: Signalish<\n\t\t'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters' | undefined\n\t>;\n\tautocorrect?: Signalish<string | undefined>;\n\tautoCorrect?: Signalish<string | undefined>;\n\tautofocus?: Signalish<boolean | undefined>;\n\tautoFocus?: Signalish<boolean | undefined>;\n\tclass?: Signalish<string | undefined>;\n\tclassName?: Signalish<string | undefined>;\n\tcontenteditable?: Signalish<\n\t\tBooleanish | '' | 'plaintext-only' | 'inherit' | undefined\n\t>;\n\tcontentEditable?: Signalish<\n\t\tBooleanish | '' | 'plaintext-only' | 'inherit' | undefined\n\t>;\n\tdir?: Signalish<'auto' | 'rtl' | 'ltr' | undefined>;\n\tdraggable?: Signalish<boolean | undefined>;\n\tenterkeyhint?: Signalish<\n\t\t| 'enter'\n\t\t| 'done'\n\t\t| 'go'\n\t\t| 'next'\n\t\t| 'previous'\n\t\t| 'search'\n\t\t| 'send'\n\t\t| undefined\n\t>;\n\texportparts?: Signalish<string | undefined>;\n\thidden?: Signalish<boolean | 'hidden' | 'until-found' | undefined>;\n\tid?: Signalish<string | undefined>;\n\tinert?: Signalish<boolean | undefined>;\n\tinputmode?: Signalish<string | undefined>;\n\tinputMode?: Signalish<string | undefined>;\n\tis?: Signalish<string | undefined>;\n\tlang?: Signalish<string | undefined>;\n\tnonce?: Signalish<string | undefined>;\n\tpart?: Signalish<string | undefined>;\n\tpopover?: Signalish<'auto' | 'hint' | 'manual' | boolean | undefined>;\n\tslot?: Signalish<string | undefined>;\n\tspellcheck?: Signalish<boolean | undefined>;\n\tstyle?: Signalish<string | CSSProperties | undefined>;\n\ttabindex?: Signalish<number | undefined>;\n\ttabIndex?: Signalish<number | undefined>;\n\ttitle?: Signalish<string | undefined>;\n\ttranslate?: Signalish<boolean | undefined>;\n\n\t// WAI-ARIA Attributes\n\t// Most elements only allow a subset of roles and so this\n\t// is overwritten in many of the per-element interfaces below\n\trole?: Signalish<AriaRole | undefined>;\n\n\t// Non-standard Attributes\n\tdisablePictureInPicture?: Signalish<boolean | undefined>;\n\telementtiming?: Signalish<string | undefined>;\n\telementTiming?: Signalish<string | undefined>;\n\tresults?: Signalish<number | undefined>;\n\n\t// RDFa Attributes\n\tabout?: Signalish<string | undefined>;\n\tdatatype?: Signalish<string | undefined>;\n\tinlist?: Signalish<any>;\n\tprefix?: Signalish<string | undefined>;\n\tproperty?: Signalish<string | undefined>;\n\tresource?: Signalish<string | undefined>;\n\ttypeof?: Signalish<string | undefined>;\n\tvocab?: Signalish<string | undefined>;\n\n\t// Microdata Attributes\n\titemid?: Signalish<string | undefined>;\n\titemID?: Signalish<string | undefined>;\n\titemprop?: Signalish<string | undefined>;\n\titemProp?: Signalish<string | undefined>;\n\titemref?: Signalish<string | undefined>;\n\titemRef?: Signalish<string | undefined>;\n\titemscope?: Signalish<boolean | undefined>;\n\titemScope?: Signalish<boolean | undefined>;\n\titemtype?: Signalish<string | undefined>;\n\titemType?: Signalish<string | undefined>;\n}\n\nexport type HTMLAttributeReferrerPolicy =\n\t| ''\n\t| 'no-referrer'\n\t| 'no-referrer-when-downgrade'\n\t| 'origin'\n\t| 'origin-when-cross-origin'\n\t| 'same-origin'\n\t| 'strict-origin'\n\t| 'strict-origin-when-cross-origin'\n\t| 'unsafe-url';\n\nexport type HTMLAttributeAnchorTarget =\n\t| '_self'\n\t| '_blank'\n\t| '_parent'\n\t| '_top'\n\t| (string & {});\n\nexport interface PartialAnchorHTMLAttributes<T extends EventTarget>\n\textends HTMLAttributes<T> {\n\tdownload?: Signalish<any>;\n\threflang?: Signalish<string | undefined>;\n\threfLang?: Signalish<string | undefined>;\n\tmedia?: Signalish<string | undefined>;\n\tping?: Signalish<string | undefined>;\n\trel?: Signalish<string | undefined>;\n\ttarget?: Signalish<HTMLAttributeAnchorTarget | undefined>;\n\ttype?: Signalish<string | undefined>;\n\treferrerpolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\treferrerPolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n}\n\nexport type AnchorAriaRoles =\n\t| {\n\t\t\thref: Signalish<string>;\n\t\t\trole?: Signalish<\n\t\t\t\t| 'link'\n\t\t\t\t| 'button'\n\t\t\t\t| 'checkbox'\n\t\t\t\t| 'menuitem'\n\t\t\t\t| 'menuitemcheckbox'\n\t\t\t\t| 'menuitemradio'\n\t\t\t\t| 'option'\n\t\t\t\t| 'radio'\n\t\t\t\t| 'switch'\n\t\t\t\t| 'tab'\n\t\t\t\t| 'treeitem'\n\t\t\t\t| 'doc-backlink'\n\t\t\t\t| 'doc-biblioref'\n\t\t\t\t| 'doc-glossref'\n\t\t\t\t| 'doc-noteref'\n\t\t\t\t| undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\thref?: never;\n\t\t\trole?: Signalish<AriaRole | undefined>;\n\t  };\n\nexport type AccessibleAnchorHTMLAttributes<\n\tT extends EventTarget = HTMLAnchorElement\n> = Omit<PartialAnchorHTMLAttributes<T>, 'role'> & AnchorAriaRoles;\n\nexport interface AnchorHTMLAttributes<T extends EventTarget = HTMLAnchorElement>\n\textends PartialAnchorHTMLAttributes<T> {\n\thref?: Signalish<string | undefined>;\n\trole?: Signalish<AriaRole | undefined>;\n}\n\nexport interface PartialAreaHTMLAttributes<T extends EventTarget>\n\textends HTMLAttributes<T> {\n\talt?: Signalish<string | undefined>;\n\tcoords?: Signalish<string | undefined>;\n\tdownload?: Signalish<any>;\n\threflang?: Signalish<string | undefined>;\n\threfLang?: Signalish<string | undefined>;\n\tmedia?: Signalish<string | undefined>;\n\treferrerpolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\treferrerPolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\trel?: Signalish<string | undefined>;\n\tshape?: Signalish<string | undefined>;\n\ttarget?: Signalish<HTMLAttributeAnchorTarget | undefined>;\n}\n\nexport type AreaAriaRoles =\n\t| {\n\t\t\thref: Signalish<string>;\n\t\t\trole?: Signalish<'link' | undefined>;\n\t  }\n\t| {\n\t\t\thref?: never;\n\t\t\trole?: Signalish<'button' | 'link' | undefined>;\n\t  };\n\nexport type AccessibleAreaHTMLAttributes<\n\tT extends EventTarget = HTMLAreaElement\n> = Omit<PartialAreaHTMLAttributes<T>, 'role'> & AreaAriaRoles;\n\nexport interface AreaHTMLAttributes<T extends EventTarget = HTMLAreaElement>\n\textends PartialAreaHTMLAttributes<T> {\n\thref?: Signalish<string | undefined>;\n\trole?: Signalish<'button' | 'link' | undefined>;\n}\n\nexport interface ArticleHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t| 'article'\n\t\t| 'application'\n\t\t| 'document'\n\t\t| 'feed'\n\t\t| 'main'\n\t\t| 'none'\n\t\t| 'presentation'\n\t\t| 'region'\n\t\t| undefined\n\t>;\n}\n\nexport interface AsideHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t| 'complementary'\n\t\t| 'feed'\n\t\t| 'none'\n\t\t| 'note'\n\t\t| 'presentation'\n\t\t| 'region'\n\t\t| 'search'\n\t\t| 'doc-dedication'\n\t\t| 'doc-example'\n\t\t| 'doc-footnote'\n\t\t| 'doc-glossary'\n\t\t| 'doc-pullquote'\n\t\t| 'doc-tip'\n\t\t| undefined\n\t>;\n}\n\nexport interface AudioHTMLAttributes<T extends EventTarget = HTMLAudioElement>\n\textends MediaHTMLAttributes<T> {\n\trole?: Signalish<'application' | undefined>;\n}\n\nexport interface BaseHTMLAttributes<T extends EventTarget = HTMLBaseElement>\n\textends HTMLAttributes<T> {\n\thref?: Signalish<string | undefined>;\n\trole?: never;\n\ttarget?: Signalish<HTMLAttributeAnchorTarget | undefined>;\n}\n\nexport interface BlockquoteHTMLAttributes<\n\tT extends EventTarget = HTMLQuoteElement\n> extends HTMLAttributes<T> {\n\tcite?: Signalish<string | undefined>;\n}\n\nexport interface BrHTMLAttributes<T extends EventTarget = HTMLBRElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'none' | 'presentation' | undefined>;\n}\n\nexport interface ButtonHTMLAttributes<T extends EventTarget = HTMLButtonElement>\n\textends HTMLAttributes<T> {\n\tcommand?: Signalish<string | undefined>;\n\tcommandfor?: Signalish<string | undefined>;\n\tcommandFor?: Signalish<string | undefined>;\n\tdisabled?: Signalish<boolean | undefined>;\n\tform?: Signalish<string | undefined>;\n\tformaction?: Signalish<string | undefined>;\n\tformAction?: Signalish<string | undefined>;\n\tformenctype?: Signalish<string | undefined>;\n\tformEncType?: Signalish<string | undefined>;\n\tformmethod?: Signalish<string | undefined>;\n\tformMethod?: Signalish<string | undefined>;\n\tformnovalidate?: Signalish<boolean | undefined>;\n\tformNoValidate?: Signalish<boolean | undefined>;\n\tformtarget?: Signalish<string | undefined>;\n\tformTarget?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n\tpopovertarget?: Signalish<string | undefined>;\n\tpopoverTarget?: Signalish<string | undefined>;\n\tpopovertargetaction?: Signalish<'hide' | 'show' | 'toggle' | undefined>;\n\tpopoverTargetAction?: Signalish<'hide' | 'show' | 'toggle' | undefined>;\n\trole?: Signalish<\n\t\t| 'button'\n\t\t| 'checkbox'\n\t\t| 'combobox'\n\t\t| 'gridcell'\n\t\t| 'link'\n\t\t| 'menuitem'\n\t\t| 'menuitemcheckbox'\n\t\t| 'menuitemradio'\n\t\t| 'option'\n\t\t| 'radio'\n\t\t| 'separator'\n\t\t| 'slider'\n\t\t| 'switch'\n\t\t| 'tab'\n\t\t| 'treeitem'\n\t\t| undefined\n\t>;\n\ttype?: Signalish<'submit' | 'reset' | 'button' | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface CanvasHTMLAttributes<T extends EventTarget = HTMLCanvasElement>\n\textends HTMLAttributes<T> {\n\theight?: Signalish<number | string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport interface CaptionHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: 'caption';\n}\n\nexport interface ColHTMLAttributes<T extends EventTarget = HTMLTableColElement>\n\textends HTMLAttributes<T> {\n\trole?: never;\n\tspan?: Signalish<number | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport interface ColgroupHTMLAttributes<\n\tT extends EventTarget = HTMLTableColElement\n> extends HTMLAttributes<T> {\n\trole?: never;\n\tspan?: Signalish<number | undefined>;\n}\n\nexport interface DataHTMLAttributes<T extends EventTarget = HTMLDataElement>\n\textends HTMLAttributes<T> {\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface DataListHTMLAttributes<\n\tT extends EventTarget = HTMLDataListElement\n> extends HTMLAttributes<T> {\n\trole?: Signalish<'listbox' | undefined>;\n}\n\nexport interface DdHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface DelHTMLAttributes<T extends EventTarget = HTMLModElement>\n\textends HTMLAttributes<T> {\n\tcite?: Signalish<string | undefined>;\n\tdatetime?: Signalish<string | undefined>;\n\tdateTime?: Signalish<string | undefined>;\n}\n\nexport interface DetailsHTMLAttributes<\n\tT extends EventTarget = HTMLDetailsElement\n> extends HTMLAttributes<T> {\n\tname?: Signalish<string | undefined>;\n\topen?: Signalish<boolean | undefined>;\n\trole?: Signalish<'group' | undefined>;\n}\n\nexport interface DialogHTMLAttributes<T extends EventTarget = HTMLDialogElement>\n\textends HTMLAttributes<T> {\n\tonCancel?: GenericEventHandler<T> | undefined;\n\tonClose?: GenericEventHandler<T> | undefined;\n\topen?: Signalish<boolean | undefined>;\n\tclosedby?: Signalish<'none' | 'closerequest' | 'any' | undefined>;\n\tclosedBy?: Signalish<'none' | 'closerequest' | 'any' | undefined>;\n\trole?: Signalish<'dialog' | 'alertdialog' | undefined>;\n}\n\nexport interface DlHTMLAttributes<T extends EventTarget = HTMLDListElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'group' | 'list' | 'none' | 'presentation' | undefined>;\n}\n\nexport interface DtHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'listitem' | undefined>;\n}\n\nexport interface EmbedHTMLAttributes<T extends EventTarget = HTMLEmbedElement>\n\textends HTMLAttributes<T> {\n\theight?: Signalish<number | string | undefined>;\n\trole?: Signalish<\n\t\t'application' | 'document' | 'img' | 'none' | 'presentation' | undefined\n\t>;\n\tsrc?: Signalish<string | undefined>;\n\ttype?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport interface FieldsetHTMLAttributes<\n\tT extends EventTarget = HTMLFieldSetElement\n> extends HTMLAttributes<T> {\n\tdisabled?: Signalish<boolean | undefined>;\n\tform?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n\trole?: Signalish<\n\t\t'group' | 'none' | 'presentation' | 'radiogroup' | undefined\n\t>;\n}\n\nexport interface FigcaptionHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'group' | 'none' | 'presentation' | undefined>;\n}\n\nexport interface FooterHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t| 'contentinfo'\n\t\t| 'group'\n\t\t| 'none'\n\t\t| 'presentation'\n\t\t| 'doc-footnote'\n\t\t| undefined\n\t>;\n}\n\nexport interface FormHTMLAttributes<T extends EventTarget = HTMLFormElement>\n\textends HTMLAttributes<T> {\n\t'accept-charset'?: Signalish<string | undefined>;\n\tacceptCharset?: Signalish<string | undefined>;\n\taction?: Signalish<string | undefined>;\n\tautocomplete?: Signalish<string | undefined>;\n\tautoComplete?: Signalish<string | undefined>;\n\tenctype?: Signalish<string | undefined>;\n\tencType?: Signalish<string | undefined>;\n\tmethod?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n\tnovalidate?: Signalish<boolean | undefined>;\n\tnoValidate?: Signalish<boolean | undefined>;\n\trel?: Signalish<string | undefined>;\n\trole?: Signalish<'form' | 'none' | 'presentation' | 'search' | undefined>;\n\ttarget?: Signalish<string | undefined>;\n}\n\nexport interface HeadingHTMLAttributes<\n\tT extends EventTarget = HTMLHeadingElement\n> extends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t'heading' | 'none' | 'presentation' | 'tab' | 'doc-subtitle' | undefined\n\t>;\n}\n\nexport interface HeadHTMLAttributes<T extends EventTarget = HTMLHeadElement>\n\textends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface HeaderHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'banner' | 'group' | 'none' | 'presentation' | undefined>;\n}\n\nexport interface HrHTMLAttributes<T extends EventTarget = HTMLHRElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t'separator' | 'none' | 'presentation' | 'doc-pagebreak' | undefined\n\t>;\n}\n\nexport interface HtmlHTMLAttributes<T extends EventTarget = HTMLHtmlElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'document' | undefined>;\n}\n\nexport interface IframeHTMLAttributes<T extends EventTarget = HTMLIFrameElement>\n\textends HTMLAttributes<T> {\n\tallow?: Signalish<string | undefined>;\n\tallowFullScreen?: Signalish<boolean | undefined>;\n\tallowTransparency?: Signalish<boolean | undefined>;\n\t/** @deprecated */\n\tframeborder?: Signalish<number | string | undefined>;\n\t/** @deprecated */\n\tframeBorder?: Signalish<number | string | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\tloading?: Signalish<'eager' | 'lazy' | undefined>;\n\t/** @deprecated */\n\tmarginHeight?: Signalish<number | undefined>;\n\t/** @deprecated */\n\tmarginWidth?: Signalish<number | undefined>;\n\tname?: Signalish<string | undefined>;\n\treferrerpolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\treferrerPolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\trole?: Signalish<\n\t\t'application' | 'document' | 'img' | 'none' | 'presentation' | undefined\n\t>;\n\tsandbox?: Signalish<string | undefined>;\n\t/** @deprecated */\n\tscrolling?: Signalish<string | undefined>;\n\tseamless?: Signalish<boolean | undefined>;\n\tsrc?: Signalish<string | undefined>;\n\tsrcdoc?: Signalish<string | undefined>;\n\tsrcDoc?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport type HTMLAttributeCrossOrigin = 'anonymous' | 'use-credentials';\n\nexport interface PartialImgHTMLAttributes<T extends EventTarget>\n\textends HTMLAttributes<T> {\n\tcrossorigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tcrossOrigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tdecoding?: Signalish<'async' | 'auto' | 'sync' | undefined>;\n\tfetchpriority?: Signalish<'high' | 'auto' | 'low' | undefined>;\n\tfetchPriority?: Signalish<'high' | 'auto' | 'low' | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\tloading?: Signalish<'eager' | 'lazy' | undefined>;\n\treferrerpolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\treferrerPolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\tsizes?: Signalish<string | undefined>;\n\tsrc?: Signalish<string | undefined>;\n\tsrcset?: Signalish<string | undefined>;\n\tsrcSet?: Signalish<string | undefined>;\n\tusemap?: Signalish<string | undefined>;\n\tuseMap?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport type ImgAriaRolesAccessibleName = Signalish<\n\t| 'img'\n\t| 'button'\n\t| 'checkbox'\n\t| 'link'\n\t| 'menuitem'\n\t| 'menuitemcheckbox'\n\t| 'menuitemradio'\n\t| 'meter'\n\t| 'option'\n\t| 'progressbar'\n\t| 'radio'\n\t| 'scrollbar'\n\t| 'separator'\n\t| 'slider'\n\t| 'switch'\n\t| 'tab'\n\t| 'treeitem'\n\t| 'doc-cover'\n\t| undefined\n>;\n\nexport type ImgAriaRoles =\n\t| {\n\t\t\t'aria-label': Signalish<string>;\n\t\t\trole?: ImgAriaRolesAccessibleName;\n\t  }\n\t| {\n\t\t\t'aria-labelledby': Signalish<string>;\n\t\t\trole?: ImgAriaRolesAccessibleName;\n\t  }\n\t| {\n\t\t\talt: Signalish<string>;\n\t\t\trole?: ImgAriaRolesAccessibleName;\n\t  }\n\t| {\n\t\t\ttitle: Signalish<string>;\n\t\t\trole?: ImgAriaRolesAccessibleName;\n\t  }\n\t| {\n\t\t\t'aria-label'?: never;\n\t\t\t'aria-labelledby'?: never;\n\t\t\talt?: never;\n\t\t\ttitle?: never;\n\t\t\trole?: Signalish<'img' | 'none' | 'presentation' | undefined>;\n\t  };\n\nexport type AccessibleImgHTMLAttributes<\n\tT extends EventTarget = HTMLImageElement\n> = Omit<\n\tPartialImgHTMLAttributes<T>,\n\t'role' | 'aria-label' | 'aria-labelledby' | 'title'\n> &\n\tImgAriaRoles;\n\nexport interface ImgHTMLAttributes<T extends EventTarget = HTMLImageElement>\n\textends PartialImgHTMLAttributes<T> {\n\talt?: Signalish<string | undefined>;\n\t'aria-label'?: Signalish<string | undefined>;\n\t'aria-labelledby'?: Signalish<string | undefined>;\n\thref?: Signalish<string | undefined>;\n\trole?:\n\t\t| ImgAriaRolesAccessibleName\n\t\t| Signalish<'img' | 'none' | 'presentation' | undefined>;\n\ttitle?: Signalish<string | undefined>;\n}\n\nexport type HTMLInputTypeAttribute =\n\t| 'button'\n\t| 'checkbox'\n\t| 'color'\n\t| 'date'\n\t| 'datetime-local'\n\t| 'email'\n\t| 'file'\n\t| 'hidden'\n\t| 'image'\n\t| 'month'\n\t| 'number'\n\t| 'password'\n\t| 'radio'\n\t| 'range'\n\t| 'reset'\n\t| 'search'\n\t| 'submit'\n\t| 'tel'\n\t| 'text'\n\t| 'time'\n\t| 'url'\n\t| 'week';\n\nexport interface PartialInputHTMLAttributes<T extends EventTarget>\n\textends HTMLAttributes<T> {\n\taccept?: Signalish<string | undefined>;\n\talt?: Signalish<string | undefined>;\n\tautocomplete?: Signalish<string | undefined>;\n\tautoComplete?: Signalish<string | undefined>;\n\tcapture?: Signalish<'user' | 'environment' | undefined>; // https://www.w3.org/TR/html-media-capture/#the-capture-attribute\n\tchecked?: Signalish<boolean | undefined>;\n\tdefaultChecked?: Signalish<boolean | undefined>;\n\tdefaultValue?: Signalish<string | number | undefined>;\n\tdisabled?: Signalish<boolean | undefined>;\n\tenterKeyHint?: Signalish<\n\t\t| 'enter'\n\t\t| 'done'\n\t\t| 'go'\n\t\t| 'next'\n\t\t| 'previous'\n\t\t| 'search'\n\t\t| 'send'\n\t\t| undefined\n\t>;\n\tform?: Signalish<string | undefined>;\n\tformaction?: Signalish<string | undefined>;\n\tformAction?: Signalish<string | undefined>;\n\tformenctype?: Signalish<string | undefined>;\n\tformEncType?: Signalish<string | undefined>;\n\tformmethod?: Signalish<string | undefined>;\n\tformMethod?: Signalish<string | undefined>;\n\tformnovalidate?: Signalish<boolean | undefined>;\n\tformNoValidate?: Signalish<boolean | undefined>;\n\tformtarget?: Signalish<string | undefined>;\n\tformTarget?: Signalish<string | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\tindeterminate?: Signalish<boolean | undefined>;\n\tmax?: Signalish<number | string | undefined>;\n\tmaxlength?: Signalish<number | undefined>;\n\tmaxLength?: Signalish<number | undefined>;\n\tmin?: Signalish<number | string | undefined>;\n\tminlength?: Signalish<number | undefined>;\n\tminLength?: Signalish<number | undefined>;\n\tmultiple?: Signalish<boolean | undefined>;\n\tname?: Signalish<string | undefined>;\n\tpattern?: Signalish<string | undefined>;\n\tplaceholder?: Signalish<string | undefined>;\n\treadonly?: Signalish<boolean | undefined>;\n\treadOnly?: Signalish<boolean | undefined>;\n\trequired?: Signalish<boolean | undefined>;\n\tsize?: Signalish<number | undefined>;\n\tsrc?: Signalish<string | undefined>;\n\tstep?: Signalish<number | string | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n\tonChange?: GenericEventHandler<T> | undefined;\n}\n\nexport type InputAriaRoles =\n\t| {\n\t\t\ttype: Signalish<'button'>;\n\t\t\trole?: Signalish<\n\t\t\t\t| 'button'\n\t\t\t\t| 'checkbox'\n\t\t\t\t| 'combobox'\n\t\t\t\t| 'gridcell'\n\t\t\t\t| 'link'\n\t\t\t\t| 'menuitem'\n\t\t\t\t| 'menuitemcheckbox'\n\t\t\t\t| 'menuitemradio'\n\t\t\t\t| 'option'\n\t\t\t\t| 'radio'\n\t\t\t\t| 'separator'\n\t\t\t\t| 'slider'\n\t\t\t\t| 'switch'\n\t\t\t\t| 'tab'\n\t\t\t\t| 'treeitem'\n\t\t\t\t| undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'checkbox'>;\n\t\t\trole?: Signalish<\n\t\t\t\t| 'checkbox'\n\t\t\t\t| 'button'\n\t\t\t\t| 'menuitemcheckbox'\n\t\t\t\t| 'option'\n\t\t\t\t| 'switch'\n\t\t\t\t| undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'email'>;\n\t\t\tlist?: never;\n\t\t\trole?: Signalish<'textbox' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'image'>;\n\t\t\trole?: Signalish<\n\t\t\t\t| 'button'\n\t\t\t\t| 'checkbox'\n\t\t\t\t| 'gridcell'\n\t\t\t\t| 'link'\n\t\t\t\t| 'menuitem'\n\t\t\t\t| 'menuitemcheckbox'\n\t\t\t\t| 'menuitemradio'\n\t\t\t\t| 'option'\n\t\t\t\t| 'separator'\n\t\t\t\t| 'slider'\n\t\t\t\t| 'switch'\n\t\t\t\t| 'tab'\n\t\t\t\t| 'treeitem'\n\t\t\t\t| undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'number'>;\n\t\t\trole?: Signalish<'spinbutton' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'radio'>;\n\t\t\trole?: Signalish<'radio' | 'menuitemradio' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'range'>;\n\t\t\trole?: Signalish<'slider' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'reset'>;\n\t\t\trole?: Signalish<\n\t\t\t\t| 'button'\n\t\t\t\t| 'checkbox'\n\t\t\t\t| 'combobox'\n\t\t\t\t| 'gridcell'\n\t\t\t\t| 'link'\n\t\t\t\t| 'menuitem'\n\t\t\t\t| 'menuitemcheckbox'\n\t\t\t\t| 'menuitemradio'\n\t\t\t\t| 'option'\n\t\t\t\t| 'radio'\n\t\t\t\t| 'separator'\n\t\t\t\t| 'slider'\n\t\t\t\t| 'switch'\n\t\t\t\t| 'tab'\n\t\t\t\t| 'treeitem'\n\t\t\t\t| undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'search'>;\n\t\t\tlist?: never;\n\t\t\trole?: Signalish<'searchbox' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'submit'>;\n\t\t\trole?: Signalish<\n\t\t\t\t| 'button'\n\t\t\t\t| 'checkbox'\n\t\t\t\t| 'combobox'\n\t\t\t\t| 'gridcell'\n\t\t\t\t| 'link'\n\t\t\t\t| 'menuitem'\n\t\t\t\t| 'menuitemcheckbox'\n\t\t\t\t| 'menuitemradio'\n\t\t\t\t| 'option'\n\t\t\t\t| 'radio'\n\t\t\t\t| 'separator'\n\t\t\t\t| 'slider'\n\t\t\t\t| 'switch'\n\t\t\t\t| 'tab'\n\t\t\t\t| 'treeitem'\n\t\t\t\t| undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'tel'>;\n\t\t\tlist?: never;\n\t\t\trole?: Signalish<'textbox' | undefined>;\n\t  }\n\t| {\n\t\t\ttype?: Signalish<'text'>;\n\t\t\tlist?: never;\n\t\t\trole?: Signalish<\n\t\t\t\t'textbox' | 'combobox' | 'searchbox' | 'spinbutton' | undefined\n\t\t\t>;\n\t  }\n\t| {\n\t\t\ttype?: Signalish<'text' | 'search' | 'tel' | 'url' | 'email'>;\n\t\t\tlist: Signalish<string | undefined>;\n\t\t\trole?: Signalish<'combobox' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<'url'>;\n\t\t\tlist?: never;\n\t\t\trole?: Signalish<'textbox' | undefined>;\n\t  }\n\t| {\n\t\t\ttype: Signalish<\n\t\t\t\t| 'color'\n\t\t\t\t| 'date'\n\t\t\t\t| 'datetime-local'\n\t\t\t\t| 'file'\n\t\t\t\t| 'hidden'\n\t\t\t\t| 'month'\n\t\t\t\t| 'password'\n\t\t\t\t| 'time'\n\t\t\t\t| 'week'\n\t\t\t>;\n\t\t\trole?: never;\n\t  };\n\nexport type AccessibleInputHTMLAttributes<\n\tT extends EventTarget = HTMLInputElement\n> = Omit<PartialInputHTMLAttributes<T>, 'role'> & InputAriaRoles;\n\nexport interface InputHTMLAttributes<T extends EventTarget = HTMLInputElement>\n\textends PartialInputHTMLAttributes<T> {\n\ttype?: Signalish<HTMLInputTypeAttribute | undefined>;\n\trole?: Signalish<\n\t\t| 'button'\n\t\t| 'checkbox'\n\t\t| 'combobox'\n\t\t| 'gridcell'\n\t\t| 'link'\n\t\t| 'menuitem'\n\t\t| 'menuitemcheckbox'\n\t\t| 'menuitemradio'\n\t\t| 'option'\n\t\t| 'radio'\n\t\t| 'searchbox'\n\t\t| 'separator'\n\t\t| 'slider'\n\t\t| 'spinbutton'\n\t\t| 'switch'\n\t\t| 'tab'\n\t\t| 'textbox'\n\t\t| 'treeitem'\n\t\t| undefined\n\t>;\n}\n\nexport interface InsHTMLAttributes<T extends EventTarget = HTMLModElement>\n\textends HTMLAttributes<T> {\n\tcite?: Signalish<string | undefined>;\n\tdatetime?: Signalish<string | undefined>;\n\tdateTime?: Signalish<string | undefined>;\n}\n\nexport interface KeygenHTMLAttributes<\n\tT extends EventTarget = HTMLUnknownElement\n> extends HTMLAttributes<T> {\n\tchallenge?: Signalish<string | undefined>;\n\tdisabled?: Signalish<boolean | undefined>;\n\tform?: Signalish<string | undefined>;\n\tkeyType?: Signalish<string | undefined>;\n\tkeyParams?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n}\n\nexport interface LabelHTMLAttributes<T extends EventTarget = HTMLLabelElement>\n\textends HTMLAttributes<T> {\n\tfor?: Signalish<string | undefined>;\n\tform?: Signalish<string | undefined>;\n\thtmlFor?: Signalish<string | undefined>;\n\trole?: never;\n}\n\nexport interface LegendHTMLAttributes<T extends EventTarget = HTMLLegendElement>\n\textends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface LiHTMLAttributes<T extends EventTarget = HTMLLIElement>\n\textends HTMLAttributes<T> {\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface LinkHTMLAttributes<T extends EventTarget = HTMLLinkElement>\n\textends HTMLAttributes<T> {\n\tas?: Signalish<string | undefined>;\n\tcrossorigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tcrossOrigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tfetchpriority?: Signalish<'high' | 'low' | 'auto' | undefined>;\n\tfetchPriority?: Signalish<'high' | 'low' | 'auto' | undefined>;\n\thref?: Signalish<string | undefined>;\n\threflang?: Signalish<string | undefined>;\n\threfLang?: Signalish<string | undefined>;\n\tintegrity?: Signalish<string | undefined>;\n\tmedia?: Signalish<string | undefined>;\n\timageSrcSet?: Signalish<string | undefined>;\n\treferrerpolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\treferrerPolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\trel?: Signalish<string | undefined>;\n\trole?: never;\n\tsizes?: Signalish<string | undefined>;\n\ttype?: Signalish<string | undefined>;\n\tcharset?: Signalish<string | undefined>;\n\tcharSet?: Signalish<string | undefined>;\n}\n\nexport interface MainHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'main' | undefined>;\n}\n\nexport interface MapHTMLAttributes<T extends EventTarget = HTMLMapElement>\n\textends HTMLAttributes<T> {\n\tname?: Signalish<string | undefined>;\n\trole?: never;\n}\n\nexport interface MarqueeHTMLAttributes<\n\tT extends EventTarget = HTMLMarqueeElement\n> extends HTMLAttributes<T> {\n\tbehavior?: Signalish<'scroll' | 'slide' | 'alternate' | undefined>;\n\tbgColor?: Signalish<string | undefined>;\n\tdirection?: Signalish<'left' | 'right' | 'up' | 'down' | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\thspace?: Signalish<number | string | undefined>;\n\tloop?: Signalish<number | string | undefined>;\n\tscrollAmount?: Signalish<number | string | undefined>;\n\tscrollDelay?: Signalish<number | string | undefined>;\n\ttrueSpeed?: Signalish<boolean | undefined>;\n\tvspace?: Signalish<number | string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport interface MediaHTMLAttributes<T extends EventTarget = HTMLMediaElement>\n\textends HTMLAttributes<T> {\n\tautoplay?: Signalish<boolean | undefined>;\n\tautoPlay?: Signalish<boolean | undefined>;\n\tcontrols?: Signalish<boolean | undefined>;\n\tcontrolslist?: Signalish<string | undefined>;\n\tcontrolsList?: Signalish<string | undefined>;\n\tcrossorigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tcrossOrigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tcurrentTime?: Signalish<number | undefined>;\n\tdefaultMuted?: Signalish<boolean | undefined>;\n\tdefaultPlaybackRate?: Signalish<number | undefined>;\n\tdisableremoteplayback?: Signalish<boolean | undefined>;\n\tdisableRemotePlayback?: Signalish<boolean | undefined>;\n\tloop?: Signalish<boolean | undefined>;\n\tmediaGroup?: Signalish<string | undefined>;\n\tmuted?: Signalish<boolean | undefined>;\n\tplaybackRate?: Signalish<number | undefined>;\n\tpreload?: Signalish<'auto' | 'metadata' | 'none' | undefined>;\n\tpreservesPitch?: Signalish<boolean | undefined>;\n\tsrc?: Signalish<string | undefined>;\n\tsrcObject?: Signalish<MediaStream | MediaSource | Blob | File | null>;\n\tvolume?: Signalish<string | number | undefined>;\n}\n\nexport interface MenuHTMLAttributes<T extends EventTarget = HTMLMenuElement>\n\textends HTMLAttributes<T> {\n\trole:\n\t\t| 'list'\n\t\t| 'group'\n\t\t| 'listbox'\n\t\t| 'menu'\n\t\t| 'menubar'\n\t\t| 'none'\n\t\t| 'presentation'\n\t\t| 'radiogroup'\n\t\t| 'tablist'\n\t\t| 'toolbar'\n\t\t| 'tree';\n\ttype?: Signalish<string | undefined>;\n}\n\nexport interface MetaHTMLAttributes<T extends EventTarget = HTMLMetaElement>\n\textends HTMLAttributes<T> {\n\tcharset?: Signalish<string | undefined>;\n\tcharSet?: Signalish<string | undefined>;\n\tcontent?: Signalish<string | undefined>;\n\t'http-equiv'?: Signalish<string | undefined>;\n\thttpEquiv?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n\tmedia?: Signalish<string | undefined>;\n\trole?: never;\n}\n\nexport interface MeterHTMLAttributes<T extends EventTarget = HTMLMeterElement>\n\textends HTMLAttributes<T> {\n\tform?: Signalish<string | undefined>;\n\thigh?: Signalish<number | undefined>;\n\tlow?: Signalish<number | undefined>;\n\tmax?: Signalish<number | string | undefined>;\n\tmin?: Signalish<number | string | undefined>;\n\toptimum?: Signalish<number | undefined>;\n\trole?: Signalish<'meter' | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface NavHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t| 'navigation'\n\t\t| 'menu'\n\t\t| 'menubar'\n\t\t| 'none'\n\t\t| 'presentation'\n\t\t| 'tablist'\n\t\t| undefined\n\t>;\n}\n\nexport interface NoScriptHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface ObjectHTMLAttributes<T extends EventTarget = HTMLObjectElement>\n\textends HTMLAttributes<T> {\n\tclassID?: Signalish<string | undefined>;\n\tdata?: Signalish<string | undefined>;\n\tform?: Signalish<string | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\tname?: Signalish<string | undefined>;\n\trole?: Signalish<'application' | 'document' | 'img' | undefined>;\n\ttype?: Signalish<string | undefined>;\n\tusemap?: Signalish<string | undefined>;\n\tuseMap?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n\twmode?: Signalish<string | undefined>;\n}\n\nexport interface OlHTMLAttributes<T extends EventTarget = HTMLOListElement>\n\textends HTMLAttributes<T> {\n\treversed?: Signalish<boolean | undefined>;\n\trole?: Signalish<\n\t\t| 'list'\n\t\t| 'group'\n\t\t| 'listbox'\n\t\t| 'menu'\n\t\t| 'menubar'\n\t\t| 'none'\n\t\t| 'presentation'\n\t\t| 'radiogroup'\n\t\t| 'tablist'\n\t\t| 'toolbar'\n\t\t| 'tree'\n\t\t| undefined\n\t>;\n\tstart?: Signalish<number | undefined>;\n\ttype?: Signalish<'1' | 'a' | 'A' | 'i' | 'I' | undefined>;\n}\n\nexport interface OptgroupHTMLAttributes<\n\tT extends EventTarget = HTMLOptGroupElement\n> extends HTMLAttributes<T> {\n\tdisabled?: Signalish<boolean | undefined>;\n\tlabel?: Signalish<string | undefined>;\n\trole?: Signalish<'group' | undefined>;\n}\n\nexport interface OptionHTMLAttributes<T extends EventTarget = HTMLOptionElement>\n\textends HTMLAttributes<T> {\n\tdisabled?: Signalish<boolean | undefined>;\n\tlabel?: Signalish<string | undefined>;\n\trole?: Signalish<'option' | undefined>;\n\tselected?: Signalish<boolean | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface OutputHTMLAttributes<T extends EventTarget = HTMLOutputElement>\n\textends HTMLAttributes<T> {\n\tfor?: Signalish<string | undefined>;\n\tform?: Signalish<string | undefined>;\n\thtmlFor?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n}\n\nexport interface ParamHTMLAttributes<T extends EventTarget = HTMLParamElement>\n\textends HTMLAttributes<T> {\n\tname?: Signalish<string | undefined>;\n\trole?: never;\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface PictureHTMLAttributes<\n\tT extends EventTarget = HTMLPictureElement\n> extends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface ProgressHTMLAttributes<\n\tT extends EventTarget = HTMLProgressElement\n> extends HTMLAttributes<T> {\n\tmax?: Signalish<number | string | undefined>;\n\trole?: Signalish<'progressbar' | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n}\n\nexport interface QuoteHTMLAttributes<T extends EventTarget = HTMLQuoteElement>\n\textends HTMLAttributes<T> {\n\tcite?: Signalish<string | undefined>;\n}\n\nexport interface ScriptHTMLAttributes<T extends EventTarget = HTMLScriptElement>\n\textends HTMLAttributes<T> {\n\tasync?: Signalish<boolean | undefined>;\n\t/** @deprecated */\n\tcharset?: Signalish<string | undefined>;\n\t/** @deprecated */\n\tcharSet?: Signalish<string | undefined>;\n\tcrossorigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tcrossOrigin?: Signalish<HTMLAttributeCrossOrigin>;\n\tdefer?: Signalish<boolean | undefined>;\n\tintegrity?: Signalish<string | undefined>;\n\tnomodule?: Signalish<boolean | undefined>;\n\tnoModule?: Signalish<boolean | undefined>;\n\treferrerpolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\treferrerPolicy?: Signalish<HTMLAttributeReferrerPolicy | undefined>;\n\trole?: never;\n\tsrc?: Signalish<string | undefined>;\n\ttype?: Signalish<string | undefined>;\n}\n\nexport interface SearchHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t'search' | 'form' | 'group' | 'none' | 'presentation' | 'region' | undefined\n\t>;\n}\n\nexport interface PartialSelectHTMLAttributes<T extends EventTarget>\n\textends HTMLAttributes<T> {\n\tautocomplete?: Signalish<string | undefined>;\n\tautoComplete?: Signalish<string | undefined>;\n\tdefaultValue?: Signalish<string | number | undefined>;\n\tdisabled?: Signalish<boolean | undefined>;\n\tform?: Signalish<string | undefined>;\n\tname?: Signalish<string | undefined>;\n\trequired?: Signalish<boolean | undefined>;\n\tsize?: Signalish<number | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n\tonChange?: GenericEventHandler<T> | undefined;\n}\n\nexport type SelectAriaRoles =\n\t| {\n\t\t\tmultiple?: never;\n\t\t\t// Spec states this branch is limited to \"no `multiple` attribute AND no `size` attribute greater than 1\".\n\t\t\t// `1` as a default, however, caused some web compat issues and forced Firefox to default to `0` instead.\n\t\t\tsize?: 0 | 1 | never;\n\t\t\trole?: Signalish<'combobox' | 'menu' | undefined>;\n\t  }\n\t| {\n\t\t\tmultiple?: Signalish<boolean | undefined>;\n\t\t\tsize?: Signalish<number | undefined>;\n\t\t\trole?: Signalish<'listbox' | undefined>;\n\t  };\n\nexport type AccessibleSelectHTMLAttributes<\n\tT extends EventTarget = HTMLSelectElement\n> = Omit<PartialSelectHTMLAttributes<T>, 'role'> & SelectAriaRoles;\n\nexport interface SelectHTMLAttributes<T extends EventTarget = HTMLSelectElement>\n\textends PartialSelectHTMLAttributes<T> {\n\tmultiple?: Signalish<boolean | undefined>;\n\tsize?: Signalish<number | undefined>;\n\ttype?: Signalish<HTMLInputTypeAttribute | undefined>;\n\trole?: Signalish<'combobox' | 'listbox' | 'menu' | undefined>;\n}\n\nexport interface SlotHTMLAttributes<T extends EventTarget = HTMLSlotElement>\n\textends HTMLAttributes<T> {\n\tname?: Signalish<string | undefined>;\n\trole?: never;\n}\n\nexport interface SourceHTMLAttributes<T extends EventTarget = HTMLSourceElement>\n\textends HTMLAttributes<T> {\n\theight?: Signalish<number | string | undefined>;\n\tmedia?: Signalish<string | undefined>;\n\trole?: never;\n\tsizes?: Signalish<string | undefined>;\n\tsrc?: Signalish<string | undefined>;\n\tsrcset?: Signalish<string | undefined>;\n\tsrcSet?: Signalish<string | undefined>;\n\ttype?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport interface StyleHTMLAttributes<T extends EventTarget = HTMLStyleElement>\n\textends HTMLAttributes<T> {\n\tmedia?: Signalish<string | undefined>;\n\trole?: never;\n\tscoped?: Signalish<boolean | undefined>;\n\ttype?: Signalish<string | undefined>;\n}\n\nexport interface TableHTMLAttributes<T extends EventTarget = HTMLTableElement>\n\textends HTMLAttributes<T> {\n\tcellPadding?: Signalish<string | undefined>;\n\tcellSpacing?: Signalish<string | undefined>;\n\tsummary?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n}\n\nexport interface TdHTMLAttributes<T extends EventTarget = HTMLTableCellElement>\n\textends HTMLAttributes<T> {\n\talign?: Signalish<\n\t\t'left' | 'center' | 'right' | 'justify' | 'char' | undefined\n\t>;\n\tcolspan?: Signalish<number | undefined>;\n\tcolSpan?: Signalish<number | undefined>;\n\theaders?: Signalish<string | undefined>;\n\trowspan?: Signalish<number | undefined>;\n\trowSpan?: Signalish<number | undefined>;\n\tscope?: Signalish<string | undefined>;\n\tabbr?: Signalish<string | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n\tvalign?: Signalish<'top' | 'middle' | 'bottom' | 'baseline' | undefined>;\n}\n\nexport interface TemplateHTMLAttributes<\n\tT extends EventTarget = HTMLTemplateElement\n> extends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface TextareaHTMLAttributes<\n\tT extends EventTarget = HTMLTextAreaElement\n> extends HTMLAttributes<T> {\n\tautocomplete?: Signalish<string | undefined>;\n\tautoComplete?: Signalish<string | undefined>;\n\tcols?: Signalish<number | undefined>;\n\tdefaultValue?: Signalish<string | number | undefined>;\n\tdirName?: Signalish<string | undefined>;\n\tdisabled?: Signalish<boolean | undefined>;\n\tform?: Signalish<string | undefined>;\n\tmaxlength?: Signalish<number | undefined>;\n\tmaxLength?: Signalish<number | undefined>;\n\tminlength?: Signalish<number | undefined>;\n\tminLength?: Signalish<number | undefined>;\n\tname?: Signalish<string | undefined>;\n\tplaceholder?: Signalish<string | undefined>;\n\treadOnly?: Signalish<boolean | undefined>;\n\trequired?: Signalish<boolean | undefined>;\n\trole?: Signalish<'textbox' | undefined>;\n\trows?: Signalish<number | undefined>;\n\tvalue?: Signalish<string | number | undefined>;\n\twrap?: Signalish<string | undefined>;\n\tonChange?: GenericEventHandler<T> | undefined;\n}\n\nexport interface ThHTMLAttributes<T extends EventTarget = HTMLTableCellElement>\n\textends HTMLAttributes<T> {\n\talign?: Signalish<\n\t\t'left' | 'center' | 'right' | 'justify' | 'char' | undefined\n\t>;\n\tcolspan?: Signalish<number | undefined>;\n\tcolSpan?: Signalish<number | undefined>;\n\theaders?: Signalish<string | undefined>;\n\trowspan?: Signalish<number | undefined>;\n\trowSpan?: Signalish<number | undefined>;\n\tscope?: Signalish<string | undefined>;\n\tabbr?: Signalish<string | undefined>;\n}\n\nexport interface TimeHTMLAttributes<T extends EventTarget = HTMLTimeElement>\n\textends HTMLAttributes<T> {\n\tdatetime?: Signalish<string | undefined>;\n\tdateTime?: Signalish<string | undefined>;\n}\n\nexport interface TitleHTMLAttributes<T extends EventTarget = HTMLTitleElement>\n\textends HTMLAttributes<T> {\n\trole?: never;\n}\n\nexport interface TrackHTMLAttributes<T extends EventTarget = HTMLTrackElement>\n\textends MediaHTMLAttributes<T> {\n\tdefault?: Signalish<boolean | undefined>;\n\tkind?: Signalish<string | undefined>;\n\tlabel?: Signalish<string | undefined>;\n\trole?: never;\n\tsrclang?: Signalish<string | undefined>;\n\tsrcLang?: Signalish<string | undefined>;\n}\n\nexport interface UlHTMLAttributes<T extends EventTarget = HTMLUListElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<\n\t\t| 'list'\n\t\t| 'group'\n\t\t| 'listbox'\n\t\t| 'menu'\n\t\t| 'menubar'\n\t\t| 'none'\n\t\t| 'presentation'\n\t\t| 'radiogroup'\n\t\t| 'tablist'\n\t\t| 'toolbar'\n\t\t| 'tree'\n\t\t| undefined\n\t>;\n}\n\nexport interface VideoHTMLAttributes<T extends EventTarget = HTMLVideoElement>\n\textends MediaHTMLAttributes<T> {\n\tdisablePictureInPicture?: Signalish<boolean | undefined>;\n\theight?: Signalish<number | string | undefined>;\n\tplaysinline?: Signalish<boolean | undefined>;\n\tplaysInline?: Signalish<boolean | undefined>;\n\tposter?: Signalish<string | undefined>;\n\twidth?: Signalish<number | string | undefined>;\n\trole?: Signalish<'application' | undefined>;\n}\n\nexport interface WbrHTMLAttributes<T extends EventTarget = HTMLElement>\n\textends HTMLAttributes<T> {\n\trole?: Signalish<'none' | 'presentation' | undefined>;\n}\n\nexport type DetailedHTMLProps<\n\tHA extends HTMLAttributes<RefType>,\n\tRefType extends EventTarget = EventTarget\n> = HA;\n\nexport interface MathMLAttributes<Target extends EventTarget = MathMLElement>\n\textends HTMLAttributes<Target> {\n\tdir?: Signalish<'ltr' | 'rtl' | undefined>;\n\tdisplaystyle?: Signalish<boolean | undefined>;\n\t/** @deprecated This feature is non-standard. See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/href  */\n\thref?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/mathbackground */\n\tmathbackground?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/mathcolor */\n\tmathcolor?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/mathsize */\n\tmathsize?: Signalish<string | undefined>;\n\tnonce?: Signalish<string | undefined>;\n\tscriptlevel?: Signalish<string | undefined>;\n}\n\nexport interface AnnotationMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tencoding?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/semantics#src */\n\tsrc?: Signalish<string | undefined>;\n}\n\nexport interface AnnotationXmlMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tencoding?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/semantics#src */\n\tsrc?: Signalish<string | undefined>;\n}\n\nexport interface MActionMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction#actiontype */\n\tactiontype?: Signalish<'statusline' | 'toggle' | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction#selection */\n\tselection?: Signalish<string | undefined>;\n}\n\nexport interface MathMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tdisplay?: Signalish<'block' | 'inline' | undefined>;\n}\n\nexport interface MEncloseMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tnotation?: Signalish<string | undefined>;\n}\n\nexport interface MErrorMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MFencedMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tclose?: Signalish<string | undefined>;\n\topen?: Signalish<string | undefined>;\n\tseparators?: Signalish<string | undefined>;\n}\n\nexport interface MFracMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfrac#denomalign */\n\tdenomalign?: Signalish<'center' | 'left' | 'right' | undefined>;\n\tlinethickness?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfrac#numalign */\n\tnumalign?: Signalish<'center' | 'left' | 'right' | undefined>;\n}\n\nexport interface MiMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** The only value allowed in the current specification is normal (case insensitive)\n\t * See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mi#mathvariant */\n\tmathvariant?: Signalish<\n\t\t| 'normal'\n\t\t| 'bold'\n\t\t| 'italic'\n\t\t| 'bold-italic'\n\t\t| 'double-struck'\n\t\t| 'bold-fraktur'\n\t\t| 'script'\n\t\t| 'bold-script'\n\t\t| 'fraktur'\n\t\t| 'sans-serif'\n\t\t| 'bold-sans-serif'\n\t\t| 'sans-serif-italic'\n\t\t| 'sans-serif-bold-italic'\n\t\t| 'monospace'\n\t\t| 'initial'\n\t\t| 'tailed'\n\t\t| 'looped'\n\t\t| 'stretched'\n\t\t| undefined\n\t>;\n}\n\nexport interface MmultiScriptsMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mmultiscripts#subscriptshift */\n\tsubscriptshift?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mmultiscripts#superscriptshift */\n\tsuperscriptshift?: Signalish<string | undefined>;\n}\n\nexport interface MNMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MOMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo#accent */\n\taccent?: Signalish<boolean | undefined>;\n\tfence?: Signalish<boolean | undefined>;\n\tlargeop?: Signalish<boolean | undefined>;\n\tlspace?: Signalish<string | undefined>;\n\tmaxsize?: Signalish<string | undefined>;\n\tminsize?: Signalish<string | undefined>;\n\tmovablelimits?: Signalish<boolean | undefined>;\n\trspace?: Signalish<string | undefined>;\n\tseparator?: Signalish<boolean | undefined>;\n\tstretchy?: Signalish<boolean | undefined>;\n\tsymmetric?: Signalish<boolean | undefined>;\n}\n\nexport interface MOverMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\taccent?: Signalish<boolean | undefined>;\n}\n\nexport interface MPaddedMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tdepth?: Signalish<string | undefined>;\n\theight?: Signalish<string | undefined>;\n\tlspace?: Signalish<string | undefined>;\n\tvoffset?: Signalish<string | undefined>;\n\twidth?: Signalish<string | undefined>;\n}\n\nexport interface MPhantomMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MPrescriptsMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MRootMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MRowMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MSMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/ms#browser_compatibility */\n\tlquote?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/ms#browser_compatibility */\n\trquote?: Signalish<string | undefined>;\n}\n\nexport interface MSpaceMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tdepth?: Signalish<string | undefined>;\n\theight?: Signalish<string | undefined>;\n\twidth?: Signalish<string | undefined>;\n}\n\nexport interface MSqrtMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MStyleMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#background */\n\tbackground?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#color */\n\tcolor?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#fontsize */\n\tfontsize?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#fontstyle */\n\tfontstyle?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#fontweight */\n\tfontweight?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#scriptminsize */\n\tscriptminsize?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#scriptsizemultiplier */\n\tscriptsizemultiplier?: Signalish<string | undefined>;\n}\n\nexport interface MSubMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msub#subscriptshift */\n\tsubscriptshift?: Signalish<string | undefined>;\n}\n\nexport interface MSubsupMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msubsup#subscriptshift */\n\tsubscriptshift?: Signalish<string | undefined>;\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msubsup#superscriptshift */\n\tsuperscriptshift?: Signalish<string | undefined>;\n}\n\nexport interface MSupMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msup#superscriptshift */\n\tsuperscriptshift?: Signalish<string | undefined>;\n}\n\nexport interface MTableMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#align */\n\talign?: Signalish<\n\t\t'axis' | 'baseline' | 'bottom' | 'center' | 'top' | undefined\n\t>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#columnalign */\n\tcolumnalign?: Signalish<'center' | 'left' | 'right' | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#columnlines */\n\tcolumnlines?: Signalish<'dashed' | 'none' | 'solid' | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#columnspacing */\n\tcolumnspacing?: Signalish<string | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#frame */\n\tframe?: Signalish<'dashed' | 'none' | 'solid' | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#framespacing */\n\tframespacing?: Signalish<string | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#rowalign */\n\trowalign?: Signalish<\n\t\t'axis' | 'baseline' | 'bottom' | 'center' | 'top' | undefined\n\t>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#rowlines */\n\trowlines?: Signalish<'dashed' | 'none' | 'solid' | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#rowspacing */\n\trowspacing?: Signalish<string | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#width */\n\twidth?: Signalish<string | undefined>;\n}\n\nexport interface MTdMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\tcolumnspan?: Signalish<number | undefined>;\n\trowspan?: Signalish<number | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtd#columnalign */\n\tcolumnalign?: Signalish<'center' | 'left' | 'right' | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtd#rowalign */\n\trowalign?: Signalish<\n\t\t'axis' | 'baseline' | 'bottom' | 'center' | 'top' | undefined\n\t>;\n}\n\nexport interface MTextMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n\nexport interface MTrMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtr#columnalign */\n\tcolumnalign?: Signalish<'center' | 'left' | 'right' | undefined>;\n\t/** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtr#rowalign */\n\trowalign?: Signalish<\n\t\t'axis' | 'baseline' | 'bottom' | 'center' | 'top' | undefined\n\t>;\n}\n\nexport interface MUnderMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\taccentunder?: Signalish<boolean | undefined>;\n}\n\nexport interface MUnderoverMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {\n\taccent?: Signalish<boolean | undefined>;\n\taccentunder?: Signalish<boolean | undefined>;\n}\n\nexport interface SemanticsMathMLAttributes<T extends EventTarget>\n\textends MathMLAttributes<T> {}\n"
  },
  {
    "path": "src/index.d.ts",
    "content": "export as namespace preact;\n\nimport { JSXInternal } from './jsx';\nimport { DOMAttributes, HTMLAttributes, SVGAttributes } from './dom';\n\nexport import JSX = JSXInternal;\nexport * from './dom';\n\n//\n// Preact Virtual DOM\n// -----------------------------------\n\nexport interface VNode<P = {}> {\n\ttype: ComponentType<P> | string;\n\tprops: P & { children: ComponentChildren };\n\tkey: Key;\n\t/**\n\t * ref is not guaranteed by React.ReactElement, for compatibility reasons\n\t * with popular react libs we define it as optional too\n\t */\n\tref?: Ref<any> | null;\n\t/**\n\t * The time this `vnode` started rendering. Will only be set when\n\t * the devtools are attached.\n\t * Default value: `0`\n\t */\n\tstartTime?: number;\n\t/**\n\t * The time that the rendering of this `vnode` was completed. Will only be\n\t * set when the devtools are attached.\n\t * Default value: `-1`\n\t */\n\tendTime?: number;\n}\n\n//\n// Preact Component interface\n// -----------------------------------\n\nexport type Key = string | number | any;\n\nexport type RefObject<T> = { current: T };\nexport type RefCallback<T> = (instance: T | null) => void | (() => void);\nexport type Ref<T> = RefCallback<T> | RefObject<T | null> | null;\n\nexport type ComponentChild =\n\t| VNode<any>\n\t| object\n\t| string\n\t| number\n\t| bigint\n\t| boolean\n\t| null\n\t| undefined;\nexport type ComponentChildren = ComponentChild[] | ComponentChild;\n\nexport interface Attributes {\n\tkey?: Key | undefined;\n\tjsx?: boolean | undefined;\n}\n\nexport interface ClassAttributes<T> extends Attributes {\n\tref?: Ref<T>;\n}\n\nexport interface PreactDOMAttributes {\n\tchildren?: ComponentChildren;\n\tdangerouslySetInnerHTML?: {\n\t\t__html: Parameters<DOMParser['parseFromString']>[0];\n\t};\n}\n\nexport interface ErrorInfo {\n\tcomponentStack?: string;\n}\n\nexport type RenderableProps<P, RefType = any> = P &\n\tReadonly<Attributes & { children?: ComponentChildren; ref?: Ref<RefType> }>;\n\nexport type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;\nexport type ComponentFactory<P = {}> = ComponentType<P>;\n\nexport type ComponentProps<\n\tC extends ComponentType<any> | keyof JSXInternal.IntrinsicElements\n> = C extends ComponentType<infer P>\n\t? P\n\t: C extends keyof JSXInternal.IntrinsicElements\n\t\t? JSXInternal.IntrinsicElements[C]\n\t\t: {};\n\nexport interface FunctionComponent<P = {}> {\n\t(props: RenderableProps<P>, context?: any): ComponentChildren;\n\tdisplayName?: string;\n}\nexport interface FunctionalComponent<P = {}> extends FunctionComponent<P> {}\n\nexport interface ComponentClass<P = {}, S = {}> {\n\tnew (props: P, context?: any): Component<P, S>;\n\tdisplayName?: string;\n\tcontextType?: Context<any>;\n\tgetDerivedStateFromProps?(\n\t\tprops: Readonly<P>,\n\t\tstate: Readonly<S>\n\t): Partial<S> | null;\n\tgetDerivedStateFromError?(error: any): Partial<S> | null;\n}\nexport interface ComponentConstructor<P = {}, S = {}>\n\textends ComponentClass<P, S> {}\n\n// Type alias for a component instance considered generally, whether stateless or stateful.\nexport type AnyComponent<P = {}, S = {}> =\n\t| FunctionComponent<P>\n\t| ComponentConstructor<P, S>;\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nexport interface Component<P = {}, S = {}> {\n\tcomponentWillMount?(): void;\n\tcomponentDidMount?(): void;\n\tcomponentWillUnmount?(): void;\n\tgetChildContext?(): object;\n\tcomponentWillReceiveProps?(nextProps: Readonly<P>, nextContext: any): void;\n\tshouldComponentUpdate?(\n\t\tnextProps: Readonly<P>,\n\t\tnextState: Readonly<S>,\n\t\tnextContext: any\n\t): boolean;\n\tcomponentWillUpdate?(\n\t\tnextProps: Readonly<P>,\n\t\tnextState: Readonly<S>,\n\t\tnextContext: any\n\t): void;\n\tgetSnapshotBeforeUpdate?(oldProps: Readonly<P>, oldState: Readonly<S>): any;\n\tcomponentDidUpdate?(\n\t\tpreviousProps: Readonly<P>,\n\t\tpreviousState: Readonly<S>,\n\t\tsnapshot: any\n\t): void;\n\tcomponentDidCatch?(error: any, errorInfo: ErrorInfo): void;\n}\n\nexport abstract class Component<P, S> {\n\tconstructor(props?: P, context?: any);\n\n\tstatic displayName?: string;\n\tstatic contextType?: Context<any>;\n\n\t// Static members cannot reference class type parameters. This is not\n\t// supported in TypeScript. Reusing the same type arguments from `Component`\n\t// will lead to an impossible state where one cannot satisfy the type\n\t// constraint under no circumstances, see #1356.In general type arguments\n\t// seem to be a bit buggy and not supported well at the time of this\n\t// writing with TS 3.3.3333.\n\tstatic getDerivedStateFromProps?(\n\t\tprops: Readonly<object>,\n\t\tstate: Readonly<object>\n\t): object | null;\n\tstatic getDerivedStateFromError?(error: any): object | null;\n\n\tstate: Readonly<S>;\n\tprops: RenderableProps<P>;\n\tcontext: any;\n\n\t// From https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e836acc75a78cf0655b5dfdbe81d69fdd4d8a252/types/react/index.d.ts#L402\n\t// // We MUST keep setState() as a unified signature because it allows proper checking of the method return type.\n\t// // See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257\n\tsetState<K extends keyof S>(\n\t\tstate:\n\t\t\t| ((\n\t\t\t\t\tprevState: Readonly<S>,\n\t\t\t\t\tprops: Readonly<P>\n\t\t\t  ) => Pick<S, K> | Partial<S> | null)\n\t\t\t| (Pick<S, K> | Partial<S> | null),\n\t\tcallback?: () => void\n\t): void;\n\n\tforceUpdate(callback?: () => void): void;\n\n\tabstract render(\n\t\tprops?: RenderableProps<P>,\n\t\tstate?: Readonly<S>,\n\t\tcontext?: any\n\t): ComponentChildren;\n}\n\n//\n// Preact createElement\n// -----------------------------------\n\nexport function createElement(\n\ttype: 'input',\n\tprops:\n\t\t| (DOMAttributes<HTMLInputElement> &\n\t\t\t\tClassAttributes<HTMLInputElement>)\n\t\t| null,\n\t...children: ComponentChildren[]\n): VNode<\n\tDOMAttributes<HTMLInputElement> &\n\t\tClassAttributes<HTMLInputElement>\n>;\nexport function createElement<\n\tP extends HTMLAttributes<T>,\n\tT extends HTMLElement\n>(\n\ttype: keyof JSXInternal.IntrinsicElements,\n\tprops: (ClassAttributes<T> & P) | null,\n\t...children: ComponentChildren[]\n): VNode<ClassAttributes<T> & P>;\nexport function createElement<\n\tP extends SVGAttributes<T>,\n\tT extends HTMLElement\n>(\n\ttype: keyof JSXInternal.IntrinsicSVGElements,\n\tprops: (ClassAttributes<T> & P) | null,\n\t...children: ComponentChildren[]\n): VNode<ClassAttributes<T> & P>;\nexport function createElement<T extends HTMLElement>(\n\ttype: string,\n\tprops:\n\t\t| (ClassAttributes<T> &\n\t\t\t\tHTMLAttributes &\n\t\t\t\tSVGAttributes)\n\t\t| null,\n\t...children: ComponentChildren[]\n): VNode<\n\tClassAttributes<T> & HTMLAttributes & SVGAttributes\n>;\nexport function createElement<P>(\n\ttype: ComponentType<P> | string,\n\tprops: (Attributes & P) | null,\n\t...children: ComponentChildren[]\n): VNode<P>;\nexport namespace createElement {\n\texport import JSX = JSXInternal;\n}\n\nexport function h(\n\ttype: 'input',\n\tprops:\n\t\t| (DOMAttributes<HTMLInputElement> &\n\t\t\t\tClassAttributes<HTMLInputElement>)\n\t\t| null,\n\t...children: ComponentChildren[]\n): VNode<\n\tDOMAttributes<HTMLInputElement> &\n\t\tClassAttributes<HTMLInputElement>\n>;\nexport function h<\n\tP extends HTMLAttributes<T>,\n\tT extends HTMLElement\n>(\n\ttype: keyof JSXInternal.IntrinsicElements,\n\tprops: (ClassAttributes<T> & P) | null,\n\t...children: ComponentChildren[]\n): VNode<ClassAttributes<T> & P>;\nexport function h<\n\tP extends SVGAttributes<T>,\n\tT extends HTMLElement\n>(\n\ttype: keyof JSXInternal.IntrinsicSVGElements,\n\tprops: (ClassAttributes<T> & P) | null,\n\t...children: ComponentChildren[]\n): VNode<ClassAttributes<T> & P>;\nexport function h<T extends HTMLElement>(\n\ttype: string,\n\tprops:\n\t\t| (ClassAttributes<T> &\n\t\t\t\tHTMLAttributes &\n\t\t\t\tSVGAttributes)\n\t\t| null,\n\t...children: ComponentChildren[]\n): VNode<\n\t| (ClassAttributes<T> &\n\t\t\tHTMLAttributes &\n\t\t\tSVGAttributes)\n\t| null\n>;\nexport function h<P>(\n\ttype: ComponentType<P> | string,\n\tprops: (Attributes & P) | null,\n\t...children: ComponentChildren[]\n): VNode<Attributes & P>;\nexport namespace h {\n\texport import JSX = JSXInternal;\n}\n\n//\n// Preact render\n// -----------------------------------\nexport interface ContainerNode {\n\treadonly nodeType: number;\n\treadonly parentNode: ContainerNode | null;\n\treadonly firstChild: ContainerNode | null;\n\treadonly childNodes: ArrayLike<ContainerNode>;\n\n\tinsertBefore(node: ContainerNode, child: ContainerNode | null): ContainerNode;\n\tappendChild(node: ContainerNode): ContainerNode;\n\tremoveChild(child: ContainerNode): ContainerNode;\n}\n\nexport function render(vnode: ComponentChild, parent: ContainerNode): void;\nexport function hydrate(vnode: ComponentChild, parent: ContainerNode): void;\nexport function cloneElement(\n\tvnode: VNode<any>,\n\tprops?: any,\n\t...children: ComponentChildren[]\n): VNode<any>;\nexport function cloneElement<P>(\n\tvnode: VNode<P>,\n\tprops?: any,\n\t...children: ComponentChildren[]\n): VNode<P>;\n\n//\n// Preact Built-in Components\n// -----------------------------------\n\n// TODO: Revisit what the public type of this is...\nexport const Fragment: FunctionComponent<{}>;\n\n//\n// Preact options\n// -----------------------------------\n\n/**\n * Global options for preact\n */\nexport interface Options {\n\t/** Attach a hook that is invoked whenever a VNode is created. */\n\tvnode?(vnode: VNode): void;\n\t/** Attach a hook that is invoked immediately before a vnode is unmounted. */\n\tunmount?(vnode: VNode): void;\n\t/** Attach a hook that is invoked after a vnode has rendered. */\n\tdiffed?(vnode: VNode): void;\n\tevent?(e: Event): any;\n\trequestAnimationFrame?(callback: () => void): void;\n\tdebounceRendering?(cb: () => void): void;\n\tuseDebugValue?(value: string | number): void;\n\t_addHookName?(name: string | number): void;\n\t__suspenseDidResolve?(vnode: VNode, cb: () => void): void;\n\t// __canSuspenseResolve?(vnode: VNode, cb: () => void): void;\n\n\t/**\n\t * Customize attribute serialization when a precompiled JSX transform\n\t * is used.\n\t */\n\tattr?(name: string, value: any): string | void;\n}\n\nexport const options: Options;\n\n//\n// Preact helpers\n// -----------------------------------\nexport function createRef<T = any>(): RefObject<T>;\nexport function toChildArray(\n\tchildren: ComponentChildren\n): Array<VNode | string | number>;\nexport function isValidElement(vnode: any): vnode is VNode;\n\n//\n// Context\n// -----------------------------------\nexport interface Consumer<T>\n\textends FunctionComponent<{\n\t\tchildren: (value: T) => ComponentChildren;\n\t}> {}\nexport interface PreactConsumer<T> extends Consumer<T> {}\n\nexport interface Provider<T>\n\textends FunctionComponent<{\n\t\tvalue: T;\n\t\tchildren?: ComponentChildren;\n\t}> {}\nexport interface PreactProvider<T> extends Provider<T> {}\nexport type ContextType<C extends Context<any>> = C extends Context<infer T>\n\t? T\n\t: never;\n\nexport interface Context<T> extends preact.Provider<T> {\n\tConsumer: preact.Consumer<T>;\n\tProvider: preact.Provider<T>;\n\tdisplayName?: string;\n}\n\nexport interface PreactContext<T> extends Context<T> {}\n\nexport function createContext<T>(defaultValue: T): Context<T>;\n"
  },
  {
    "path": "src/index.js",
    "content": "export { render, hydrate } from './render';\nexport {\n\tcreateElement,\n\tcreateElement as h,\n\tFragment,\n\tcreateRef,\n\tisValidElement\n} from './create-element';\nexport { BaseComponent as Component } from './component';\nexport { cloneElement } from './clone-element';\nexport { createContext } from './create-context';\nexport { toChildArray } from './diff/children';\nexport { default as options } from './options';\n"
  },
  {
    "path": "src/internal.d.ts",
    "content": "import * as preact from './index';\n\nexport enum HookType {\n\tuseState = 1,\n\tuseReducer = 2,\n\tuseEffect = 3,\n\tuseLayoutEffect = 4,\n\tuseRef = 5,\n\tuseImperativeHandle = 6,\n\tuseMemo = 7,\n\tuseCallback = 8,\n\tuseContext = 9,\n\tuseErrorBoundary = 10,\n\t// Not a real hook, but the devtools treat is as such\n\tuseDebugvalue = 11\n}\n\nexport interface DevSource {\n\tfileName: string;\n\tlineNumber: number;\n}\n\nexport interface ErrorInfo {\n\tcomponentStack?: string;\n}\n\nexport interface Options extends preact.Options {\n\t/** Attach a hook that is invoked before render, mainly to check the arguments. */\n\t_root?(vnode: ComponentChild, parent: preact.ContainerNode): void;\n\t/** Attach a hook that is invoked before a vnode is diffed. */\n\t_diff?(vnode: VNode): void;\n\t/** Attach a hook that is invoked after a tree was mounted or was updated. */\n\t_commit?(vnode: VNode, commitQueue: Component[]): void;\n\t/** Attach a hook that is invoked before a vnode has rendered. */\n\t_render?(vnode: VNode): void;\n\t/** Attach a hook that is invoked before a hook's state is queried. */\n\t_hook?(component: Component, index: number, type: HookType): void;\n\t/** Bypass effect execution. Currenty only used in devtools for hooks inspection */\n\t_skipEffects?: boolean;\n\t/** Attach a hook that is invoked after an error is caught in a component but before calling lifecycle hooks */\n\t_catchError(\n\t\terror: any,\n\t\tvnode: VNode,\n\t\toldVNode?: VNode | undefined,\n\t\terrorInfo?: ErrorInfo | undefined\n\t): void;\n\t/** Attach a hook that fires when hydration can't find a proper DOM-node to match with */\n\t_hydrationMismatch?(\n\t\tvnode: VNode,\n\t\texcessDomChildren: Array<PreactElement | null>\n\t): void;\n}\n\nexport type ComponentChild =\n\t| VNode<any>\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| undefined;\nexport type ComponentChildren = ComponentChild[] | ComponentChild;\n\nexport interface FunctionComponent<P = {}> extends preact.FunctionComponent<P> {\n\t// Internally, createContext uses `contextType` on a Function component to\n\t// implement the Consumer component\n\tcontextType?: PreactContext;\n\n\t// Internally, createContext stores a ref to the context object on the Provider\n\t// Function component to help devtools\n\t_contextRef?: PreactContext;\n\n\t// Define these properties as undefined on FunctionComponent to get rid of\n\t// some errors in `diff()`\n\tgetDerivedStateFromProps?: undefined;\n\tgetDerivedStateFromError?: undefined;\n}\n\nexport interface ComponentClass<P = {}> extends preact.ComponentClass<P> {\n\t_contextRef?: any;\n\n\t// Override public contextType with internal PreactContext type\n\tcontextType?: PreactContext;\n}\n\n// Redefine ComponentType using our new internal FunctionComponent interface above\nexport type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>;\n\nexport interface PreactElement extends preact.ContainerNode {\n\t// Namespace detection\n\treadonly namespaceURI?: string;\n\t// Property used to update Text nodes\n\tdata?: CharacterData['data'];\n\t// Property to set __dangerouslySetInnerHTML\n\tinnerHTML?: Element['innerHTML'];\n\tremove?: Element['remove'];\n\n\t// Attribute reading and setting\n\treadonly attributes?: Element['attributes'];\n\tsetAttribute?: Element['setAttribute'];\n\tremoveAttribute?: Element['removeAttribute'];\n\n\t// Event listeners\n\taddEventListener?: Element['addEventListener'];\n\tremoveEventListener?: Element['removeEventListener'];\n\n\t// Used to match DOM nodes to VNodes during hydration\n\treadonly ownerDocument: Document;\n\n\t// Setting styles\n\treadonly style?: CSSStyleDeclaration;\n\n\t// nextSibling required for inserting nodes\n\treadonly nextSibling: PreactElement | null;\n\n\t// Used to match DOM nodes to VNodes during hydration. Note: doesn't exist\n\t// on Text nodes\n\treadonly localName?: string;\n\n\t// Input handling\n\tvalue?: HTMLInputElement['value'];\n\tchecked?: HTMLInputElement['checked'];\n\n\t// Internal properties\n\t_children?: VNode<any> | null;\n\t/** Event listeners to support event delegation */\n\t_listeners?: Record<string, (e: Event) => void>;\n}\n\nexport interface PreactEvent extends Event {\n\t_dispatched?: number;\n}\n\n// We use the `current` property to differentiate between the two kinds of Refs so\n// internally we'll define `current` on both to make TypeScript happy\ntype RefObject<T> = { current: T | null };\ntype RefCallback<T> = {\n\t(instance: T | null): void | (() => void);\n\tcurrent: undefined;\n};\nexport type Ref<T> = RefObject<T> | RefCallback<T>;\n\nexport interface VNode<P = {}> extends preact.VNode<P> {\n\ttype: string | ComponentType<P>;\n\tprops: P & { children: ComponentChildren };\n\tref?: Ref<any> | null;\n\t_children: Array<VNode<any>> | null;\n\t_parent: VNode | null;\n\t_depth: number | null;\n\t/**\n\t * The [first (for Fragments)] DOM child of a VNode\n\t */\n\t_dom: PreactElement | null;\n\t_component: Component | null;\n\tconstructor: undefined;\n\t_original: number;\n\t_index: number;\n\t_flags: number;\n}\n\nexport interface Component<P = {}, S = {}>\n\textends Omit<preact.Component<P, S>, 'base'> {\n\t// When component is functional component, this is reset to functional component\n\tconstructor: ComponentType<P>;\n\tstate: S; // Override Component[\"state\"] to not be readonly for internal use, specifically Hooks\n\n\t_excess?: PreactElement[];\n\t_renderCallbacks: Array<() => void>; // Only class components\n\t_stateCallbacks: Array<() => void>; // Only class components\n\t_globalContext?: any;\n\t_vnode?: VNode<P> | null;\n\t_nextState?: S | null; // Only class components\n\t/** Only used in the devtools to later dirty check if state has changed */\n\t_prevState?: S | null;\n\t/**\n\t * Pointer to the parent dom node. This is only needed for top-level Fragment\n\t * components or array returns.\n\t */\n\t_parentDom?: PreactElement | null;\n\t_bits: number;\n}\n\nexport interface PreactContext extends preact.Context<any> {\n\t_id: string;\n\t_defaultValue: any;\n}\n"
  },
  {
    "path": "src/jsx.d.ts",
    "content": "// Users who only use Preact for SSR might not specify \"dom\" in their lib in tsconfig.json\n/// <reference lib=\"dom\" />\n\nimport * as preact from './index';\n\ntype Defaultize<Props, Defaults> =\n\t// Distribute over unions\n\tProps extends any // Make any properties included in Default optional\n\t\t? Partial<Pick<Props, Extract<keyof Props, keyof Defaults>>> & // Include the remaining properties from Props\n\t\t\t\tPick<Props, Exclude<keyof Props, keyof Defaults>>\n\t\t: never;\n\nexport namespace JSXInternal {\n\texport type LibraryManagedAttributes<Component, Props> = Component extends {\n\t\tdefaultProps: infer Defaults;\n\t}\n\t\t? Defaultize<Props, Defaults>\n\t\t: Props;\n\n\texport interface IntrinsicAttributes {\n\t\tkey?: any;\n\t}\n\n\texport type ElementType<P = any> =\n\t\t| {\n\t\t\t\t[K in keyof IntrinsicElements]: P extends IntrinsicElements[K]\n\t\t\t\t\t? K\n\t\t\t\t\t: never;\n\t\t  }[keyof IntrinsicElements]\n\t\t| preact.ComponentType<P>;\n\texport interface Element extends preact.VNode<any> {}\n\texport type ElementClass =\n\t\t| preact.Component<any, any>\n\t\t| preact.FunctionComponent<any>;\n\n\texport interface ElementAttributesProperty {\n\t\tprops: any;\n\t}\n\n\texport interface ElementChildrenAttribute {\n\t\tchildren: any;\n\t}\n\n\texport interface IntrinsicSVGElements {\n\t\tsvg: preact.SVGAttributes<SVGSVGElement>;\n\t\tanimate: preact.SVGAttributes<SVGAnimateElement>;\n\t\tcircle: preact.SVGAttributes<SVGCircleElement>;\n\t\tanimateMotion: preact.SVGAttributes<SVGAnimateMotionElement>;\n\t\tanimateTransform: preact.SVGAttributes<SVGAnimateTransformElement>;\n\t\tclipPath: preact.SVGAttributes<SVGClipPathElement>;\n\t\tdefs: preact.SVGAttributes<SVGDefsElement>;\n\t\tdesc: preact.SVGAttributes<SVGDescElement>;\n\t\tellipse: preact.SVGAttributes<SVGEllipseElement>;\n\t\tfeBlend: preact.SVGAttributes<SVGFEBlendElement>;\n\t\tfeColorMatrix: preact.SVGAttributes<SVGFEColorMatrixElement>;\n\t\tfeComponentTransfer: preact.SVGAttributes<SVGFEComponentTransferElement>;\n\t\tfeComposite: preact.SVGAttributes<SVGFECompositeElement>;\n\t\tfeConvolveMatrix: preact.SVGAttributes<SVGFEConvolveMatrixElement>;\n\t\tfeDiffuseLighting: preact.SVGAttributes<SVGFEDiffuseLightingElement>;\n\t\tfeDisplacementMap: preact.SVGAttributes<SVGFEDisplacementMapElement>;\n\t\tfeDistantLight: preact.SVGAttributes<SVGFEDistantLightElement>;\n\t\tfeDropShadow: preact.SVGAttributes<SVGFEDropShadowElement>;\n\t\tfeFlood: preact.SVGAttributes<SVGFEFloodElement>;\n\t\tfeFuncA: preact.SVGAttributes<SVGFEFuncAElement>;\n\t\tfeFuncB: preact.SVGAttributes<SVGFEFuncBElement>;\n\t\tfeFuncG: preact.SVGAttributes<SVGFEFuncGElement>;\n\t\tfeFuncR: preact.SVGAttributes<SVGFEFuncRElement>;\n\t\tfeGaussianBlur: preact.SVGAttributes<SVGFEGaussianBlurElement>;\n\t\tfeImage: preact.SVGAttributes<SVGFEImageElement>;\n\t\tfeMerge: preact.SVGAttributes<SVGFEMergeElement>;\n\t\tfeMergeNode: preact.SVGAttributes<SVGFEMergeNodeElement>;\n\t\tfeMorphology: preact.SVGAttributes<SVGFEMorphologyElement>;\n\t\tfeOffset: preact.SVGAttributes<SVGFEOffsetElement>;\n\t\tfePointLight: preact.SVGAttributes<SVGFEPointLightElement>;\n\t\tfeSpecularLighting: preact.SVGAttributes<SVGFESpecularLightingElement>;\n\t\tfeSpotLight: preact.SVGAttributes<SVGFESpotLightElement>;\n\t\tfeTile: preact.SVGAttributes<SVGFETileElement>;\n\t\tfeTurbulence: preact.SVGAttributes<SVGFETurbulenceElement>;\n\t\tfilter: preact.SVGAttributes<SVGFilterElement>;\n\t\tforeignObject: preact.SVGAttributes<SVGForeignObjectElement>;\n\t\tg: preact.SVGAttributes<SVGGElement>;\n\t\timage: preact.SVGAttributes<SVGImageElement>;\n\t\tline: preact.SVGAttributes<SVGLineElement>;\n\t\tlinearGradient: preact.SVGAttributes<SVGLinearGradientElement>;\n\t\tmarker: preact.SVGAttributes<SVGMarkerElement>;\n\t\tmask: preact.SVGAttributes<SVGMaskElement>;\n\t\tmetadata: preact.SVGAttributes<SVGMetadataElement>;\n\t\tmpath: preact.SVGAttributes<SVGMPathElement>;\n\t\tpath: preact.SVGAttributes<SVGPathElement>;\n\t\tpattern: preact.SVGAttributes<SVGPatternElement>;\n\t\tpolygon: preact.SVGAttributes<SVGPolygonElement>;\n\t\tpolyline: preact.SVGAttributes<SVGPolylineElement>;\n\t\tradialGradient: preact.SVGAttributes<SVGRadialGradientElement>;\n\t\trect: preact.SVGAttributes<SVGRectElement>;\n\t\tset: preact.SVGAttributes<SVGSetElement>;\n\t\tstop: preact.SVGAttributes<SVGStopElement>;\n\t\tswitch: preact.SVGAttributes<SVGSwitchElement>;\n\t\tsymbol: preact.SVGAttributes<SVGSymbolElement>;\n\t\ttext: preact.SVGAttributes<SVGTextElement>;\n\t\ttextPath: preact.SVGAttributes<SVGTextPathElement>;\n\t\ttspan: preact.SVGAttributes<SVGTSpanElement>;\n\t\tuse: preact.SVGAttributes<SVGUseElement>;\n\t\tview: preact.SVGAttributes<SVGViewElement>;\n\t}\n\n\texport interface IntrinsicMathMLElements {\n\t\tannotation: preact.AnnotationMathMLAttributes<MathMLElement>;\n\t\t'annotation-xml': preact.AnnotationXmlMathMLAttributes<MathMLElement>;\n\t\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction */\n\t\tmaction: preact.MActionMathMLAttributes<MathMLElement>;\n\t\tmath: preact.MathMathMLAttributes<MathMLElement>;\n\t\t/** This feature is non-standard. See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/menclose  */\n\t\tmenclose: preact.MEncloseMathMLAttributes<MathMLElement>;\n\t\tmerror: preact.MErrorMathMLAttributes<MathMLElement>;\n\t\t/** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfenced */\n\t\tmfenced: preact.MFencedMathMLAttributes<MathMLElement>;\n\t\tmfrac: preact.MFracMathMLAttributes<MathMLElement>;\n\t\tmi: preact.MiMathMLAttributes<MathMLElement>;\n\t\tmmultiscripts: preact.MmultiScriptsMathMLAttributes<MathMLElement>;\n\t\tmn: preact.MNMathMLAttributes<MathMLElement>;\n\t\tmo: preact.MOMathMLAttributes<MathMLElement>;\n\t\tmover: preact.MOverMathMLAttributes<MathMLElement>;\n\t\tmpadded: preact.MPaddedMathMLAttributes<MathMLElement>;\n\t\tmphantom: preact.MPhantomMathMLAttributes<MathMLElement>;\n\t\tmprescripts: preact.MPrescriptsMathMLAttributes<MathMLElement>;\n\t\tmroot: preact.MRootMathMLAttributes<MathMLElement>;\n\t\tmrow: preact.MRowMathMLAttributes<MathMLElement>;\n\t\tms: preact.MSMathMLAttributes<MathMLElement>;\n\t\tmspace: preact.MSpaceMathMLAttributes<MathMLElement>;\n\t\tmsqrt: preact.MSqrtMathMLAttributes<MathMLElement>;\n\t\tmstyle: preact.MStyleMathMLAttributes<MathMLElement>;\n\t\tmsub: preact.MSubMathMLAttributes<MathMLElement>;\n\t\tmsubsup: preact.MSubsupMathMLAttributes<MathMLElement>;\n\t\tmsup: preact.MSupMathMLAttributes<MathMLElement>;\n\t\tmtable: preact.MTableMathMLAttributes<MathMLElement>;\n\t\tmtd: preact.MTdMathMLAttributes<MathMLElement>;\n\t\tmtext: preact.MTextMathMLAttributes<MathMLElement>;\n\t\tmtr: preact.MTrMathMLAttributes<MathMLElement>;\n\t\tmunder: preact.MUnderMathMLAttributes<MathMLElement>;\n\t\tmunderover: preact.MUnderMathMLAttributes<MathMLElement>;\n\t\tsemantics: preact.SemanticsMathMLAttributes<MathMLElement>;\n\t}\n\n\texport interface IntrinsicHTMLElements {\n\t\ta: preact.AccessibleAnchorHTMLAttributes<HTMLAnchorElement>;\n\t\tabbr: preact.HTMLAttributes<HTMLElement>;\n\t\taddress: preact.HTMLAttributes<HTMLElement>;\n\t\tarea: preact.AccessibleAreaHTMLAttributes<HTMLAreaElement>;\n\t\tarticle: preact.ArticleHTMLAttributes<HTMLElement>;\n\t\taside: preact.AsideHTMLAttributes<HTMLElement>;\n\t\taudio: preact.AudioHTMLAttributes<HTMLAudioElement>;\n\t\tb: preact.HTMLAttributes<HTMLElement>;\n\t\tbase: preact.BaseHTMLAttributes<HTMLBaseElement>;\n\t\tbdi: preact.HTMLAttributes<HTMLElement>;\n\t\tbdo: preact.HTMLAttributes<HTMLElement>;\n\t\tbig: preact.HTMLAttributes<HTMLElement>;\n\t\tblockquote: preact.BlockquoteHTMLAttributes<HTMLQuoteElement>;\n\t\tbody: preact.HTMLAttributes<HTMLBodyElement>;\n\t\tbr: preact.BrHTMLAttributes<HTMLBRElement>;\n\t\tbutton: preact.ButtonHTMLAttributes<HTMLButtonElement>;\n\t\tcanvas: preact.CanvasHTMLAttributes<HTMLCanvasElement>;\n\t\tcaption: preact.CaptionHTMLAttributes<HTMLTableCaptionElement>;\n\t\tcite: preact.HTMLAttributes<HTMLElement>;\n\t\tcode: preact.HTMLAttributes<HTMLElement>;\n\t\tcol: preact.ColHTMLAttributes<HTMLTableColElement>;\n\t\tcolgroup: preact.ColgroupHTMLAttributes<HTMLTableColElement>;\n\t\tdata: preact.DataHTMLAttributes<HTMLDataElement>;\n\t\tdatalist: preact.DataListHTMLAttributes<HTMLDataListElement>;\n\t\tdd: preact.DdHTMLAttributes<HTMLElement>;\n\t\tdel: preact.DelHTMLAttributes<HTMLModElement>;\n\t\tdetails: preact.DetailsHTMLAttributes<HTMLDetailsElement>;\n\t\tdfn: preact.HTMLAttributes<HTMLElement>;\n\t\tdialog: preact.DialogHTMLAttributes<HTMLDialogElement>;\n\t\tdiv: preact.HTMLAttributes<HTMLDivElement>;\n\t\tdl: preact.DlHTMLAttributes<HTMLDListElement>;\n\t\tdt: preact.DtHTMLAttributes<HTMLElement>;\n\t\tem: preact.HTMLAttributes<HTMLElement>;\n\t\tembed: preact.EmbedHTMLAttributes<HTMLEmbedElement>;\n\t\tfieldset: preact.FieldsetHTMLAttributes<HTMLFieldSetElement>;\n\t\tfigcaption: preact.FigcaptionHTMLAttributes<HTMLElement>;\n\t\tfigure: preact.HTMLAttributes<HTMLElement>;\n\t\tfooter: preact.FooterHTMLAttributes<HTMLElement>;\n\t\tform: preact.FormHTMLAttributes<HTMLFormElement>;\n\t\th1: preact.HeadingHTMLAttributes<HTMLHeadingElement>;\n\t\th2: preact.HeadingHTMLAttributes<HTMLHeadingElement>;\n\t\th3: preact.HeadingHTMLAttributes<HTMLHeadingElement>;\n\t\th4: preact.HeadingHTMLAttributes<HTMLHeadingElement>;\n\t\th5: preact.HeadingHTMLAttributes<HTMLHeadingElement>;\n\t\th6: preact.HeadingHTMLAttributes<HTMLHeadingElement>;\n\t\thead: preact.HeadHTMLAttributes<HTMLHeadElement>;\n\t\theader: preact.HeaderHTMLAttributes<HTMLElement>;\n\t\thgroup: preact.HTMLAttributes<HTMLElement>;\n\t\thr: preact.HrHTMLAttributes<HTMLHRElement>;\n\t\thtml: preact.HtmlHTMLAttributes<HTMLHtmlElement>;\n\t\ti: preact.HTMLAttributes<HTMLElement>;\n\t\tiframe: preact.IframeHTMLAttributes<HTMLIFrameElement>;\n\t\timg: preact.AccessibleImgHTMLAttributes<HTMLImageElement>;\n\t\tinput: preact.AccessibleInputHTMLAttributes<HTMLInputElement>;\n\t\tins: preact.InsHTMLAttributes<HTMLModElement>;\n\t\tkbd: preact.HTMLAttributes<HTMLElement>;\n\t\tkeygen: preact.KeygenHTMLAttributes<HTMLUnknownElement>;\n\t\tlabel: preact.LabelHTMLAttributes<HTMLLabelElement>;\n\t\tlegend: preact.LegendHTMLAttributes<HTMLLegendElement>;\n\t\tli: preact.LiHTMLAttributes<HTMLLIElement>;\n\t\tlink: preact.LinkHTMLAttributes<HTMLLinkElement>;\n\t\tmain: preact.MainHTMLAttributes<HTMLElement>;\n\t\tmap: preact.MapHTMLAttributes<HTMLMapElement>;\n\t\tmark: preact.HTMLAttributes<HTMLElement>;\n\t\tmarquee: preact.MarqueeHTMLAttributes<HTMLMarqueeElement>;\n\t\tmenu: preact.MenuHTMLAttributes<HTMLMenuElement>;\n\t\tmenuitem: preact.HTMLAttributes<HTMLUnknownElement>;\n\t\tmeta: preact.MetaHTMLAttributes<HTMLMetaElement>;\n\t\tmeter: preact.MeterHTMLAttributes<HTMLMeterElement>;\n\t\tnav: preact.NavHTMLAttributes<HTMLElement>;\n\t\tnoscript: preact.NoScriptHTMLAttributes<HTMLElement>;\n\t\tobject: preact.ObjectHTMLAttributes<HTMLObjectElement>;\n\t\tol: preact.OlHTMLAttributes<HTMLOListElement>;\n\t\toptgroup: preact.OptgroupHTMLAttributes<HTMLOptGroupElement>;\n\t\toption: preact.OptionHTMLAttributes<HTMLOptionElement>;\n\t\toutput: preact.OutputHTMLAttributes<HTMLOutputElement>;\n\t\tp: preact.HTMLAttributes<HTMLParagraphElement>;\n\t\tparam: preact.ParamHTMLAttributes<HTMLParamElement>;\n\t\tpicture: preact.PictureHTMLAttributes<HTMLPictureElement>;\n\t\tpre: preact.HTMLAttributes<HTMLPreElement>;\n\t\tprogress: preact.ProgressHTMLAttributes<HTMLProgressElement>;\n\t\tq: preact.QuoteHTMLAttributes<HTMLQuoteElement>;\n\t\trp: preact.HTMLAttributes<HTMLElement>;\n\t\trt: preact.HTMLAttributes<HTMLElement>;\n\t\truby: preact.HTMLAttributes<HTMLElement>;\n\t\ts: preact.HTMLAttributes<HTMLElement>;\n\t\tsamp: preact.HTMLAttributes<HTMLElement>;\n\t\tscript: preact.ScriptHTMLAttributes<HTMLScriptElement>;\n\t\tsearch: preact.SearchHTMLAttributes<HTMLElement>;\n\t\tsection: preact.HTMLAttributes<HTMLElement>;\n\t\tselect: preact.AccessibleSelectHTMLAttributes<HTMLSelectElement>;\n\t\tslot: preact.SlotHTMLAttributes<HTMLSlotElement>;\n\t\tsmall: preact.HTMLAttributes<HTMLElement>;\n\t\tsource: preact.SourceHTMLAttributes<HTMLSourceElement>;\n\t\tspan: preact.HTMLAttributes<HTMLSpanElement>;\n\t\tstrong: preact.HTMLAttributes<HTMLElement>;\n\t\tstyle: preact.StyleHTMLAttributes<HTMLStyleElement>;\n\t\tsub: preact.HTMLAttributes<HTMLElement>;\n\t\tsummary: preact.HTMLAttributes<HTMLElement>;\n\t\tsup: preact.HTMLAttributes<HTMLElement>;\n\t\ttable: preact.TableHTMLAttributes<HTMLTableElement>;\n\t\ttbody: preact.HTMLAttributes<HTMLTableSectionElement>;\n\t\ttd: preact.TdHTMLAttributes<HTMLTableCellElement>;\n\t\ttemplate: preact.TemplateHTMLAttributes<HTMLTemplateElement>;\n\t\ttextarea: preact.TextareaHTMLAttributes<HTMLTextAreaElement>;\n\t\ttfoot: preact.HTMLAttributes<HTMLTableSectionElement>;\n\t\tth: preact.ThHTMLAttributes<HTMLTableCellElement>;\n\t\tthead: preact.HTMLAttributes<HTMLTableSectionElement>;\n\t\ttime: preact.TimeHTMLAttributes<HTMLTimeElement>;\n\t\ttitle: preact.TitleHTMLAttributes<HTMLTitleElement>;\n\t\ttr: preact.HTMLAttributes<HTMLTableRowElement>;\n\t\ttrack: preact.TrackHTMLAttributes<HTMLTrackElement>;\n\t\tu: preact.UlHTMLAttributes<HTMLElement>;\n\t\tul: preact.HTMLAttributes<HTMLUListElement>;\n\t\tvar: preact.HTMLAttributes<HTMLElement>;\n\t\tvideo: preact.VideoHTMLAttributes<HTMLVideoElement>;\n\t\twbr: preact.WbrHTMLAttributes<HTMLElement>;\n\t}\n\n\texport interface IntrinsicElements\n\t\textends IntrinsicSVGElements,\n\t\t\tIntrinsicMathMLElements,\n\t\t\tIntrinsicHTMLElements {}\n}\n"
  },
  {
    "path": "src/options.js",
    "content": "import { _catchError } from './diff/catch-error';\n\n/**\n * The `option` object can potentially contain callback functions\n * that are called during various stages of our renderer. This is the\n * foundation on which all our addons like `preact/debug`, `preact/compat`,\n * and `preact/hooks` are based on. See the `Options` type in `internal.d.ts`\n * for a full list of available option hooks (most editors/IDEs allow you to\n * ctrl+click or cmd+click on mac the type definition below).\n * @type {import('./internal').Options}\n */\nconst options = {\n\t_catchError\n};\n\nexport default options;\n"
  },
  {
    "path": "src/render.js",
    "content": "import { EMPTY_OBJ, MODE_HYDRATE, NULL } from './constants';\nimport { commitRoot, diff } from './diff/index';\nimport { createElement, Fragment } from './create-element';\nimport options from './options';\nimport { slice } from './util';\n\n/**\n * Render a Preact virtual node into a DOM element\n * @param {import('./internal').ComponentChild} vnode The virtual node to render\n * @param {import('./internal').PreactElement} parentDom The DOM element to render into\n */\nexport function render(vnode, parentDom) {\n\t// https://github.com/preactjs/preact/issues/3794\n\tif (parentDom == document) {\n\t\tparentDom = document.documentElement;\n\t}\n\n\tif (options._root) options._root(vnode, parentDom);\n\n\t// @ts-expect-error\n\tlet isHydrating = vnode && vnode._flags & MODE_HYDRATE;\n\n\t// To be able to support calling `render()` multiple times on the same\n\t// DOM node, we need to obtain a reference to the previous tree. We do\n\t// this by assigning a new `_children` property to DOM nodes which points\n\t// to the last rendered tree. By default this property is not present, which\n\t// means that we are mounting a new tree for the first time.\n\tlet oldVNode = isHydrating ? NULL : parentDom._children;\n\n\tparentDom._children = createElement(Fragment, NULL, [vnode]);\n\n\t// List of effects that need to be called after diffing.\n\tlet commitQueue = [],\n\t\trefQueue = [];\n\n\tdiff(\n\t\tparentDom,\n\t\t// Determine the new vnode tree and store it on the DOM element on\n\t\t// our custom `_children` property.\n\t\tparentDom._children,\n\t\toldVNode || EMPTY_OBJ,\n\t\tEMPTY_OBJ,\n\t\tparentDom.namespaceURI,\n\t\toldVNode\n\t\t\t? NULL\n\t\t\t: parentDom.firstChild\n\t\t\t\t? slice.call(parentDom.childNodes)\n\t\t\t\t: NULL,\n\t\tcommitQueue,\n\t\toldVNode ? oldVNode._dom : parentDom.firstChild,\n\t\t// @ts-expect-error we are doing a bit-wise operation so it's either 0 or true\n\t\tisHydrating,\n\t\trefQueue,\n\t\tparentDom.ownerDocument\n\t);\n\n\t// Flush all queued effects\n\tcommitRoot(commitQueue, parentDom._children, refQueue);\n}\n\n/**\n * Update an existing DOM element with data from a Preact virtual node\n * @param {import('./internal').ComponentChild} vnode The virtual node to render\n * @param {import('./internal').PreactElement} parentDom The DOM element to update\n */\nexport function hydrate(vnode, parentDom) {\n\t// @ts-expect-error\n\tvnode._flags |= MODE_HYDRATE;\n\trender(vnode, parentDom);\n}\n"
  },
  {
    "path": "src/util.js",
    "content": "import { EMPTY_ARR } from './constants';\n\nexport const isArray = Array.isArray;\nexport const slice = EMPTY_ARR.slice;\nexport const assign = Object.assign;\n\n/**\n * Remove a child node from its parent if attached.\n * @param {import('./internal').PreactElement | null} node The node to remove\n */\nexport function removeNode(node) {\n\tif (node && node.parentNode) node.remove();\n}\n"
  },
  {
    "path": "test/_util/dom.js",
    "content": "/**\n * Serialize contents\n * @typedef {string | number | Array<string | number>} Contents\n * @param {Contents} contents\n */\nconst serialize = contents =>\n\tArray.isArray(contents) ? contents.join('') : contents.toString();\n\n/**\n * A helper to generate innerHTML validation strings containing spans\n * @param {Contents} contents The contents of the span, as a string\n */\nexport const span = contents => `<span>${serialize(contents)}</span>`;\n\n/**\n * A helper to generate innerHTML validation strings containing divs\n * @param {Contents} contents The contents of the div, as a string\n */\nexport const div = contents => `<div>${serialize(contents)}</div>`;\n\n/**\n * A helper to generate innerHTML validation strings containing p\n * @param {Contents} contents The contents of the p, as a string\n */\nexport const p = contents => `<p>${serialize(contents)}</p>`;\n\n/**\n * A helper to generate innerHTML validation strings containing sections\n * @param {Contents} contents The contents of the section, as a string\n */\nexport const section = contents => `<section>${serialize(contents)}</section>`;\n\n/**\n * A helper to generate innerHTML validation strings containing uls\n * @param {Contents} contents The contents of the ul, as a string\n */\nexport const ul = contents => `<ul>${serialize(contents)}</ul>`;\n\n/**\n * A helper to generate innerHTML validation strings containing ols\n * @param {Contents} contents The contents of the ol, as a string\n */\nexport const ol = contents => `<ol>${serialize(contents)}</ol>`;\n\n/**\n * A helper to generate innerHTML validation strings containing lis\n * @param {Contents} contents The contents of the li, as a string\n */\nexport const li = contents => `<li>${serialize(contents)}</li>`;\n\n/**\n * A helper to generate innerHTML validation strings containing inputs\n */\nexport const input = () => `<input type=\"text\">`;\n\n/**\n * A helper to generate innerHTML validation strings containing h1\n * @param {Contents} contents The contents of the h1\n */\nexport const h1 = contents => `<h1>${serialize(contents)}</h1>`;\n\n/**\n * A helper to generate innerHTML validation strings containing h2\n * @param {Contents} contents The contents of the h2\n */\nexport const h2 = contents => `<h2>${serialize(contents)}</h2>`;\n"
  },
  {
    "path": "test/_util/helpers.jsx",
    "content": "import { createElement, options } from 'preact';\nimport { clearLog, getLog } from './logCall';\nimport { teardown as testUtilTeardown } from 'preact/test-utils';\nimport { vi } from 'vitest';\n\n/** @jsx createElement */\n\n/**\n * Assign properties from `props` to `obj`\n * @template O, P The obj and props types\n * @param {O} obj The object to copy properties to\n * @param {P} props The object to copy properties from\n * @returns {O & P}\n */\nfunction assign(obj, props) {\n\tfor (let i in props) obj[i] = props[i];\n\treturn /** @type {O & P} */ (obj);\n}\n\nexport function supportsPassiveEvents() {\n\tlet supported = false;\n\ttry {\n\t\tlet options = {\n\t\t\tget passive() {\n\t\t\t\tsupported = true;\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t};\n\n\t\twindow.addEventListener('test', options, options);\n\t\twindow.removeEventListener('test', options, options);\n\t} catch (err) {\n\t\tsupported = false;\n\t}\n\treturn supported;\n}\n\nexport function supportsDataList() {\n\treturn (\n\t\t'list' in document.createElement('input') &&\n\t\tBoolean(\n\t\t\tdocument.createElement('datalist') && 'HTMLDataListElement' in window\n\t\t)\n\t);\n}\n\nconst VOID_ELEMENTS =\n\t/^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/;\n\nfunction encodeEntities(str) {\n\treturn str.replace(/&/g, '&amp;');\n}\n\n/**\n * Normalize svg paths spacing. Some browsers insert spaces around letters,\n * others do not.\n * @param {string} str\n * @returns {string}\n */\nfunction normalizePath(str) {\n\tlet len = str.length;\n\tlet out = '';\n\tfor (let i = 0; i < len; i++) {\n\t\tconst char = str[i];\n\t\tif (/[A-Za-z]/.test(char)) {\n\t\t\tif (i == 0) out += char + ' ';\n\t\t\telse\n\t\t\t\tout += (str[i - 1] == ' ' ? '' : ' ') + char + (i < len - 1 ? ' ' : '');\n\t\t} else if (char == '-' && str[i - 1] !== ' ') out += ' ' + char;\n\t\telse out += char;\n\t}\n\n\treturn out.replace(/\\s\\s+/g, ' ').replace(/z/g, 'Z');\n}\n\nexport function serializeHtml(node) {\n\tlet str = '';\n\tlet child = node.firstChild;\n\twhile (child) {\n\t\tstr += serializeDomTree(child);\n\t\tchild = child.nextSibling;\n\t}\n\treturn str;\n}\n\n/**\n * Serialize a DOM tree.\n * Uses deterministic sorting where necessary to ensure consistent tests.\n * @param {Element|Node} node\tThe root node to serialize\n * @returns {string} html\n */\nfunction serializeDomTree(node) {\n\tif (node.nodeType === 3) {\n\t\treturn encodeEntities(node.data);\n\t} else if (node.nodeType === 8) {\n\t\treturn '<!--' + encodeEntities(node.data) + '-->';\n\t} else if (node.nodeType === 1 || node.nodeType === 9) {\n\t\tlet str = '<' + node.localName;\n\t\tconst attrs = [];\n\t\tfor (let i = 0; i < node.attributes.length; i++) {\n\t\t\tattrs.push(node.attributes[i].name);\n\t\t}\n\t\tattrs.sort();\n\t\tfor (let i = 0; i < attrs.length; i++) {\n\t\t\tconst name = attrs[i];\n\t\t\tlet value = node.getAttribute(name);\n\n\t\t\t// don't render attributes with null or undefined values\n\t\t\tif (value == null) continue;\n\n\t\t\t// normalize empty class attribute\n\t\t\tif (!value && name === 'class') continue;\n\n\t\t\tstr += ' ' + name;\n\t\t\tvalue = encodeEntities(value);\n\n\t\t\t// normalize svg <path d=\"value\">\n\t\t\tif (node.localName === 'path' && name === 'd') {\n\t\t\t\tvalue = normalizePath(value);\n\t\t\t}\n\t\t\tstr += '=\"' + value + '\"';\n\t\t}\n\t\tstr += '>';\n\n\t\t// For elements that don't have children (e.g. <wbr />) don't descend.\n\t\tif (!VOID_ELEMENTS.test(node.localName)) {\n\t\t\t// IE puts the value of a textarea as its children while other browsers don't.\n\t\t\t// Normalize those differences by forcing textarea to not have children.\n\t\t\tif (node.localName != 'textarea') {\n\t\t\t\tlet child = node.firstChild;\n\t\t\t\twhile (child) {\n\t\t\t\t\tstr += serializeDomTree(child);\n\t\t\t\t\tchild = child.nextSibling;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstr += '</' + node.localName + '>';\n\t\t}\n\t\treturn str;\n\t}\n}\n\n/**\n * Normalize event creation in browsers\n * @param {string} name\n * @returns {Event}\n */\nexport function createEvent(name) {\n\t// Modern browsers\n\tif (typeof Event == 'function') {\n\t\treturn new Event(name);\n\t}\n\n\t// IE 11...\n\tlet event = document.createEvent('Event');\n\tevent.initEvent(name, true, true);\n\treturn event;\n}\n\n/**\n * Sort a cssText alphabetically.\n * @param {string} cssText\n */\nexport function sortCss(cssText) {\n\treturn (\n\t\tcssText\n\t\t\t.split(';')\n\t\t\t.filter(Boolean)\n\t\t\t.map(s => s.replace(/^\\s+|\\s+$/g, '').replace(/(\\s*:\\s*)/g, ': '))\n\t\t\t.sort((a, b) => {\n\t\t\t\t// CSS Variables are typically positioned at the start\n\t\t\t\tif (a[0] === '-') {\n\t\t\t\t\t// If both are a variable we just compare them\n\t\t\t\t\tif (b[0] === '-') return a.localeCompare(b);\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\t// b is a css var\n\t\t\t\tif (b[0] === '-') return 1;\n\n\t\t\t\treturn a.localeCompare(b);\n\t\t\t})\n\t\t\t.join('; ') + ';'\n\t);\n}\n\n/**\n * Setup the test environment\n * @param {string} [id]\n * @returns {HTMLDivElement}\n */\nexport function setupScratch(id) {\n\tconst scratch = document.createElement('div');\n\tscratch.id = id || 'scratch';\n\t(document.body || document.documentElement).appendChild(scratch);\n\treturn scratch;\n}\n\nlet oldOptions = null;\nexport function clearOptions() {\n\toldOptions = assign({}, options);\n\tdelete options.vnode;\n\tdelete options.diffed;\n\tdelete options.unmount;\n\tdelete options._diff;\n}\n\n/**\n * Teardown test environment and reset preact's internal state\n * @param {HTMLElement} scratch\n */\nexport function teardown(scratch) {\n\tif (!document.contains(scratch)) return;\n\n\tif (scratch) {\n\t\tscratch.parentNode.removeChild(scratch);\n\t}\n\n\tif (oldOptions != null) {\n\t\tassign(options, oldOptions);\n\t\toldOptions = null;\n\t}\n\n\ttestUtilTeardown();\n\n\tif (getLog().length > 0) {\n\t\tclearLog();\n\t}\n\n\trestoreElementAttributes();\n}\n\nconst Foo = () => 'd';\nexport const getMixedArray = () =>\n\t// Make it a function so each test gets a new copy of the array\n\t[0, 'a', 'b', <span>c</span>, <Foo />, null, undefined, false, ['e', 'f'], 1];\nexport const mixedArrayHTML = '0ab<span>c</span>def1';\n\n/**\n * Reset obj to empty to keep reference\n * @param {object} obj\n */\nexport function clear(obj) {\n\tObject.keys(obj).forEach(key => delete obj[key]);\n}\n\n/**\n * Hacky normalization of attribute order across browsers.\n * @param {string} html\n */\nexport function sortAttributes(html) {\n\treturn html.replace(\n\t\t/<([a-z0-9-]+)((?:\\s[a-z0-9:_.-]+=\".*?\")+)((?:\\s*\\/)?>)/gi,\n\t\t(s, pre, attrs, after) => {\n\t\t\tlet list = attrs\n\t\t\t\t.match(/\\s[a-z0-9:_.-]+=\".*?\"/gi)\n\t\t\t\t.sort((a, b) => (a > b ? 1 : -1));\n\t\t\tif (~after.indexOf('/')) after = '></' + pre + '>';\n\t\t\treturn '<' + pre + list.join('') + after;\n\t\t}\n\t);\n}\n\nlet attributesSpy, originalAttributesPropDescriptor;\n\nexport function spyOnElementAttributes() {\n\tconst test = Object.getOwnPropertyDescriptor(Element.prototype, 'attributes');\n\tconst getter = test?.get;\n\n\t// IE11 doesn't correctly restore the prototype methods so we have to check\n\t// whether this prototype method is already a spy.\n\tif (!attributesSpy && !(getter && vi.isMockFunction(getter))) {\n\t\tif (!originalAttributesPropDescriptor) {\n\t\t\toriginalAttributesPropDescriptor = Object.getOwnPropertyDescriptor(\n\t\t\t\tElement.prototype,\n\t\t\t\t'attributes'\n\t\t\t);\n\t\t}\n\n\t\tattributesSpy = vi.spyOn(Element.prototype, 'attributes', 'get');\n\t} else if (getter && vi.isMockFunction(getter)) {\n\t\t// Due to IE11 not resetting we will do this manually when it is a proxy.\n\t\tgetter.mockClear();\n\t}\n\n\treturn attributesSpy || getter;\n}\n\nfunction restoreElementAttributes() {\n\tif (originalAttributesPropDescriptor) {\n\t\t// Workaround bug in Sinon where getter/setter spies don't get auto-restored\n\t\tObject.defineProperty(\n\t\t\tElement.prototype,\n\t\t\t'attributes',\n\t\t\toriginalAttributesPropDescriptor\n\t\t);\n\t\tattributesSpy = null;\n\t}\n}\n"
  },
  {
    "path": "test/_util/logCall.js",
    "content": "/**\n * Serialize an object\n * @param {Object} obj\n * @return {string}\n */\nfunction serialize(obj) {\n\tif (obj instanceof Text) return '#text';\n\tif (obj instanceof Element) return `<${obj.localName}>${obj.textContent}`;\n\tif (obj === document) return 'document';\n\tif (typeof obj == 'string') return obj;\n\treturn Object.prototype.toString.call(obj).replace(/(^\\[object |\\]$)/g, '');\n}\n\n/** @type {string[]} */\nlet log = [];\n\n/**\n * Modify obj's original method to log calls and arguments on logger object\n * @template T\n * @param {T} obj\n * @param {keyof T} method\n */\nexport function logCall(obj, method) {\n\tlet old = obj[method];\n\tobj[method] = function (...args) {\n\t\tlet c = '';\n\t\tfor (let i = 0; i < args.length; i++) {\n\t\t\tif (c) c += ', ';\n\t\t\tc += serialize(args[i]);\n\t\t}\n\n\t\tlet operation;\n\t\tswitch (method) {\n\t\t\tcase 'insertBefore': {\n\t\t\t\tif (args[1] === null && args.length === 2) {\n\t\t\t\t\toperation = `${serialize(this)}.appendChild(${serialize(args[0])})`;\n\t\t\t\t} else {\n\t\t\t\t\toperation = `${serialize(this)}.${String(method)}(${c})`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\toperation = `${serialize(this)}.${String(method)}(${c})`;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tlog.push(operation);\n\t\treturn old.apply(this, args);\n\t};\n\n\treturn () => (obj[method] = old);\n}\n\n/**\n * Return log object\n * @return {string[]} log\n */\nexport function getLog() {\n\treturn log;\n}\n\n/** Clear log object */\nexport function clearLog() {\n\tlog = [];\n}\n\nexport function getLogSummary() {\n\t/** @type {{ [key: string]: number }} */\n\tconst summary = {};\n\n\tfor (let entry of log) {\n\t\tsummary[entry] = (summary[entry] || 0) + 1;\n\t}\n\n\treturn summary;\n}\n"
  },
  {
    "path": "test/_util/optionSpies.js",
    "content": "import { options as rawOptions } from 'preact';\nimport { vi } from 'vitest';\n\n/** @type {import('preact/src/internal').Options} */\nlet options = rawOptions;\n\nlet oldVNode = options.vnode;\nlet oldEvent = options.event || (e => e);\nlet oldAfterDiff = options.diffed;\nlet oldUnmount = options.unmount;\n\nlet oldRoot = options._root;\nlet oldBeforeDiff = options._diff;\nlet oldBeforeRender = options._render;\nlet oldBeforeCommit = options._commit;\nlet oldHook = options._hook;\nlet oldCatchError = options._catchError;\n\nexport const vnodeSpy = vi.fn(oldVNode);\nexport const eventSpy = vi.fn(oldEvent);\nexport const afterDiffSpy = vi.fn(oldAfterDiff);\nexport const unmountSpy = vi.fn(oldUnmount);\n\nexport const rootSpy = vi.fn(oldRoot);\nexport const beforeDiffSpy = vi.fn(oldBeforeDiff);\nexport const beforeRenderSpy = vi.fn(oldBeforeRender);\nexport const beforeCommitSpy = vi.fn(oldBeforeCommit);\nexport const hookSpy = vi.fn(oldHook);\nexport const catchErrorSpy = vi.fn(oldCatchError);\n\noptions.vnode = vnodeSpy;\noptions.event = eventSpy;\noptions.diffed = afterDiffSpy;\noptions.unmount = unmountSpy;\noptions._root = rootSpy;\noptions._diff = beforeDiffSpy;\noptions._render = beforeRenderSpy;\noptions._commit = beforeCommitSpy;\noptions._hook = hookSpy;\noptions._catchError = catchErrorSpy;\n"
  },
  {
    "path": "test/browser/cloneElement.test.jsx",
    "content": "import { createElement, cloneElement, createRef } from 'preact';\n\ndescribe('cloneElement', () => {\n\tit('should clone components', () => {\n\t\tfunction Comp() {}\n\t\tconst instance = <Comp prop1={1}>hello</Comp>;\n\t\tconst clone = cloneElement(instance);\n\n\t\texpect(clone.prototype).to.equal(instance.prototype);\n\t\texpect(clone.type).to.equal(instance.type);\n\t\texpect(clone.props).not.to.equal(instance.props); // Should be a different object...\n\t\texpect(clone.props).to.deep.equal(instance.props); // with the same properties\n\t});\n\n\tit('should merge new props', () => {\n\t\tfunction Foo() {}\n\t\tconst instance = <Foo prop1={1} prop2={2} />;\n\t\tconst clone = cloneElement(instance, { prop1: -1, newProp: -2 });\n\n\t\texpect(clone.prototype).to.equal(instance.prototype);\n\t\texpect(clone.type).to.equal(instance.type);\n\t\texpect(clone.props).not.to.equal(instance.props);\n\t\texpect(clone.props.prop1).to.equal(-1);\n\t\texpect(clone.props.prop2).to.equal(2);\n\t\texpect(clone.props.newProp).to.equal(-2);\n\t});\n\n\tit('should override children if specified', () => {\n\t\tfunction Foo() {}\n\t\tconst instance = <Foo>hello</Foo>;\n\t\tconst clone = cloneElement(instance, null, 'world', '!');\n\n\t\texpect(clone.prototype).to.equal(instance.prototype);\n\t\texpect(clone.type).to.equal(instance.type);\n\t\texpect(clone.props).not.to.equal(instance.props);\n\t\texpect(clone.props.children).to.deep.equal(['world', '!']);\n\t});\n\n\tit('should override children if null is provided as an argument', () => {\n\t\tfunction Foo() {}\n\t\tconst instance = <Foo>foo</Foo>;\n\t\tconst clone = cloneElement(instance, { children: 'bar' }, null);\n\n\t\texpect(clone.prototype).to.equal(instance.prototype);\n\t\texpect(clone.type).to.equal(instance.type);\n\t\texpect(clone.props).not.to.equal(instance.props);\n\t\texpect(clone.props.children).to.be.null;\n\t});\n\n\tit('should override key if specified', () => {\n\t\tfunction Foo() {}\n\t\tconst instance = <Foo key=\"1\">hello</Foo>;\n\n\t\tlet clone = cloneElement(instance);\n\t\texpect(clone.key).to.equal('1');\n\n\t\tclone = cloneElement(instance, { key: '2' });\n\t\texpect(clone.key).to.equal('2');\n\t});\n\n\tit('should override ref if specified', () => {\n\t\tfunction a() {}\n\t\tfunction b() {}\n\t\tconst instance = <div ref={a}>hello</div>;\n\n\t\tlet clone = cloneElement(instance);\n\t\texpect(clone.ref).to.equal(a);\n\n\t\tclone = cloneElement(instance, { ref: b });\n\t\texpect(clone.ref).to.equal(b);\n\t});\n\n\tit('should normalize props (ref)', () => {\n\t\tconst div = <div>hello</div>;\n\t\tconst clone = cloneElement(div, { ref: createRef() });\n\t\texpect(clone.props.ref).to.equal(undefined);\n\t});\n\n\tit('should normalize props (key)', () => {\n\t\tconst div = <div>hello</div>;\n\t\tconst clone = cloneElement(div, { key: 'myKey' });\n\t\texpect(clone.props.key).to.equal(undefined);\n\t});\n});\n"
  },
  {
    "path": "test/browser/components.test.jsx",
    "content": "import { createElement, render, Component, Fragment, options } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport {\n\tsetupScratch,\n\tteardown,\n\tgetMixedArray,\n\tmixedArrayHTML,\n\tserializeHtml,\n\tsortAttributes\n} from '../_util/helpers';\nimport { vi } from 'vitest';\n\nconst h = createElement;\n\nfunction getAttributes(node) {\n\tlet attrs = {};\n\tif (node.attributes) {\n\t\tfor (let i = node.attributes.length; i--; ) {\n\t\t\tattrs[node.attributes[i].name] = node.attributes[i].value;\n\t\t}\n\t}\n\treturn attrs;\n}\n\ndescribe('Components', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('Component construction', () => {\n\t\t/** @type {object} */\n\t\tlet instance;\n\t\tlet PROPS;\n\t\tlet STATE;\n\n\t\tbeforeEach(() => {\n\t\t\tinstance = null;\n\t\t\tPROPS = { foo: 'bar', onBaz: () => {} };\n\t\t\tSTATE = { text: 'Hello' };\n\t\t});\n\n\t\tit('should render components', () => {\n\t\t\tclass C1 extends Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>C1</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(C1.prototype, 'render');\n\t\t\trender(<C1 />, scratch);\n\n\t\t\texpect(C1.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(C1.prototype.render).toHaveBeenCalledWith({}, {}, {});\n\t\t\texpect(C1.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div' })\n\t\t\t);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div>C1</div>');\n\t\t});\n\n\t\tit('should render functional components', () => {\n\t\t\tconst C3 = vi.fn(props => <div {...props} />);\n\n\t\t\trender(<C3 {...PROPS} />, scratch);\n\n\t\t\texpect(C3).toHaveBeenCalledOnce().toHaveBeenCalledWith(PROPS, {});\n\t\t\t// .toHaveReturnedWith({\n\t\t\t// \ttype: 'div',\n\t\t\t// \tprops: PROPS\n\t\t\t// });\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\"></div>');\n\t\t});\n\n\t\tit('should render components with props', () => {\n\t\t\tlet constructorProps;\n\n\t\t\tclass C2 extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tconstructorProps = props;\n\t\t\t\t}\n\t\t\t\trender(props) {\n\t\t\t\t\treturn <div {...props} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(C2.prototype, 'render');\n\n\t\t\trender(<C2 {...PROPS} />, scratch);\n\n\t\t\texpect(constructorProps).to.deep.equal(PROPS);\n\n\t\t\texpect(C2.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(C2.prototype.render).toHaveBeenCalledWith(PROPS, {}, {});\n\t\t\texpect(C2.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({\n\t\t\t\t\ttype: 'div',\n\t\t\t\t\tprops: PROPS\n\t\t\t\t})\n\t\t\t);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\"></div>');\n\t\t});\n\n\t\tit('should not crash when setting state in constructor', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\t// the following line made `this._nextState !== this.state` be truthy prior to the fix for preactjs/preact#2638\n\t\t\t\t\tthis.state = {};\n\t\t\t\t\tthis.setState({ preact: 'awesome' });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\texpect(() => render(<Foo foo=\"bar\" />, scratch)).not.to.throw();\n\t\t\trerender();\n\t\t});\n\n\t\tit('should not crash when setting state with cb in constructor', () => {\n\t\t\tlet spy = vi.fn();\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.setState({ preact: 'awesome' }, spy);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\texpect(() => render(<Foo foo=\"bar\" />, scratch)).not.to.throw();\n\t\t\trerender();\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should not crash when calling forceUpdate with cb in constructor', () => {\n\t\t\tlet spy = vi.fn();\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.forceUpdate(spy);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\texpect(() => render(<Foo foo=\"bar\" />, scratch)).not.to.throw();\n\t\t\trerender();\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should accurately call nested setState callbacks', () => {\n\t\t\tlet states = [];\n\t\t\tlet finalState;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { a: 'b' };\n\t\t\t\t}\n\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tstates.push(this.state);\n\t\t\t\t\texpect(scratch.innerHTML).to.equal('<p>b</p>');\n\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\tthis.setState({ a: 'a' }, () => {\n\t\t\t\t\t\tstates.push(this.state);\n\t\t\t\t\t\texpect(scratch.innerHTML).to.equal('<p>a</p>');\n\n\t\t\t\t\t\tthis.setState({ a: 'c' }, () => {\n\t\t\t\t\t\t\texpect(scratch.innerHTML).to.equal('<p>c</p>');\n\t\t\t\t\t\t\tstates.push(this.state);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tfinalState = this.state;\n\t\t\t\t\treturn <p>{this.state.a}</p>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\trerender(); // First setState\n\t\t\trerender(); // Second setState\n\n\t\t\tlet [firstState, secondState, thirdState] = states;\n\t\t\texpect(finalState).to.deep.equal({ a: 'c' });\n\t\t\texpect(firstState).to.deep.equal({ a: 'b' });\n\t\t\texpect(secondState).to.deep.equal({ a: 'a' });\n\t\t\texpect(thirdState).to.deep.equal({ a: 'c' });\n\t\t});\n\n\t\tit('should initialize props & context but not state in Component constructor', () => {\n\t\t\t// Not initializing state matches React behavior: https://codesandbox.io/s/rml19v8o2q\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\texpect(this.props).to.equal(props);\n\t\t\t\t\texpect(this.state).to.deep.equal(undefined);\n\t\t\t\t\texpect(this.context).to.equal(context);\n\n\t\t\t\t\tinstance = this;\n\t\t\t\t}\n\t\t\t\trender(props) {\n\t\t\t\t\treturn <div {...props}>Hello</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, {}, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal({});\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit(\"should render Component classes that don't pass args into the Component constructor\", () => {\n\t\t\tfunction Foo() {\n\t\t\t\tComponent.call(this);\n\t\t\t\tinstance = this;\n\t\t\t\tthis.state = STATE;\n\t\t\t}\n\t\t\tFoo.prototype.render = vi.fn((props, state) => (\n\t\t\t\t<div {...props}>{state.text}</div>\n\t\t\t));\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, STATE, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal(STATE);\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit('should also update the current dom', () => {\n\t\t\tlet trigger;\n\n\t\t\tclass A extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { show: false };\n\t\t\t\t\ttrigger = this.set = this.set.bind(this);\n\t\t\t\t}\n\n\t\t\t\tset() {\n\t\t\t\t\tthis.setState({ show: true });\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.show ? <div>A</div> : null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst B = () => <p>B</p>;\n\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\t<A />\n\t\t\t\t\t<B />\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(scratch.innerHTML).to.equal('<div><p>B</p></div>');\n\n\t\t\ttrigger();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div><div>A</div><p>B</p></div>');\n\t\t});\n\n\t\tit('should not orphan children', () => {\n\t\t\tlet triggerC, triggerA;\n\t\t\tconst B = () => <p>B</p>;\n\n\t\t\t// Component with state which swaps its returned element type\n\t\t\tclass C extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { show: false };\n\t\t\t\t\ttriggerC = this.set = this.set.bind(this);\n\t\t\t\t}\n\n\t\t\t\tset() {\n\t\t\t\t\tthis.setState({ show: true });\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.show ? <div>data</div> : <p>Loading</p>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst WrapC = () => <C />;\n\n\t\t\tclass A extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { show: false };\n\t\t\t\t\ttriggerA = this.set = this.set.bind(this);\n\t\t\t\t}\n\n\t\t\t\tset() {\n\t\t\t\t\tthis.setState({ show: true });\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.show ? <B /> : <WrapC />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<A />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<p>Loading</p>');\n\n\t\t\ttriggerC();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>data</div>');\n\n\t\t\ttriggerA();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<p>B</p>');\n\t\t});\n\n\t\tit('should update children props correctly in subsequent renders', () => {\n\t\t\tlet update, update2;\n\t\t\tclass Counter extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { counter: 0 };\n\t\t\t\t\tupdate2 = () => {\n\t\t\t\t\t\tthis.setState({ counter: this.state.counter + 1 });\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\trender({ counter }) {\n\t\t\t\t\tif (!counter) return null;\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<p>\n\t\t\t\t\t\t\t{counter}-{this.state.counter}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { counter: 0 };\n\t\t\t\t\tupdate = () => {\n\t\t\t\t\t\tthis.setState({ counter: this.state.counter + 1 });\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <Counter counter={this.state.counter} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\t\tupdate2();\n\t\t\trerender();\n\t\t\tupdate();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<p>1-1</p>');\n\t\t});\n\n\t\tit(\"should render components that don't pass args into the Component constructor (unistore pattern)\", () => {\n\t\t\t// Pattern unistore uses for connect: https://github.com/developit/unistore/blob/1df7cf60ac6fa1a70859d745fbaea7ea3f1b8d30/src/integrations/preact.js#L23\n\t\t\tfunction Wrapper() {\n\t\t\t\tinstance = this;\n\t\t\t\tthis.state = STATE;\n\t\t\t\tthis.render = vi.fn((props, state) => (\n\t\t\t\t\t<div {...props}>{state.text}</div>\n\t\t\t\t));\n\t\t\t}\n\t\t\t(Wrapper.prototype = new Component()).constructor = Wrapper;\n\n\t\t\trender(<Wrapper {...PROPS} />, scratch);\n\n\t\t\texpect(instance.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(instance.render).toHaveBeenCalledWith(PROPS, STATE, {});\n\t\t\texpect(instance.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal(STATE);\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit(\"should render components that don't call Component constructor\", () => {\n\t\t\tfunction Foo() {\n\t\t\t\tinstance = this;\n\t\t\t\tthis.state = STATE;\n\t\t\t}\n\t\t\tFoo.prototype = Object.create(Component);\n\t\t\tFoo.prototype.render = vi.fn((props, state) => (\n\t\t\t\t<div {...props}>{state.text}</div>\n\t\t\t));\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, STATE, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal(STATE);\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit(\"should render components that don't call Component constructor and don't initialize state\", () => {\n\t\t\tfunction Foo() {\n\t\t\t\tinstance = this;\n\t\t\t}\n\t\t\tFoo.prototype.render = vi.fn(props => <div {...props}>Hello</div>);\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, {}, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal({});\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit(\"should render components that don't inherit from Component\", () => {\n\t\t\tclass Foo {\n\t\t\t\tconstructor() {\n\t\t\t\t\tinstance = this;\n\t\t\t\t\tthis.state = STATE;\n\t\t\t\t}\n\t\t\t\trender(props, state) {\n\t\t\t\t\treturn <div {...props}>{state.text}</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, STATE, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal(STATE);\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit(\"should render components that don't inherit from Component (unistore pattern)\", () => {\n\t\t\t// Pattern unistore uses for Provider: https://github.com/developit/unistore/blob/1df7cf60ac6fa1a70859d745fbaea7ea3f1b8d30/src/integrations/preact.js#L59\n\t\t\tfunction Provider() {\n\t\t\t\tinstance = this;\n\t\t\t\tthis.state = STATE;\n\t\t\t}\n\t\t\tProvider.prototype.render = vi.fn((props, state) => (\n\t\t\t\t<div {...PROPS}>{state.text}</div>\n\t\t\t));\n\n\t\t\trender(<Provider {...PROPS} />, scratch);\n\n\t\t\texpect(Provider.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Provider.prototype.render).toHaveBeenCalledWith(PROPS, STATE, {});\n\t\t\texpect(Provider.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal(STATE);\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit(\"should render components that don't inherit from Component and don't initialize state\", () => {\n\t\t\tclass Foo {\n\t\t\t\tconstructor() {\n\t\t\t\t\tinstance = this;\n\t\t\t\t}\n\t\t\t\trender(props, state) {\n\t\t\t\t\treturn <div {...props}>Hello</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, {}, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(\n\t\t\t\texpect.objectContaining({ type: 'div', props: PROPS })\n\t\t\t);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal({});\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">Hello</div>');\n\t\t});\n\n\t\tit('should render class components that inherit from Component without a render method', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tinstance = this;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\trender(<Foo {...PROPS} />, scratch);\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledWith(PROPS, {}, {});\n\t\t\texpect(Foo.prototype.render).toHaveReturned(undefined);\n\t\t\texpect(instance.props).to.deep.equal(PROPS);\n\t\t\texpect(instance.state).to.deep.equal({});\n\t\t\texpect(instance.context).to.deep.equal({});\n\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\t\t});\n\t});\n\n\tit('should render string', () => {\n\t\tclass StringComponent extends Component {\n\t\t\trender() {\n\t\t\t\treturn 'Hi there';\n\t\t\t}\n\t\t}\n\n\t\trender(<StringComponent />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('Hi there');\n\t});\n\n\tit('should render number as string', () => {\n\t\tclass NumberComponent extends Component {\n\t\t\trender() {\n\t\t\t\treturn 42;\n\t\t\t}\n\t\t}\n\n\t\trender(<NumberComponent />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('42');\n\t});\n\n\tit('should render a new String()', () => {\n\t\tclass ConstructedStringComponent extends Component {\n\t\t\trender() {\n\t\t\t\t/* eslint-disable no-new-wrappers */\n\t\t\t\treturn new String('Hi from a constructed string!');\n\t\t\t}\n\t\t}\n\n\t\trender(<ConstructedStringComponent />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('Hi from a constructed string!');\n\t});\n\n\tit('should render null as empty string', () => {\n\t\tclass NullComponent extends Component {\n\t\t\trender() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\trender(<NullComponent />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\t// Test for Issue #73\n\tit('should remove orphaned elements replaced by Components', () => {\n\t\tclass Comp extends Component {\n\t\t\trender() {\n\t\t\t\treturn <span>span in a component</span>;\n\t\t\t}\n\t\t}\n\n\t\tlet root;\n\t\tfunction test(content) {\n\t\t\troot = render(content, scratch, root);\n\t\t}\n\n\t\ttest(<Comp />);\n\t\ttest(<div>just a div</div>);\n\t\ttest(<Comp />);\n\n\t\texpect(scratch.innerHTML).to.equal('<span>span in a component</span>');\n\t});\n\n\t// Test for Issue preactjs/preact#176\n\tit('should remove children when root changes to text node', () => {\n\t\t/** @type {import('preact').Component} */\n\t\tlet comp;\n\n\t\tclass Comp extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tcomp = this;\n\t\t\t}\n\t\t\trender(_, { alt }) {\n\t\t\t\treturn alt ? 'asdf' : <div>test</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\n\t\tcomp.setState({ alt: true });\n\t\tcomp.forceUpdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML, 'switching to textnode').to.equal('asdf');\n\n\t\tcomp.setState({ alt: false });\n\t\tcomp.forceUpdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML, 'switching to element').to.equal(\n\t\t\t'<div>test</div>'\n\t\t);\n\n\t\tcomp.setState({ alt: true });\n\t\tcomp.forceUpdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML, 'switching to textnode 2').to.equal('asdf');\n\t});\n\n\t// Test for Issue preactjs/preact#1616\n\tit('should maintain order when setting state (that inserts dom-elements)', () => {\n\t\tlet add, addTwice, reset;\n\t\tconst Entry = props => <div>{props.children}</div>;\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\n\t\t\t\tthis.state = { values: ['abc'] };\n\n\t\t\t\tadd = this.add = this.add.bind(this);\n\t\t\t\taddTwice = this.addTwice = this.addTwice.bind(this);\n\t\t\t\treset = this.reset = this.reset.bind(this);\n\t\t\t}\n\n\t\t\tadd() {\n\t\t\t\tthis.setState({ values: [...this.state.values, 'def'] });\n\t\t\t}\n\n\t\t\taddTwice() {\n\t\t\t\tthis.setState({ values: [...this.state.values, 'def', 'ghi'] });\n\t\t\t}\n\n\t\t\treset() {\n\t\t\t\tthis.setState({ values: ['abc'] });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.values.map(v => (\n\t\t\t\t\t\t\t<Entry>{v}</Entry>\n\t\t\t\t\t\t))}\n\t\t\t\t\t\t<button>First Button</button>\n\t\t\t\t\t\t<button>Second Button</button>\n\t\t\t\t\t\t<button>Third Button</button>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.firstChild.innerHTML).to.equal(\n\t\t\t'<div>abc</div>' +\n\t\t\t\t'<button>First Button</button><button>Second Button</button><button>Third Button</button>'\n\t\t);\n\n\t\tadd();\n\t\trerender();\n\t\texpect(scratch.firstChild.innerHTML).to.equal(\n\t\t\t'<div>abc</div><div>def' +\n\t\t\t\t'</div><button>First Button</button><button>Second Button</button><button>Third Button</button>'\n\t\t);\n\n\t\tadd();\n\t\trerender();\n\t\texpect(scratch.firstChild.innerHTML).to.equal(\n\t\t\t'<div>abc</div><div>def</div><div>def' +\n\t\t\t\t'</div><button>First Button</button><button>Second Button</button><button>Third Button</button>'\n\t\t);\n\n\t\treset();\n\t\trerender();\n\t\texpect(scratch.firstChild.innerHTML).to.equal(\n\t\t\t'<div>abc</div>' +\n\t\t\t\t'<button>First Button</button><button>Second Button</button><button>Third Button</button>'\n\t\t);\n\n\t\taddTwice();\n\t\trerender();\n\t\texpect(scratch.firstChild.innerHTML).to.equal(\n\t\t\t'<div>abc</div><div>def</div><div>ghi' +\n\t\t\t\t'</div><button>First Button</button><button>Second Button</button><button>Third Button</button>'\n\t\t);\n\t});\n\n\t// Test for Issue preactjs/preact#254\n\tit('should not recycle common class children with different keys', () => {\n\t\tlet idx = 0;\n\t\tlet msgs = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];\n\t\tlet sideEffect = vi.fn();\n\n\t\tclass Comp extends Component {\n\t\t\tcomponentWillMount() {\n\t\t\t\tthis.innerMsg = msgs[idx++ % 8];\n\t\t\t\tsideEffect();\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>{this.innerMsg}</div>;\n\t\t\t}\n\t\t}\n\t\tvi.spyOn(Comp.prototype, 'componentWillMount');\n\n\t\tlet good, bad;\n\t\tclass GoodContainer extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { alt: false };\n\t\t\t\tgood = this;\n\t\t\t}\n\n\t\t\trender(_, { alt }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{alt ? null : <Comp key={1} alt={alt} />}\n\t\t\t\t\t\t{alt ? null : <Comp key={2} alt={alt} />}\n\t\t\t\t\t\t{alt ? <Comp key={3} alt={alt} /> : null}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass BadContainer extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { alt: false };\n\t\t\t\tbad = this;\n\t\t\t}\n\n\t\t\trender(_, { alt }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{alt ? null : <Comp alt={alt} />}\n\t\t\t\t\t\t{alt ? null : <Comp alt={alt} />}\n\t\t\t\t\t\t{alt ? <Comp alt={alt} /> : null}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<GoodContainer />, scratch);\n\t\texpect(scratch.textContent, 'new component with key present').to.equal(\n\t\t\t'AB'\n\t\t);\n\t\texpect(Comp.prototype.componentWillMount).toHaveBeenCalledTimes(2);\n\t\texpect(sideEffect).toHaveBeenCalledTimes(2);\n\n\t\tsideEffect.mockClear();\n\t\tComp.prototype.componentWillMount.mockClear();\n\t\tgood.setState({ alt: true });\n\t\trerender();\n\t\texpect(\n\t\t\tscratch.textContent,\n\t\t\t'new component with key present re-rendered'\n\t\t).to.equal('C');\n\t\t//we are recycling the first 2 components already rendered, just need a new one\n\t\texpect(Comp.prototype.componentWillMount).toHaveBeenCalledTimes(1);\n\t\texpect(sideEffect).toHaveBeenCalledTimes(1);\n\n\t\tsideEffect.mockClear();\n\t\tComp.prototype.componentWillMount.mockClear();\n\t\trender(<BadContainer />, scratch);\n\t\texpect(scratch.textContent, 'new component without key').to.equal('DE');\n\t\texpect(Comp.prototype.componentWillMount).toHaveBeenCalledTimes(2);\n\t\texpect(sideEffect).toHaveBeenCalledTimes(2);\n\n\t\tsideEffect.mockClear();\n\t\tComp.prototype.componentWillMount.mockClear();\n\t\tbad.setState({ alt: true });\n\t\trerender();\n\n\t\texpect(\n\t\t\tscratch.textContent,\n\t\t\t'use null placeholders to detect new component is appended'\n\t\t).to.equal('F');\n\t\texpect(Comp.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\texpect(sideEffect).toHaveBeenCalledOnce();\n\t});\n\n\tdescribe('array children', () => {\n\t\tit(\"should render DOM element's array children\", () => {\n\t\t\trender(<div>{getMixedArray()}</div>, scratch);\n\t\t\texpect(scratch.firstChild.innerHTML).to.equal(mixedArrayHTML);\n\t\t});\n\n\t\tit(\"should render Component's array children\", () => {\n\t\t\tconst Foo = () => getMixedArray();\n\n\t\t\trender(<Foo />, scratch);\n\n\t\t\texpect(scratch.innerHTML).to.equal(mixedArrayHTML);\n\t\t});\n\n\t\tit(\"should render Fragment's array children\", () => {\n\t\t\tconst Foo = () => <Fragment>{getMixedArray()}</Fragment>;\n\n\t\t\trender(<Foo />, scratch);\n\n\t\t\texpect(scratch.innerHTML).to.equal(mixedArrayHTML);\n\t\t});\n\n\t\tit('should render sibling array children', () => {\n\t\t\tconst Todo = () => (\n\t\t\t\t<ul>\n\t\t\t\t\t<li>A header</li>\n\t\t\t\t\t{['a', 'b'].map(value => (\n\t\t\t\t\t\t<li>{value}</li>\n\t\t\t\t\t))}\n\t\t\t\t\t<li>A divider</li>\n\t\t\t\t\t{['c', 'd'].map(value => (\n\t\t\t\t\t\t<li>{value}</li>\n\t\t\t\t\t))}\n\t\t\t\t\t<li>A footer</li>\n\t\t\t\t</ul>\n\t\t\t);\n\n\t\t\trender(<Todo />, scratch);\n\n\t\t\tlet ul = scratch.firstChild;\n\t\t\texpect(ul.childNodes.length).to.equal(7);\n\t\t\texpect(ul.childNodes[0].textContent).to.equal('A header');\n\t\t\texpect(ul.childNodes[1].textContent).to.equal('a');\n\t\t\texpect(ul.childNodes[2].textContent).to.equal('b');\n\t\t\texpect(ul.childNodes[3].textContent).to.equal('A divider');\n\t\t\texpect(ul.childNodes[4].textContent).to.equal('c');\n\t\t\texpect(ul.childNodes[5].textContent).to.equal('d');\n\t\t\texpect(ul.childNodes[6].textContent).to.equal('A footer');\n\t\t});\n\t});\n\n\tdescribe('props.children', () => {\n\t\tlet children;\n\n\t\tlet Foo = props => {\n\t\t\tchildren = props.children;\n\t\t\treturn <div>{props.children}</div>;\n\t\t};\n\n\t\tlet FunctionFoo = props => {\n\t\t\tchildren = props.children;\n\t\t\treturn <div>{props.children(2)}</div>;\n\t\t};\n\n\t\tlet Bar = () => <span>Bar</span>;\n\n\t\tbeforeEach(() => {\n\t\t\tchildren = undefined;\n\t\t});\n\n\t\tit('should support passing children as a prop', () => {\n\t\t\tconst Foo = props => <div {...props} />;\n\n\t\t\trender(\n\t\t\t\t<Foo a=\"b\" children={[<span class=\"bar\">bar</span>, '123', 456]} />,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t'<div a=\"b\"><span class=\"bar\">bar</span>123456</div>'\n\t\t\t);\n\t\t});\n\n\t\tit('should be ignored when explicit children exist', () => {\n\t\t\tconst Foo = props => <div {...props}>a</div>;\n\n\t\t\trender(<Foo children={'b'} />, scratch);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div>a</div>');\n\t\t});\n\n\t\tit('should be undefined with no child', () => {\n\t\t\trender(<Foo />, scratch);\n\n\t\t\texpect(children).to.be.undefined;\n\t\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\t});\n\n\t\tit('should be null with null as a child', () => {\n\t\t\trender(<Foo>{null}</Foo>, scratch);\n\n\t\t\texpect(children).to.be.null;\n\t\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\t});\n\n\t\tit('should be false with false as a child', () => {\n\t\t\trender(<Foo>{false}</Foo>, scratch);\n\n\t\t\texpect(children).to.be.false;\n\t\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\t});\n\n\t\tit('should be true with true as a child', () => {\n\t\t\trender(<Foo>{true}</Foo>, scratch);\n\n\t\t\texpect(children).to.be.true;\n\t\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\t});\n\n\t\tit('should be a string with a text child', () => {\n\t\t\trender(<Foo>text</Foo>, scratch);\n\n\t\t\texpect(children).to.be.a('string');\n\t\t\texpect(children).to.equal('text');\n\t\t\texpect(scratch.innerHTML).to.equal('<div>text</div>');\n\t\t});\n\n\t\tit('should be a string with a number child', () => {\n\t\t\trender(<Foo>1</Foo>, scratch);\n\n\t\t\texpect(children).to.be.a('string');\n\t\t\texpect(children).to.equal('1');\n\t\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\t\t});\n\n\t\tit('should be a VNode with a DOM node child', () => {\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\t<span />\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(children).to.be.an('object');\n\t\t\texpect(children.type).to.equal('span');\n\t\t\texpect(scratch.innerHTML).to.equal('<div><span></span></div>');\n\t\t});\n\n\t\tit('should be a VNode with a Component child', () => {\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\t<Bar />\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(children).to.be.an('object');\n\t\t\texpect(children.type).to.equal(Bar);\n\t\t\texpect(scratch.innerHTML).to.equal('<div><span>Bar</span></div>');\n\t\t});\n\n\t\tit('should be a function with a function child', () => {\n\t\t\tconst child = num => num.toFixed(2);\n\t\t\trender(<FunctionFoo>{child}</FunctionFoo>, scratch);\n\n\t\t\texpect(children).to.be.an('function');\n\t\t\texpect(children).to.equal(child);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>2.00</div>');\n\t\t});\n\n\t\tit('should be an array with multiple children', () => {\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\t0<span />\n\t\t\t\t\t<input />\n\t\t\t\t\t<div />1\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(children).to.be.an('array');\n\t\t\texpect(children[0]).to.equal('0');\n\t\t\texpect(children[1].type).to.equal('span');\n\t\t\texpect(children[2].type).to.equal('input');\n\t\t\texpect(children[3].type).to.equal('div');\n\t\t\texpect(children[4]).to.equal('1');\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t`<div>0<span></span><input><div></div>1</div>`\n\t\t\t);\n\t\t});\n\n\t\tit('should be an array with an array as children', () => {\n\t\t\tconst mixedArray = getMixedArray();\n\t\t\trender(<Foo>{mixedArray}</Foo>, scratch);\n\n\t\t\texpect(children).to.be.an('array');\n\t\t\texpect(children).to.deep.equal(mixedArray);\n\t\t\texpect(scratch.innerHTML).to.equal(`<div>${mixedArrayHTML}</div>`);\n\t\t});\n\n\t\tit('should not flatten sibling and nested arrays', () => {\n\t\t\tconst list1 = [0, 1];\n\t\t\tconst list2 = [2, 3];\n\t\t\tconst list3 = [4, 5];\n\t\t\tconst list4 = [6, 7];\n\t\t\tconst list5 = [8, 9];\n\n\t\t\trender(\n\t\t\t\t<Foo>\n\t\t\t\t\t{[list1, list2]}\n\t\t\t\t\t{[list3, list4]}\n\t\t\t\t\t{list5}\n\t\t\t\t</Foo>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(children).to.be.an('array');\n\t\t\texpect(children).to.deep.equal([[list1, list2], [list3, list4], list5]);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>0123456789</div>');\n\t\t});\n\t});\n\n\tdescribe('High-Order Components', () => {\n\t\tit('should render wrapper HOCs', () => {\n\t\t\tconst text = \"We'll throw some happy little limbs on this tree.\";\n\n\t\t\tfunction withBobRoss(ChildComponent) {\n\t\t\t\treturn class BobRossIpsum extends Component {\n\t\t\t\t\tgetChildContext() {\n\t\t\t\t\t\treturn { text };\n\t\t\t\t\t}\n\n\t\t\t\t\trender(props) {\n\t\t\t\t\t\treturn <ChildComponent {...props} />;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst PaintSomething = (props, context) => <div>{context.text}</div>;\n\t\t\tconst Paint = withBobRoss(PaintSomething);\n\n\t\t\trender(<Paint />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal(`<div>${text}</div>`);\n\t\t});\n\n\t\tit('should render HOCs with generic children', () => {\n\t\t\tconst text =\n\t\t\t\t\"Let your imagination just wonder around when you're doing these things.\";\n\n\t\t\tclass BobRossProvider extends Component {\n\t\t\t\tgetChildContext() {\n\t\t\t\t\treturn { text };\n\t\t\t\t}\n\n\t\t\t\trender(props) {\n\t\t\t\t\treturn props.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction BobRossConsumer(props, context) {\n\t\t\t\treturn props.children(context.text);\n\t\t\t}\n\n\t\t\tconst Say = props => <div>{props.text}</div>;\n\n\t\t\tconst Speak = () => (\n\t\t\t\t<BobRossProvider>\n\t\t\t\t\t<span>A span</span>\n\t\t\t\t\t<BobRossConsumer>{text => <Say text={text} />}</BobRossConsumer>\n\t\t\t\t\t<span>A final span</span>\n\t\t\t\t</BobRossProvider>\n\t\t\t);\n\n\t\t\trender(<Speak />, scratch);\n\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t`<span>A span</span><div>${text}</div><span>A final span</span>`\n\t\t\t);\n\t\t});\n\n\t\tit('should render nested functional components', () => {\n\t\t\tconst PROPS = { foo: 'bar', onBaz: () => {} };\n\n\t\t\tconst Outer = vi.fn(props => <Inner {...props} />);\n\n\t\t\tconst Inner = vi.fn(props => <div {...props}>inner</div>);\n\n\t\t\trender(<Outer {...PROPS} />, scratch);\n\n\t\t\texpect(Outer)\n\t\t\t\t.toHaveBeenCalledOnce()\n\t\t\t\t.toHaveBeenCalledWith(PROPS, {})\n\t\t\t\t.toHaveReturned(\n\t\t\t\t\texpect.objectContaining({\n\t\t\t\t\t\ttype: Inner,\n\t\t\t\t\t\tprops: PROPS\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\texpect(Inner)\n\t\t\t\t.toHaveBeenCalledOnce()\n\t\t\t\t.toHaveBeenCalledWith(PROPS, {})\n\t\t\t\t.toHaveReturned(\n\t\t\t\t\texpect.objectContaining({\n\t\t\t\t\t\ttype: 'div',\n\t\t\t\t\t\tprops: { ...PROPS, children: 'inner' }\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div foo=\"bar\">inner</div>');\n\t\t});\n\n\t\tit('should re-render nested functional components', () => {\n\t\t\tlet doRender = null;\n\t\t\tclass Outer extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tlet i = 1;\n\t\t\t\t\tdoRender = () => this.setState({ i: ++i });\n\t\t\t\t}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <Inner i={i} {...props} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Outer.prototype, 'render');\n\t\t\tvi.spyOn(Outer.prototype, 'componentWillUnmount');\n\n\t\t\tlet j = 0;\n\t\t\tconst Inner = vi.fn(props => (\n\t\t\t\t<div j={++j} {...props}>\n\t\t\t\t\tinner\n\t\t\t\t</div>\n\t\t\t));\n\n\t\t\trender(<Outer foo=\"bar\" />, scratch);\n\n\t\t\t// update & flush\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(Outer.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\n\t\t\texpect(Inner).toHaveBeenNthCalledWith(2, { foo: 'bar', i: 2 }, {});\n\n\t\t\texpect(getAttributes(scratch.firstElementChild)).to.eql({\n\t\t\t\tj: '2',\n\t\t\t\ti: '2',\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\n\t\t\t// update & flush\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(Inner).toHaveBeenCalledTimes(3);\n\n\t\t\texpect(Inner).toHaveBeenNthCalledWith(3, { foo: 'bar', i: 3 }, {});\n\n\t\t\texpect(getAttributes(scratch.firstElementChild)).to.eql({\n\t\t\t\tj: '3',\n\t\t\t\ti: '3',\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\t\t});\n\n\t\tit('should re-render nested components', () => {\n\t\t\tlet doRender = null,\n\t\t\t\talt = false;\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tlet i = 1;\n\t\t\t\t\tdoRender = () => this.setState({ i: ++i });\n\t\t\t\t}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\tif (alt) return <div is-alt />;\n\t\t\t\t\treturn <Inner i={i} {...props} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Outer.prototype, 'render');\n\t\t\tvi.spyOn(Outer.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Outer.prototype, 'componentWillUnmount');\n\n\t\t\tlet j = 0;\n\t\t\tclass Inner extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t}\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender(props) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div j={++j} {...props}>\n\t\t\t\t\t\t\tinner\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner.prototype, 'render');\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillUnmount');\n\n\t\t\trender(<Outer foo=\"bar\" />, scratch);\n\n\t\t\texpect(Outer.prototype.componentDidMount).toHaveBeenCalledOnce();\n\n\t\t\t// update & flush\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(Outer.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.render).toHaveBeenCalledTimes(2);\n\n\t\t\texpect(Inner.prototype.render).toHaveBeenNthCalledWith(\n\t\t\t\t2,\n\t\t\t\t{ foo: 'bar', i: 2 },\n\t\t\t\t{},\n\t\t\t\t{}\n\t\t\t);\n\n\t\t\texpect(getAttributes(scratch.firstElementChild)).to.eql({\n\t\t\t\tj: '2',\n\t\t\t\ti: '2',\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\n\t\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\t\tsortAttributes('<div foo=\"bar\" j=\"2\" i=\"2\">inner</div>')\n\t\t\t);\n\n\t\t\t// update & flush\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.render).toHaveBeenCalledTimes(3);\n\n\t\t\texpect(Inner.prototype.render).toHaveBeenNthCalledWith(\n\t\t\t\t3,\n\t\t\t\t{ foo: 'bar', i: 3 },\n\t\t\t\t{},\n\t\t\t\t{}\n\t\t\t);\n\n\t\t\texpect(getAttributes(scratch.firstElementChild)).to.eql({\n\t\t\t\tj: '3',\n\t\t\t\ti: '3',\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\n\t\t\t// update & flush\n\t\t\talt = true;\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledOnce();\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div is-alt=\"true\"></div>');\n\n\t\t\t// update & flush\n\t\t\talt = false;\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\t\tsortAttributes('<div foo=\"bar\" j=\"4\" i=\"5\">inner</div>')\n\t\t\t);\n\t\t});\n\n\t\tit('should resolve intermediary functional component', () => {\n\t\t\tlet ctx = {};\n\t\t\tclass Root extends Component {\n\t\t\t\tgetChildContext() {\n\t\t\t\t\treturn { ctx };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Func />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst Func = () => <Inner />;\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>inner</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\t\trender(<Root />, scratch);\n\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\tInner.prototype.componentDidMount\n\t\t\t);\n\n\t\t\trender(<asdf />, scratch);\n\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should unmount children of high-order components without unmounting parent', () => {\n\t\t\tlet outer,\n\t\t\t\tinner2,\n\t\t\t\tcounter = 0;\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\touter = this;\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tchild: this.props.child\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\trender(_, { child: C }) {\n\t\t\t\t\treturn <C />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Outer.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Outer.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Outer.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Outer.prototype, 'render');\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn h('element' + ++counter);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\t\tclass Inner2 extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tinner2 = this;\n\t\t\t\t}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn h('element' + ++counter);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner2.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Inner2.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Inner2.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Inner2.prototype, 'render');\n\n\t\t\trender(<Outer child={Inner} />, scratch);\n\n\t\t\t// outer should only have been mounted once\n\t\t\texpect(Outer.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Outer.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Outer.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\t// inner should only have been mounted once\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\touter.setState({ child: Inner2 });\n\t\t\touter.forceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(Inner2.prototype.render).toHaveBeenCalledOnce();\n\n\t\t\t// outer should still only have been mounted once\n\t\t\texpect(Outer.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Outer.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Outer.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\t// inner should only have been mounted once\n\t\t\texpect(Inner2.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner2.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner2.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\tinner2.forceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(Inner2.prototype.render).toHaveBeenCalledTimes(2);\n\t\t\texpect(Inner2.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner2.prototype.componentDidMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner2.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\t\t});\n\n\t\tit('should remount when swapping between HOC child types', () => {\n\t\t\tclass Outer extends Component {\n\t\t\t\trender({ child: Child }) {\n\t\t\t\t\treturn <Child />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div class=\"inner\">foo</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\t\tconst InnerFunc = () => <div class=\"inner-func\">bar</div>;\n\n\t\t\trender(<Outer child={Inner} />, scratch);\n\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\n\t\t\tInner.prototype.componentWillMount.mockReset();\n\t\t\trender(<Outer child={InnerFunc} />, scratch);\n\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledTimes(0);\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledOnce();\n\n\t\t\tInner.prototype.componentWillUnmount.mockReset();\n\t\t\trender(<Outer child={Inner} />, scratch);\n\n\t\t\texpect(Inner.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(Inner.prototype.componentWillUnmount).toHaveBeenCalledTimes(0);\n\t\t});\n\t});\n\n\tdescribe('Component Nesting', () => {\n\t\tlet useIntermediary = false;\n\n\t\tlet createComponent = Intermediary => {\n\t\t\tclass C extends Component {\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\trender({ children }) {\n\t\t\t\t\tif (!useIntermediary) return children;\n\t\t\t\t\tlet I = useIntermediary === true ? Intermediary : useIntermediary;\n\t\t\t\t\treturn <I>{children}</I>;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(C.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(C.prototype, 'render');\n\t\t\treturn C;\n\t\t};\n\n\t\tlet createFunction = () => vi.fn(({ children }) => children);\n\n\t\tlet F1 = createFunction();\n\t\tlet F2 = createFunction();\n\t\tlet F3 = createFunction();\n\n\t\tlet C1 = createComponent(F1);\n\t\tlet C2 = createComponent(F2);\n\t\tlet C3 = createComponent(F3);\n\n\t\tlet reset = () =>\n\t\t\t[C1, C2, C3]\n\t\t\t\t.reduce(\n\t\t\t\t\t(acc, c) =>\n\t\t\t\t\t\tacc.concat(c.prototype.render, c.prototype.componentWillMount),\n\t\t\t\t\t[F1, F2, F3]\n\t\t\t\t)\n\t\t\t\t.forEach(c => c.mockReset());\n\n\t\tit('should handle lifecycle for no intermediary in component tree', () => {\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>\n\t\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t\t</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(C1.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(C2.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(C3.prototype.componentWillMount).toHaveBeenCalledOnce();\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>Some Text</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(C1.prototype.componentWillMount).toHaveBeenCalledTimes(0);\n\t\t\texpect(C2.prototype.componentWillMount).toHaveBeenCalledTimes(0);\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(C1.prototype.componentWillMount).toHaveBeenCalledTimes(0);\n\t\t\texpect(C3.prototype.componentWillMount).toHaveBeenCalledOnce();\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>\n\t\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t\t</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(C1.prototype.componentWillMount).toHaveBeenCalledTimes(0);\n\t\t\texpect(C2.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t\texpect(C3.prototype.componentWillMount).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should handle lifecycle for nested intermediary functional components', () => {\n\t\t\tuseIntermediary = true;\n\n\t\t\trender(<div />, scratch);\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>\n\t\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t\t</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'initial mount w/ intermediary fn, C1'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t\texpect(\n\t\t\t\tC2.prototype.componentWillMount,\n\t\t\t\t'initial mount w/ intermediary fn, C2'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t\texpect(\n\t\t\t\tC3.prototype.componentWillMount,\n\t\t\t\t'initial mount w/ intermediary fn, C3'\n\t\t\t).toHaveBeenCalledOnce();\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>Some Text</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'unmount innermost w/ intermediary fn, C1'\n\t\t\t).toHaveBeenCalledTimes(0);\n\t\t\texpect(\n\t\t\t\tC2.prototype.componentWillMount,\n\t\t\t\t'unmount innermost w/ intermediary fn, C2'\n\t\t\t).toHaveBeenCalledTimes(0);\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'swap innermost w/ intermediary fn'\n\t\t\t).toHaveBeenCalledTimes(0);\n\t\t\texpect(\n\t\t\t\tC3.prototype.componentWillMount,\n\t\t\t\t'swap innermost w/ intermediary fn'\n\t\t\t).toHaveBeenCalledOnce();\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>\n\t\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t\t</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'inject between, C1 w/ intermediary fn'\n\t\t\t).toHaveBeenCalledTimes(0);\n\t\t\texpect(\n\t\t\t\tC2.prototype.componentWillMount,\n\t\t\t\t'inject between, C2 w/ intermediary fn'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t\texpect(\n\t\t\t\tC3.prototype.componentWillMount,\n\t\t\t\t'inject between, C3 w/ intermediary fn'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should render components by depth', () => {\n\t\t\tlet spy = vi.fn();\n\t\t\tlet update;\n\t\t\tclass Child extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tupdate = () => {\n\t\t\t\t\t\tthis.props.update();\n\t\t\t\t\t\tthis.setState({});\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tspy();\n\t\t\t\t\tlet items = [];\n\t\t\t\t\tfor (let i = 0; i < this.props.items; i++) items.push(i);\n\t\t\t\t\treturn <div>{items.join(',')}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet i = 0;\n\t\t\tclass Parent extends Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <Child items={++i} update={() => this.setState({})} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Parent />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\n\t\t\tupdate();\n\t\t\trerender();\n\t\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\t});\n\n\t\tit('should handle lifecycle for nested intermediary elements', () => {\n\t\t\tuseIntermediary = 'div';\n\n\t\t\trender(<div />, scratch);\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>\n\t\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t\t</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'initial mount w/ intermediary div, C1'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t\texpect(\n\t\t\t\tC2.prototype.componentWillMount,\n\t\t\t\t'initial mount w/ intermediary div, C2'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t\texpect(\n\t\t\t\tC3.prototype.componentWillMount,\n\t\t\t\t'initial mount w/ intermediary div, C3'\n\t\t\t).toHaveBeenCalledOnce();\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>Some Text</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'unmount innermost w/ intermediary div, C1'\n\t\t\t).toHaveBeenCalledTimes(0);\n\t\t\texpect(\n\t\t\t\tC2.prototype.componentWillMount,\n\t\t\t\t'unmount innermost w/ intermediary div, C2'\n\t\t\t).toHaveBeenCalledTimes(0);\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'swap innermost w/ intermediary div'\n\t\t\t).toHaveBeenCalledTimes(0);\n\t\t\texpect(\n\t\t\t\tC3.prototype.componentWillMount,\n\t\t\t\t'swap innermost w/ intermediary div'\n\t\t\t).toHaveBeenCalledOnce();\n\n\t\t\treset();\n\t\t\trender(\n\t\t\t\t<C1>\n\t\t\t\t\t<C2>\n\t\t\t\t\t\t<C3>Some Text</C3>\n\t\t\t\t\t</C2>\n\t\t\t\t</C1>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(\n\t\t\t\tC1.prototype.componentWillMount,\n\t\t\t\t'inject between, C1 w/ intermediary div'\n\t\t\t).toHaveBeenCalledTimes(0);\n\t\t\texpect(\n\t\t\t\tC2.prototype.componentWillMount,\n\t\t\t\t'inject between, C2 w/ intermediary div'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t\texpect(\n\t\t\t\tC3.prototype.componentWillMount,\n\t\t\t\t'inject between, C3 w/ intermediary div'\n\t\t\t).toHaveBeenCalledOnce();\n\t\t});\n\t});\n\n\tit('should set component._vnode._dom when sCU returns false', () => {\n\t\tlet parent;\n\t\tclass Parent extends Component {\n\t\t\trender() {\n\t\t\t\tparent = this;\n\t\t\t\treturn <Child />;\n\t\t\t}\n\t\t}\n\n\t\tlet renderChildDiv = false;\n\n\t\tlet child;\n\t\tclass Child extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tchild = this;\n\t\t\t\tif (!renderChildDiv) return null;\n\t\t\t\treturn <div class=\"child\" />;\n\t\t\t}\n\t\t}\n\n\t\tlet app;\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\tapp = this;\n\t\t\t\treturn <Parent />;\n\t\t\t}\n\t\t}\n\n\t\t// TODO: Consider rewriting test to not rely on internal properties\n\t\t// and instead capture user-facing bug that would occur if this\n\t\t// behavior were broken\n\t\tconst getDom = c => ('__v' in c ? c.__v.__e : c._vnode._dom);\n\n\t\trender(<App />, scratch);\n\t\texpect(getDom(child)).to.equalNode(scratch.querySelector('.child'));\n\n\t\tapp.forceUpdate();\n\t\texpect(getDom(child)).to.equalNode(scratch.querySelector('.child'));\n\n\t\tparent.setState({});\n\t\trenderChildDiv = true;\n\t\tchild.forceUpdate();\n\t\texpect(getDom(child)).to.equalNode(scratch.querySelector('.child'));\n\t\trerender();\n\n\t\texpect(getDom(child)).to.equalNode(scratch.querySelector('.child'));\n\n\t\trenderChildDiv = false;\n\t\tapp.setState({});\n\t\tchild.forceUpdate();\n\t\trerender();\n\t\texpect(getDom(child)).to.equalNode(scratch.querySelector('.child'));\n\t});\n\n\t// preact/#1323\n\tit('should handle hoisted component vnodes without DOM', () => {\n\t\tlet x = 0;\n\t\tlet mounted = '';\n\t\tlet unmounted = '';\n\t\tlet updateAppState;\n\n\t\tclass X extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.name = `${x++}`;\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\tmounted += `,${this.name}`;\n\t\t\t}\n\n\t\t\tcomponentWillUnmount() {\n\t\t\t\tunmounted += `,${this.name}`;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\t// Statically create X element\n\t\tconst A = <X />;\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t\tupdateAppState = () => this.setState({ i: this.state.i + 1 });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div key={this.state.i}>\n\t\t\t\t\t\t{A}\n\t\t\t\t\t\t{A}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tupdateAppState();\n\t\trerender();\n\t\tupdateAppState();\n\t\trerender();\n\n\t\texpect(mounted).to.equal(',0,1,2,3,4,5');\n\t\texpect(unmounted).to.equal(',0,1,2,3');\n\t});\n\n\tit('should ignore invalid vnodes in children array', () => {\n\t\t/** @type { (() => void)} */\n\t\tlet update;\n\n\t\tconst obj = { a: 10, b: 'hello' };\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t\tupdate = () => this.setState({ i: this.state.i + 1 });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <p>{obj}</p>;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tupdate();\n\t\texpect(() => rerender()).not.to.throw();\n\t});\n\n\tdescribe('setState', () => {\n\t\tit('should not error if called on an unmounted component', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet increment;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { count: 0 };\n\t\t\t\t\tincrement = () => this.setState({ count: this.state.count + 1 });\n\t\t\t\t}\n\t\t\t\trender(props, state) {\n\t\t\t\t\treturn <div>{state.count}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>0</div>');\n\n\t\t\tincrement();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\n\t\t\trender(null, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\t\texpect(() => increment()).to.not.throw();\n\t\t\texpect(() => rerender()).to.not.throw();\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\t\t});\n\n\t\tit('setState callbacks should have latest state, even when called in render', () => {\n\t\t\tlet callbackState;\n\t\t\tlet i = 0;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { foo: 'bar' };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\t// So we don't get infinite loop\n\t\t\t\t\tif (i++ === 0) {\n\t\t\t\t\t\tthis.setState({ foo: 'baz' }, () => {\n\t\t\t\t\t\t\tcallbackState = this.state;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn String(this.state.foo);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('bar');\n\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('baz');\n\t\t\texpect(callbackState).to.deep.equal({ foo: 'baz' });\n\t\t});\n\n\t\t// #2716\n\t\tit('should work with readonly state', () => {\n\t\t\tlet update;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { foo: 'bar' };\n\t\t\t\t\tupdate = () =>\n\t\t\t\t\t\tthis.setState(prev => {\n\t\t\t\t\t\t\tObject.defineProperty(prev, 'foo', {\n\t\t\t\t\t\t\t\twritable: false\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\treturn prev;\n\t\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(() => {\n\t\t\t\tupdate();\n\t\t\t\trerender();\n\t\t\t}).to.not.throw();\n\t\t});\n\t});\n\n\tdescribe('forceUpdate', () => {\n\t\tit('should not error if called on an unmounted component', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet forceUpdate;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tforceUpdate = () => this.forceUpdate();\n\t\t\t\t}\n\t\t\t\trender(props, state) {\n\t\t\t\t\treturn <div>Hello</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\t\trender(null, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\t\texpect(() => forceUpdate()).to.not.throw();\n\t\t\texpect(() => rerender()).to.not.throw();\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\t\t});\n\n\t\tit('should update old dom on forceUpdate in a lifecycle', () => {\n\t\t\tlet i = 0;\n\t\t\tclass App extends Component {\n\t\t\t\tcomponentWillReceiveProps() {\n\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tif (i++ == 0) return <div>foo</div>;\n\t\t\t\t\treturn <div>bar</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\trender(<App />, scratch);\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div>bar</div>');\n\t\t});\n\n\t\tit('should skip shouldComponentUpdate when called during render', () => {\n\t\t\tlet isSCUCalled = false;\n\t\t\tclass App extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\tisSCUCalled = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tconst isUpdated = this.isUpdated;\n\t\t\t\t\tif (!isUpdated) {\n\t\t\t\t\t\tthis.isUpdated = true;\n\t\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t\t}\n\t\t\t\t\treturn <div>Updated: {isUpdated ? 'yes' : 'no'}</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t\trender(<App />, scratch);\n\t\t\trerender();\n\t\t\texpect(isSCUCalled).to.be.false;\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Updated: yes</div>');\n\t\t});\n\n\t\tit('should break through strict equality optimization', () => {\n\t\t\tlet isSCUCalled = false;\n\n\t\t\tclass Child extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tthis.props.parent.forceUpdate();\n\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t\tthis.isUpdated = true;\n\t\t\t\t}\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\tisSCUCalled = true;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>Updated: {this.isUpdated ? 'yes' : 'no'}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass App extends Component {\n\t\t\t\tchildren = <Child parent={this} />;\n\t\t\t\trender() {\n\t\t\t\t\treturn this.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\trerender();\n\t\t\texpect(isSCUCalled).to.be.false;\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Updated: yes</div>');\n\t\t});\n\t});\n\n\tit('should reset the rerender queue if rendering throws', () => {\n\t\tlet shouldThrow = false;\n\t\tlet increment;\n\t\tlet debounceCount = 0;\n\t\tlet flush;\n\n\t\t// Use a custom debounceRendering so we can track whether\n\t\t// enqueueRender actually schedules a new process() call.\n\t\tconst prevDebounce = options.debounceRendering;\n\t\toptions.debounceRendering = cb => {\n\t\t\tdebounceCount++;\n\t\t\tflush = cb;\n\t\t};\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { count: 0 };\n\t\t\t\tincrement = () => this.setState(s => ({ count: s.count + 1 }));\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\tif (shouldThrow) throw new Error('test error');\n\t\t\t\treturn <div>{state.count}</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>0</div>');\n\n\t\t// First setState to sync prevDebounce inside enqueueRender\n\t\tincrement();\n\t\texpect(debounceCount).to.equal(1);\n\t\tflush();\n\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\n\t\t// Trigger a rerender that will throw\n\t\tdebounceCount = 0;\n\t\tshouldThrow = true;\n\t\tincrement();\n\t\texpect(debounceCount).to.equal(1);\n\t\texpect(() => flush()).to.throw();\n\n\t\t// After the error, a subsequent setState must schedule a new\n\t\t// process() via debounceRendering. Without the fix,\n\t\t// _rerenderCount stays non-zero and enqueueRender won't\n\t\t// call debounceRendering, leaving the component stuck.\n\t\tdebounceCount = 0;\n\t\tshouldThrow = false;\n\t\tincrement();\n\t\texpect(debounceCount).to.equal(1);\n\n\t\tflush();\n\t\texpect(scratch.innerHTML).to.equal('<div>3</div>');\n\n\t\toptions.debounceRendering = prevDebounce;\n\t});\n});\n"
  },
  {
    "path": "test/browser/context.test.jsx",
    "content": "import { createElement, render, Component, Fragment } from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('context', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should pass context to grandchildren', () => {\n\t\tconst CONTEXT = { a: 'a' };\n\t\tconst PROPS = { b: 'b' };\n\t\t// let inner;\n\n\t\tclass Outer extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn CONTEXT;\n\t\t\t}\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Inner {...props} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tvi.spyOn(Outer.prototype, 'getChildContext');\n\n\t\tclass Inner extends Component {\n\t\t\t// constructor() {\n\t\t\t// \tsuper();\n\t\t\t// \tinner = this;\n\t\t\t// }\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcomponentWillReceiveProps() {}\n\t\t\tcomponentWillUpdate() {}\n\t\t\tcomponentDidUpdate() {}\n\t\t\trender(props, state, context) {\n\t\t\t\treturn <div>{context && context.a}</div>;\n\t\t\t}\n\t\t}\n\t\tvi.spyOn(Inner.prototype, 'shouldComponentUpdate');\n\t\tvi.spyOn(Inner.prototype, 'componentWillReceiveProps');\n\t\tvi.spyOn(Inner.prototype, 'componentWillUpdate');\n\t\tvi.spyOn(Inner.prototype, 'componentDidUpdate');\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(<Outer />, scratch);\n\n\t\texpect(Outer.prototype.getChildContext).toHaveBeenCalledTimes(1);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith({}, {}, CONTEXT);\n\n\t\tCONTEXT.foo = 'bar';\n\t\trender(<Outer {...PROPS} />, scratch);\n\n\t\texpect(Outer.prototype.getChildContext).toHaveBeenCalledTimes(2);\n\n\t\texpect(Inner.prototype.shouldComponentUpdate).toHaveBeenCalledTimes(1);\n\t\texpect(Inner.prototype.shouldComponentUpdate).toHaveBeenCalledWith(\n\t\t\tPROPS,\n\t\t\t{},\n\t\t\tCONTEXT\n\t\t);\n\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalledWith(\n\t\t\tPROPS,\n\t\t\tCONTEXT\n\t\t);\n\t\texpect(Inner.prototype.componentWillUpdate).toHaveBeenCalledWith(\n\t\t\tPROPS,\n\t\t\t{},\n\t\t\tCONTEXT\n\t\t);\n\t\texpect(Inner.prototype.componentDidUpdate).toHaveBeenCalledWith(\n\t\t\t{},\n\t\t\t{},\n\t\t\tundefined\n\t\t);\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(PROPS, {}, CONTEXT);\n\n\t\t/* Future:\n\t\t *  Newly created context objects are *not* currently cloned.\n\t\t *  This test checks that they *are* cloned.\n\t\t */\n\t\t// Inner.prototype.render.resetHistory();\n\t\t// CONTEXT.foo = 'baz';\n\t\t// inner.forceUpdate();\n\t\t// expect(Inner.prototype.render).to.have.been.calledWith(PROPS, {}, { a:'a', foo:'bar' });\n\t});\n\n\tit('should pass context to direct children', () => {\n\t\tconst CONTEXT = { a: 'a' };\n\t\tconst PROPS = { b: 'b' };\n\n\t\tclass Outer extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn CONTEXT;\n\t\t\t}\n\t\t\trender(props) {\n\t\t\t\treturn <Inner {...props} />;\n\t\t\t}\n\t\t}\n\t\tvi.spyOn(Outer.prototype, 'getChildContext');\n\n\t\tclass Inner extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tcomponentWillReceiveProps() {}\n\t\t\tcomponentWillUpdate() {}\n\t\t\tcomponentDidUpdate() {}\n\t\t\trender(props, state, context) {\n\t\t\t\treturn <div>{context && context.a}</div>;\n\t\t\t}\n\t\t}\n\t\tvi.spyOn(Inner.prototype, 'shouldComponentUpdate');\n\t\tvi.spyOn(Inner.prototype, 'componentWillReceiveProps');\n\t\tvi.spyOn(Inner.prototype, 'componentWillUpdate');\n\t\tvi.spyOn(Inner.prototype, 'componentDidUpdate');\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(<Outer />, scratch);\n\n\t\texpect(Outer.prototype.getChildContext).toHaveBeenCalledTimes(1);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith({}, {}, CONTEXT);\n\n\t\tCONTEXT.foo = 'bar';\n\t\trender(<Outer {...PROPS} />, scratch);\n\n\t\texpect(Outer.prototype.getChildContext).toHaveBeenCalledTimes(2);\n\n\t\texpect(Inner.prototype.shouldComponentUpdate).toHaveBeenCalledTimes(1);\n\t\texpect(Inner.prototype.shouldComponentUpdate).toHaveBeenCalledWith(\n\t\t\tPROPS,\n\t\t\t{},\n\t\t\tCONTEXT\n\t\t);\n\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalledWith(\n\t\t\tPROPS,\n\t\t\tCONTEXT\n\t\t);\n\t\texpect(Inner.prototype.componentWillUpdate).toHaveBeenCalledWith(\n\t\t\tPROPS,\n\t\t\t{},\n\t\t\tCONTEXT\n\t\t);\n\t\texpect(Inner.prototype.componentDidUpdate).toHaveBeenCalledWith(\n\t\t\t{},\n\t\t\t{},\n\t\t\tundefined\n\t\t);\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(PROPS, {}, CONTEXT);\n\n\t\t// make sure render() could make use of context.a\n\t\texpect(Inner.prototype.render).toHaveReturned(\n\t\t\texpect.objectContaining({ props: { children: 'a' } })\n\t\t);\n\t});\n\n\tit('should preserve existing context properties when creating child contexts', () => {\n\t\tlet outerContext = { outer: true },\n\t\t\tinnerContext = { inner: true };\n\t\tclass Outer extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn { outerContext };\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Inner />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass Inner extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn { innerContext };\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <InnerMost />;\n\t\t\t}\n\t\t}\n\n\t\tclass InnerMost extends Component {\n\t\t\trender() {\n\t\t\t\treturn <strong>test</strong>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\t\tvi.spyOn(InnerMost.prototype, 'render');\n\n\t\trender(<Outer />, scratch);\n\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\t{},\n\t\t\t{},\n\t\t\t{ outerContext }\n\t\t);\n\t\texpect(InnerMost.prototype.render).toHaveBeenCalledWith(\n\t\t\t{},\n\t\t\t{},\n\t\t\t{ outerContext, innerContext }\n\t\t);\n\t});\n\n\tit('should pass context through Fragments', () => {\n\t\tconst context = { foo: 'bar' };\n\n\t\tconst Foo = vi.fn(() => <div />);\n\n\t\tclass Wrapper extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn context;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t\t<Foo />\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Wrapper />, scratch);\n\t\texpect(Foo.mock.calls[0][1]).to.deep.equal(context);\n\t});\n});\n"
  },
  {
    "path": "test/browser/createContext.test.jsx",
    "content": "import { setupRerender, act } from 'preact/test-utils';\nimport {\n\tcreateElement,\n\trender,\n\tComponent,\n\tcreateContext,\n\tFragment\n} from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('createContext', () => {\n\tlet scratch;\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should pass context to a consumer', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\n\t\tlet receivedContext;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.a}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<div>\n\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t{data => {\n\t\t\t\t\t\t\treceivedContext = data;\n\t\t\t\t\t\t\treturn <Inner {...data} />;\n\t\t\t\t\t\t}}\n\t\t\t\t\t</Consumer>\n\t\t\t\t</div>\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\tCONTEXT,\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedContext).to.equal(CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>a</div></div>');\n\t});\n\n\tit('should pass context to a consumer (non-provider)', () => {\n\t\tconst Ctx = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\n\t\tlet receivedContext;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.a}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<Ctx value={CONTEXT}>\n\t\t\t\t<div>\n\t\t\t\t\t<Ctx.Consumer>\n\t\t\t\t\t\t{data => {\n\t\t\t\t\t\t\treceivedContext = data;\n\t\t\t\t\t\t\treturn <Inner {...data} />;\n\t\t\t\t\t\t}}\n\t\t\t\t\t</Ctx.Consumer>\n\t\t\t\t</div>\n\t\t\t</Ctx>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\tCONTEXT,\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedContext).to.equal(CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>a</div></div>');\n\t});\n\n\t// This optimization helps\n\t// to prevent a Provider from rerendering the children, this means\n\t// we only propagate to children.\n\t// Strict equal vnode optimization\n\tit('skips referentially equal children to Provider', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tlet set,\n\t\t\trenders = 0;\n\t\tconst Layout = ({ children }) => {\n\t\t\trenders++;\n\t\t\treturn children;\n\t\t};\n\t\tclass State extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tconst { children } = this.props;\n\t\t\t\treturn <Provider value={this.state}>{children}</Provider>;\n\t\t\t}\n\t\t}\n\t\tconst App = () => (\n\t\t\t<State>\n\t\t\t\t<Layout>\n\t\t\t\t\t<Consumer>{({ i }) => <p>{i}</p>}</Consumer>\n\t\t\t\t</Layout>\n\t\t\t</State>\n\t\t);\n\t\trender(<App />, scratch);\n\t\texpect(renders).to.equal(1);\n\t\tset({ i: 2 });\n\t\trerender();\n\t\texpect(renders).to.equal(1);\n\t});\n\n\tit('skips referentially equal children to Provider w/ dom-node in between', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tlet set,\n\t\t\trenders = 0;\n\t\tconst Layout = ({ children }) => {\n\t\t\trenders++;\n\t\t\treturn children;\n\t\t};\n\t\tclass State extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tconst { children } = this.props;\n\t\t\t\treturn <Provider value={this.state}>{children}</Provider>;\n\t\t\t}\n\t\t}\n\t\tconst App = () => (\n\t\t\t<State>\n\t\t\t\t<div>\n\t\t\t\t\t<Layout>\n\t\t\t\t\t\t<Consumer>{({ i }) => <p>{i}</p>}</Consumer>\n\t\t\t\t\t</Layout>\n\t\t\t\t</div>\n\t\t\t</State>\n\t\t);\n\t\trender(<App />, scratch);\n\t\texpect(renders).to.equal(1);\n\t\tset({ i: 2 });\n\t\trerender();\n\t\texpect(renders).to.equal(1);\n\t});\n\n\tit('should preserve provider context through nesting providers', done => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\t\tconst CHILD_CONTEXT = { b: 'b' };\n\n\t\tlet parentContext, childContext;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{props.a} - {props.b}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<Consumer>\n\t\t\t\t\t{data => {\n\t\t\t\t\t\tparentContext = data;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Provider value={CHILD_CONTEXT}>\n\t\t\t\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t\t\t\t{childData => {\n\t\t\t\t\t\t\t\t\t\tchildContext = childData;\n\t\t\t\t\t\t\t\t\t\treturn <Inner {...data} {...childData} />;\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t</Consumer>\n\t\t\t\t\t\t\t</Provider>\n\t\t\t\t\t\t);\n\t\t\t\t\t}}\n\t\t\t\t</Consumer>\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\t{\n\t\t\t\t...CONTEXT,\n\t\t\t\t...CHILD_CONTEXT\n\t\t\t},\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(Inner.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(parentContext).to.equal(CONTEXT);\n\t\texpect(childContext).to.equal(CHILD_CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal('<div>a - b</div>');\n\t\treturn new Promise(resolve => {\n\t\t\tsetTimeout(() => {\n\t\t\t\texpect(Inner.prototype.render).toHaveBeenCalledOnce();\n\t\t\t\tresolve();\n\t\t\t}, 0);\n\t\t});\n\t});\n\n\tit('should preserve provider context between different providers', () => {\n\t\tconst { Provider: ThemeProvider, Consumer: ThemeConsumer } =\n\t\t\tcreateContext(null);\n\t\tconst { Provider: DataProvider, Consumer: DataConsumer } =\n\t\t\tcreateContext(null);\n\t\tconst THEME_CONTEXT = { theme: 'black' };\n\t\tconst DATA_CONTEXT = { global: 'a' };\n\n\t\tlet receivedTheme;\n\t\tlet receivedData;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{props.theme} - {props.global}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<ThemeProvider value={THEME_CONTEXT.theme}>\n\t\t\t\t<DataProvider value={DATA_CONTEXT}>\n\t\t\t\t\t<ThemeConsumer>\n\t\t\t\t\t\t{theme => {\n\t\t\t\t\t\t\treceivedTheme = theme;\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<DataConsumer>\n\t\t\t\t\t\t\t\t\t{data => {\n\t\t\t\t\t\t\t\t\t\treceivedData = data;\n\t\t\t\t\t\t\t\t\t\treturn <Inner theme={theme} {...data} />;\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t</DataConsumer>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}}\n\t\t\t\t\t</ThemeConsumer>\n\t\t\t\t</DataProvider>\n\t\t\t</ThemeProvider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\t{\n\t\t\t\t...THEME_CONTEXT,\n\t\t\t\t...DATA_CONTEXT\n\t\t\t},\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedTheme).to.equal(THEME_CONTEXT.theme);\n\t\texpect(receivedData).to.equal(DATA_CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal('<div>black - a</div>');\n\t});\n\n\tit('should preserve provider context through nesting consumers', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\n\t\tlet receivedData;\n\t\tlet receivedChildData;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.a}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<Consumer>\n\t\t\t\t\t{data => {\n\t\t\t\t\t\treceivedData = data;\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t\t\t{childData => {\n\t\t\t\t\t\t\t\t\treceivedChildData = childData;\n\t\t\t\t\t\t\t\t\treturn <Inner {...data} {...childData} />;\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t</Consumer>\n\t\t\t\t\t\t);\n\t\t\t\t\t}}\n\t\t\t\t</Consumer>\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\t{ ...CONTEXT },\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedData).to.equal(CONTEXT);\n\t\texpect(receivedChildData).to.equal(CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal('<div>a</div>');\n\t});\n\n\tit('should not emit when value does not update', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\n\t\tclass NoUpdate extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.a}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t\t<NoUpdate>\n\t\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t\t</NoUpdate>\n\t\t\t\t</Provider>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(Inner.prototype.render).toHaveBeenCalledTimes(1);\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t\t<NoUpdate>\n\t\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t\t</NoUpdate>\n\t\t\t\t</Provider>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(Inner.prototype.render).toHaveBeenCalledTimes(1);\n\t});\n\n\tit('should preserve provider context through nested components', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\n\t\tlet receivedContext;\n\n\t\tclass Consumed extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <strong>{props.a}</strong>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Consumed.prototype, 'render');\n\n\t\tclass Outer extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Inner />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass Inner extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<InnerMost />\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass InnerMost extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t\t{data => {\n\t\t\t\t\t\t\t\treceivedContext = data;\n\t\t\t\t\t\t\t\treturn <Consumed {...data} />;\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t</Consumer>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<Outer />\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Consumed.prototype.render).toHaveBeenCalledWith(\n\t\t\t{\n\t\t\t\t...CONTEXT\n\t\t\t},\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedContext).to.equal(CONTEXT);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div><strong>a</strong></div></div>'\n\t\t);\n\t});\n\n\tit('should propagates through shouldComponentUpdate false', async () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { a: 'a' };\n\t\tconst UPDATED_CONTEXT = { a: 'b' };\n\n\t\tclass Consumed extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <strong>{props.a}</strong>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Consumed.prototype, 'render');\n\n\t\tclass Outer extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Inner />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass Inner extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<InnerMost />\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass InnerMost extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Consumer>{data => <Consumed {...data} />}</Consumer>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={this.props.value}>\n\t\t\t\t\t\t<Outer />\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App value={CONTEXT} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div><strong>a</strong></div></div>'\n\t\t);\n\t\texpect(Consumed.prototype.render).toHaveBeenCalledTimes(1);\n\n\t\trender(<App value={UPDATED_CONTEXT} />, scratch);\n\n\t\trerender();\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Consumed.prototype.render).toHaveBeenCalledTimes(2);\n\t\t// expect(Consumed.prototype.render).to.have.been.calledWithMatch({ ...UPDATED_CONTEXT }, {}, { ['__cC' + (ctxId - 1)]: {} });\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div><strong>b</strong></div></div>'\n\t\t);\n\t\treturn new Promise(resolve => {\n\t\t\tsetTimeout(() => {\n\t\t\t\texpect(Consumed.prototype.render).toHaveBeenCalledTimes(2);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t});\n\n\tit('should keep the right context at the right \"depth\"', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { theme: 'a', global: 1 };\n\t\tconst NESTED_CONTEXT = { theme: 'b', global: 1 };\n\n\t\tlet receivedData;\n\t\tlet receivedNestedData;\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{props.theme} - {props.global}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tclass Nested extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{props.theme} - {props.global}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\t\tvi.spyOn(Nested.prototype, 'render');\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<Provider value={NESTED_CONTEXT}>\n\t\t\t\t\t<Consumer>\n\t\t\t\t\t\t{data => {\n\t\t\t\t\t\t\treceivedNestedData = data;\n\t\t\t\t\t\t\treturn <Nested {...data} />;\n\t\t\t\t\t\t}}\n\t\t\t\t\t</Consumer>\n\t\t\t\t</Provider>\n\t\t\t\t<Consumer>\n\t\t\t\t\t{data => {\n\t\t\t\t\t\treceivedData = data;\n\t\t\t\t\t\treturn <Inner {...data} />;\n\t\t\t\t\t}}\n\t\t\t\t</Consumer>\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// initial render does not invoke anything but render():\n\t\texpect(Nested.prototype.render).toHaveBeenCalledWith(\n\t\t\t{\n\t\t\t\t...NESTED_CONTEXT\n\t\t\t},\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\t{ ...CONTEXT },\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(receivedData).to.equal(CONTEXT);\n\t\texpect(receivedNestedData).to.equal(NESTED_CONTEXT);\n\n\t\texpect(scratch.innerHTML).to.equal('<div>b - 1</div><div>a - 1</div>');\n\t});\n\n\tit(\"should not re-render the consumer if the context doesn't change\", () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { i: 1 };\n\n\t\tclass NoUpdate extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.i}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<NoUpdate>\n\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t</NoUpdate>\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\trender(\n\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t<NoUpdate>\n\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t</NoUpdate>\n\t\t\t</Provider>,\n\t\t\tscratch\n\t\t);\n\n\t\t// Rendered twice, should called just one 'Consumer' render\n\t\texpect(Inner.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\tCONTEXT,\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<Provider value={{ i: 2 }}>\n\t\t\t\t\t<NoUpdate>\n\t\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t\t</NoUpdate>\n\t\t\t\t</Provider>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\t// Rendered three times, should call 'Consumer' render two times\n\t\texpect(Inner.prototype.render).toHaveBeenCalledTimes(2);\n\t\texpect(Inner.prototype.render).toHaveBeenCalledWith(\n\t\t\t{ i: 2 },\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<div>2</div>');\n\t});\n\n\tit('should allow for updates of props', () => {\n\t\tlet app;\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = {\n\t\t\t\t\tstatus: 'initial'\n\t\t\t\t};\n\n\t\t\t\tthis.renderInner = this.renderInner.bind(this);\n\n\t\t\t\tapp = this;\n\t\t\t}\n\n\t\t\trenderInner(value) {\n\t\t\t\treturn (\n\t\t\t\t\t<p>\n\t\t\t\t\t\t{value}: {this.state.status}\n\t\t\t\t\t</p>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value=\"value\">\n\t\t\t\t\t\t<Consumer>{this.renderInner}</Consumer>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tact(() => {\n\t\t\trender(<App />, scratch);\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.equal('<p>value: initial</p>');\n\n\t\tact(() => {\n\t\t\tapp.setState({ status: 'updated' });\n\t\t\trerender();\n\t\t});\n\n\t\texpect(scratch.innerHTML).to.equal('<p>value: updated</p>');\n\t});\n\n\tit('should re-render the consumer if the children change', () => {\n\t\tconst { Provider, Consumer } = createContext(null);\n\t\tconst CONTEXT = { i: 1 };\n\n\t\tclass Inner extends Component {\n\t\t\trender(props) {\n\t\t\t\treturn <div>{props.i}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Inner.prototype, 'render');\n\n\t\tact(() => {\n\t\t\trender(\n\t\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t</Provider>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\t// Not calling re-render since it's gonna get called with the same Consumer function\n\t\t\trender(\n\t\t\t\t<Provider value={CONTEXT}>\n\t\t\t\t\t<Consumer>{data => <Inner {...data} />}</Consumer>\n\t\t\t\t</Provider>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t});\n\n\t\t// Rendered twice, with two different children for consumer, should render twice\n\t\texpect(Inner.prototype.render).toHaveBeenCalledTimes(2);\n\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\t});\n\n\tit('should not rerender consumers that have been unmounted', () => {\n\t\tconst { Provider, Consumer } = createContext(0);\n\n\t\tconst Inner = vi.fn(props => <div>{props.value}</div>);\n\n\t\tlet toggleConsumer;\n\t\tlet changeValue;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\n\t\t\t\tthis.state = { value: 0, show: true };\n\t\t\t\tchangeValue = value => this.setState({ value });\n\t\t\t\ttoggleConsumer = () => this.setState(({ show }) => ({ show: !show }));\n\t\t\t}\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={state.value}>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{state.show\n\t\t\t\t\t\t\t\t? <Consumer>{data => <Inner value={data} />}</Consumer>\n\t\t\t\t\t\t\t\t: null}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>0</div></div>');\n\t\texpect(Inner).toHaveBeenCalledOnce();\n\n\t\tchangeValue(1);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><div>1</div></div>');\n\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\n\t\ttoggleConsumer();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\n\t\tchangeValue(2);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t\texpect(Inner).toHaveBeenCalledTimes(2);\n\t});\n\n\tdescribe('class.contextType', () => {\n\t\tit('should use default value', () => {\n\t\t\tconst ctx = createContext('foo');\n\n\t\t\tlet actual;\n\t\t\tclass App extends Component {\n\t\t\t\trender() {\n\t\t\t\t\tactual = this.context;\n\t\t\t\t\treturn <div>bar</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tApp.contextType = ctx;\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(actual).to.deep.equal('foo');\n\t\t});\n\n\t\tit('should use the value of the nearest Provider', () => {\n\t\t\tconst ctx = createContext('foo');\n\n\t\t\tlet actual;\n\t\t\tclass App extends Component {\n\t\t\t\trender() {\n\t\t\t\t\tactual = this.context;\n\t\t\t\t\treturn <div>bar</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tApp.contextType = ctx;\n\t\t\tconst Provider = ctx.Provider;\n\n\t\t\trender(\n\t\t\t\t<Provider value=\"bar\">\n\t\t\t\t\t<Provider value=\"bob\">\n\t\t\t\t\t\t<App />\n\t\t\t\t\t</Provider>\n\t\t\t\t</Provider>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(actual).to.deep.equal('bob');\n\t\t});\n\n\t\tit('should restore legacy context for children', () => {\n\t\t\tconst Foo = createContext('foo');\n\t\t\tconst spy = vi.fn();\n\n\t\t\tclass NewContext extends Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass OldContext extends Component {\n\t\t\t\tgetChildContext() {\n\t\t\t\t\treturn { foo: 'foo' };\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Inner extends Component {\n\t\t\t\trender() {\n\t\t\t\t\tspy(this.context);\n\t\t\t\t\treturn <div>Inner</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tNewContext.contextType = Foo;\n\n\t\t\trender(\n\t\t\t\t<Foo.Provider value=\"bar\">\n\t\t\t\t\t<OldContext>\n\t\t\t\t\t\t<NewContext>\n\t\t\t\t\t\t\t<Inner />\n\t\t\t\t\t\t</NewContext>\n\t\t\t\t\t</OldContext>\n\t\t\t\t</Foo.Provider>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(spy).toHaveBeenCalledWith(expect.objectContaining({ foo: 'foo' }));\n\t\t});\n\n\t\tit('should call componentWillUnmount', () => {\n\t\t\tlet Foo = createContext('foo');\n\t\t\tlet spy = vi.fn();\n\n\t\t\tlet instance;\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tinstance = this;\n\t\t\t\t}\n\n\t\t\t\tcomponentWillUnmount() {\n\t\t\t\t\tspy(this);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tApp.contextType = Foo;\n\n\t\t\trender(\n\t\t\t\t<Foo.Provider value=\"foo\">\n\t\t\t\t\t<App />\n\t\t\t\t</Foo.Provider>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\trender(null, scratch);\n\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(spy.mock.calls[0][0]).to.equal(instance);\n\t\t});\n\n\t\tit('should order updates correctly', () => {\n\t\t\tconst events = [];\n\t\t\tlet update;\n\t\t\tconst Store = createContext(null);\n\n\t\t\tclass Root extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { id: 0 };\n\t\t\t\t\tupdate = this.updateStore = this.updateStore.bind(this);\n\t\t\t\t}\n\n\t\t\t\tupdateStore() {\n\t\t\t\t\tthis.setState(state => ({ id: state.id + 1 }));\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Store.Provider value={this.state.id}>\n\t\t\t\t\t\t\t<App />\n\t\t\t\t\t\t</Store.Provider>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass App extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <Store.Consumer>{id => <Parent key={id} />}</Store.Consumer>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction Parent(props) {\n\t\t\t\treturn <Store.Consumer>{id => <Child id={id} />}</Store.Consumer>;\n\t\t\t}\n\n\t\t\tclass Child extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tevents.push('mount ' + this.props.id);\n\t\t\t\t}\n\n\t\t\t\tcomponentDidUpdate(prevProps) {\n\t\t\t\t\tevents.push('update ' + prevProps.id + ' to ' + this.props.id);\n\t\t\t\t}\n\n\t\t\t\tcomponentWillUnmount() {\n\t\t\t\t\tevents.push('unmount ' + this.props.id);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tevents.push('render ' + this.props.id);\n\t\t\t\t\treturn this.props.id;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Root />, scratch);\n\t\t\texpect(events).to.deep.equal(['render 0', 'mount 0']);\n\n\t\t\tupdate();\n\t\t\trerender();\n\t\t\texpect(events).to.deep.equal([\n\t\t\t\t'render 0',\n\t\t\t\t'mount 0',\n\t\t\t\t'unmount 0',\n\t\t\t\t'render 1',\n\t\t\t\t'mount 1'\n\t\t\t]);\n\t\t});\n\t});\n\n\tit('should rerender when reset to defaultValue', () => {\n\t\tconst defaultValue = { state: 'hi' };\n\t\tconst context = createContext(defaultValue);\n\t\tlet set;\n\n\t\tclass NoUpdate extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <context.Consumer>{v => <p>{v.state}</p>}</context.Consumer>;\n\t\t\t}\n\t\t}\n\n\t\tclass Provider extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = defaultValue;\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<context.Provider value={this.state}>\n\t\t\t\t\t\t<NoUpdate />\n\t\t\t\t\t</context.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Provider />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>hi</p>');\n\n\t\tset({ state: 'bye' });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>bye</p>');\n\n\t\tset(defaultValue);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>hi</p>');\n\t});\n\n\tit('should not call sCU on context update', () => {\n\t\tconst Ctx = createContext('foo');\n\n\t\t/** @type {(s: string) => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { foo: 'foo' };\n\t\t\t\tupdate = v => this.setState({ foo: v });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Ctx.Provider value={this.state.foo}>\n\t\t\t\t\t\t<Child />\n\t\t\t\t\t</Ctx.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst spy = vi.fn();\n\n\t\tclass Child extends Component {\n\t\t\tstatic contextType = Ctx;\n\n\t\t\tshouldComponentUpdate() {\n\t\t\t\tspy();\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <p>{this.context}</p>;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.textContent).to.equal('foo');\n\n\t\tupdate('bar');\n\t\trerender();\n\t\texpect(scratch.textContent).to.equal('bar');\n\t\texpect(spy).not.toHaveBeenCalled();\n\t});\n\n\tit('should pass context through strict equal children', () => {\n\t\tconst context = { foo: 'bar' };\n\t\tconst Ctx = createContext(null);\n\n\t\t/** @type {(s: { foo: string }) => void} */\n\t\tlet set;\n\t\tclass Wrapper extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = context;\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\n\t\t\tgetChildContext() {\n\t\t\t\treturn context;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Ctx.Provider value={this.state}>{this.props.children}</Ctx.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Wrapper>\n\t\t\t\t<Ctx.Consumer>{value => <p>{value.foo}</p>}</Ctx.Consumer>\n\t\t\t</Wrapper>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<p>bar</p>');\n\n\t\tset({ foo: 'baz' });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>baz</p>');\n\t});\n});\n"
  },
  {
    "path": "test/browser/customBuiltInElements.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { vi } from 'vitest';\n\nconst runSuite = typeof customElements == 'undefined' ? xdescribe : describe;\n\nrunSuite('customised built-in elements', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should create built in elements correctly', () => {\n\t\tclass Foo extends Component {\n\t\t\trender() {\n\t\t\t\treturn <div is=\"built-in\" />;\n\t\t\t}\n\t\t}\n\n\t\tconst spy = vi.fn();\n\n\t\tclass BuiltIn extends HTMLDivElement {\n\t\t\tconnectedCallback() {\n\t\t\t\tspy();\n\t\t\t}\n\t\t}\n\n\t\tcustomElements.define('built-in', BuiltIn, { extends: 'div' });\n\n\t\trender(<Foo />, scratch);\n\n\t\texpect(spy).toHaveBeenCalledTimes(1);\n\t});\n});\n"
  },
  {
    "path": "test/browser/events.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport {\n\tsetupScratch,\n\tteardown,\n\tsupportsPassiveEvents\n} from '../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('event handling', () => {\n\tlet scratch, proto;\n\n\tfunction fireEvent(on, type) {\n\t\tlet e = document.createEvent('Event');\n\t\te.initEvent(type, true, true);\n\t\ton.dispatchEvent(e);\n\t}\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\n\t\tproto = document.createElement('div').constructor.prototype;\n\n\t\tvi.spyOn(proto, 'addEventListener');\n\t\tvi.spyOn(proto, 'removeEventListener');\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\n\t\tproto.addEventListener.mockRestore();\n\t\tproto.removeEventListener.mockRestore();\n\t});\n\n\tit('should only register on* functions as handlers', () => {\n\t\tlet click = () => {},\n\t\t\tonclick = () => {};\n\n\t\trender(<div click={click} onClick={onclick} />, scratch);\n\n\t\texpect(scratch.childNodes[0].attributes.length).to.equal(0);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'click',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t});\n\n\tit('should only register truthy values as handlers', () => {\n\t\tfunction fooHandler() {}\n\t\tconst falsyHandler = false;\n\n\t\trender(<div onClick={falsyHandler} onOtherClick={fooHandler} />, scratch);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'otherclick',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\texpect(proto.addEventListener).not.toHaveBeenCalledWith(\n\t\t\t'Click',\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t\texpect(proto.addEventListener).not.toHaveBeenCalledWith(\n\t\t\t'click',\n\t\t\texpect.anything(),\n\t\t\texpect.anything()\n\t\t);\n\t});\n\n\tit('should support native event names', () => {\n\t\tlet click = vi.fn(),\n\t\t\tmousedown = vi.fn();\n\n\t\trender(<div onclick={() => click(1)} onmousedown={mousedown} />, scratch);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledTimes(2);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'click',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'mousedown',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tfireEvent(scratch.childNodes[0], 'click');\n\t\texpect(click).toHaveBeenCalledOnce();\n\t\texpect(click).toHaveBeenCalledWith(1);\n\t});\n\n\tit('should support camel-case event names', () => {\n\t\tlet click = vi.fn(),\n\t\t\tmousedown = vi.fn();\n\n\t\trender(<div onClick={() => click(1)} onMouseDown={mousedown} />, scratch);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledTimes(2);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'click',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'mousedown',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tfireEvent(scratch.childNodes[0], 'click');\n\t\texpect(click).toHaveBeenCalledOnce();\n\t\texpect(click).toHaveBeenCalledWith(1);\n\t});\n\n\tit('should update event handlers', () => {\n\t\tlet click1 = vi.fn();\n\t\tlet click2 = vi.fn();\n\n\t\trender(<div onClick={click1} />, scratch);\n\n\t\tfireEvent(scratch.childNodes[0], 'click');\n\t\texpect(click1).toHaveBeenCalledOnce();\n\t\texpect(click2).not.toHaveBeenCalled();\n\n\t\tclick1.mockClear();\n\t\tclick2.mockClear();\n\n\t\trender(<div onClick={click2} />, scratch);\n\n\t\tfireEvent(scratch.childNodes[0], 'click');\n\t\texpect(click1).not.toHaveBeenCalled();\n\t\texpect(click2).toHaveBeenCalled();\n\t});\n\n\tit('should remove event handlers', () => {\n\t\tlet click = vi.fn(),\n\t\t\tmousedown = vi.fn();\n\n\t\trender(<div onClick={() => click(1)} onMouseDown={mousedown} />, scratch);\n\t\trender(<div onClick={() => click(2)} />, scratch);\n\n\t\texpect(proto.removeEventListener).toHaveBeenCalledWith(\n\t\t\t'mousedown',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tfireEvent(scratch.childNodes[0], 'mousedown');\n\t\texpect(mousedown).not.toHaveBeenCalled();\n\n\t\tproto.removeEventListener.mockClear();\n\t\tclick.mockClear();\n\t\tmousedown.mockClear();\n\n\t\trender(<div />, scratch);\n\n\t\texpect(proto.removeEventListener).toHaveBeenCalledWith(\n\t\t\t'click',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tfireEvent(scratch.childNodes[0], 'click');\n\t\texpect(click).not.toHaveBeenCalled();\n\t});\n\n\tit('should register events not appearing on dom nodes', () => {\n\t\tlet onAnimationEnd = () => {};\n\n\t\trender(<div onanimationend={onAnimationEnd} />, scratch);\n\t\texpect(proto.addEventListener).toHaveBeenCalledOnce();\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'animationend',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t});\n\n\t// Skip test if browser doesn't support passive events\n\tif (supportsPassiveEvents()) {\n\t\tit('should use capturing for event props ending with *Capture', () => {\n\t\t\tlet click = vi.fn();\n\n\t\t\trender(\n\t\t\t\t<div onClickCapture={click}>\n\t\t\t\t\t<button type=\"button\">Click me</button>\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tlet btn = scratch.firstChild.firstElementChild;\n\t\t\tbtn.click();\n\n\t\t\texpect(click).toHaveBeenCalledOnce();\n\n\t\t\t// IE doesn't set it\n\t\t\tif (!/Edge/.test(navigator.userAgent)) {\n\t\t\t\texpect(click).toHaveBeenCalledWith(\n\t\t\t\t\texpect.objectContaining({ eventPhase: 0 })\n\t\t\t\t); // capturing\n\t\t\t}\n\t\t});\n\n\t\tit('should support both capturing and non-capturing events on the same element', () => {\n\t\t\tlet click = vi.fn(),\n\t\t\t\tclickCapture = vi.fn();\n\n\t\t\trender(\n\t\t\t\t<div onClick={click} onClickCapture={clickCapture}>\n\t\t\t\t\t<button />\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tlet root = scratch.firstChild;\n\t\t\troot.firstElementChild.click();\n\n\t\t\texpect(clickCapture).toHaveBeenCalledOnce();\n\t\t\texpect(click).toHaveBeenCalledOnce();\n\t\t});\n\t}\n\n\t// Uniquely named in that the base event names end with 'Capture'\n\tit('should support (got|lost)PointerCapture events', () => {\n\t\tlet gotPointerCapture = vi.fn(),\n\t\t\tgotPointerCaptureCapture = vi.fn(),\n\t\t\tlostPointerCapture = vi.fn(),\n\t\t\tlostPointerCaptureCapture = vi.fn();\n\n\t\trender(\n\t\t\t<div\n\t\t\t\tonGotPointerCapture={gotPointerCapture}\n\t\t\t\tonLostPointerCapture={lostPointerCapture}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledTimes(2);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'gotpointercapture',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'lostpointercapture',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\n\t\tproto.addEventListener.mockClear();\n\n\t\trender(\n\t\t\t<div\n\t\t\t\tonGotPointerCaptureCapture={gotPointerCaptureCapture}\n\t\t\t\tonLostPointerCaptureCapture={lostPointerCaptureCapture}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledTimes(2);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'gotpointercapture',\n\t\t\texpect.any(Function),\n\t\t\ttrue\n\t\t);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'lostpointercapture',\n\t\t\texpect.any(Function),\n\t\t\ttrue\n\t\t);\n\t});\n\n\tit('should support camel-case focus event names', () => {\n\t\trender(<div onFocusIn={() => {}} onFocusOut={() => {}} />, scratch);\n\n\t\texpect(proto.addEventListener).toHaveBeenCalledTimes(2);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'focusin',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t\texpect(proto.addEventListener).toHaveBeenCalledWith(\n\t\t\t'focusout',\n\t\t\texpect.any(Function),\n\t\t\tfalse\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/browser/focus.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component, Fragment, hydrate } from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { div, span, input as inputStr, h1, h2 } from '../_util/dom';\n\n/* eslint-disable react/jsx-boolean-value */\n\ndescribe('focus', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t/** @type {(newState: Partial<{ before: number[]; after: number[] }>) => void} */\n\tlet setState;\n\n\t/** @type {() => void} */\n\tlet prepend, append, shift, pop;\n\n\t/** @type {() => void} */\n\tlet getDynamicListHtml;\n\n\tclass DynamicList extends Component {\n\t\tconstructor(props) {\n\t\t\tsuper(props);\n\t\t\tthis.state = {\n\t\t\t\tbefore: props.initialBefore || [],\n\t\t\t\tafter: props.initialAfter || []\n\t\t\t};\n\n\t\t\tsetState = newState => this.setState(newState);\n\n\t\t\tprepend = () => {\n\t\t\t\tconst before = this.state.before;\n\t\t\t\tconst newValue = before[0] ? before[0] - 1 : 1;\n\t\t\t\tthis.setState({\n\t\t\t\t\tbefore: [newValue, ...before]\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tappend = () => {\n\t\t\t\tconst after = this.state.after;\n\t\t\t\tconst lastValue = after[after.length - 1];\n\t\t\t\tconst newValue = lastValue ? lastValue + 1 : 2;\n\t\t\t\tthis.setState({\n\t\t\t\t\tafter: [...after, newValue]\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tshift = () => {\n\t\t\t\tthis.setState({\n\t\t\t\t\tbefore: this.state.before.slice(1)\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tpop = () => {\n\t\t\t\tthis.setState({\n\t\t\t\t\tafter: this.state.after.slice(0, -1)\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tgetDynamicListHtml = () => {\n\t\t\t\tconst liHtml = this.props.as == Input ? inputStr : span;\n\t\t\t\treturn div([\n\t\t\t\t\t...this.state.before.map(liHtml),\n\t\t\t\t\t'<input id=\"input-0\" type=\"text\">',\n\t\t\t\t\t...this.state.after.map(liHtml)\n\t\t\t\t]);\n\t\t\t};\n\t\t}\n\n\t\trender(props, state) {\n\t\t\tconst ListComponent = props.as || ListItem;\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t{state.before.map(value => (\n\t\t\t\t\t\t<ListComponent key={props.unkeyed ? undefined : value}>\n\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t</ListComponent>\n\t\t\t\t\t))}\n\t\t\t\t\t<InputWithId id=\"0\" />\n\t\t\t\t\t{state.after.map(value => (\n\t\t\t\t\t\t<ListComponent key={props.unkeyed ? undefined : value}>\n\t\t\t\t\t\t\t{value}\n\t\t\t\t\t\t</ListComponent>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t}\n\n\tconst List = ({ children }) => <div>{children}</div>;\n\tconst ListItem = ({ children }) => <span>{children}</span>;\n\tconst InputWithId = ({ id }) => <input id={`input-${id}`} type=\"text\" />;\n\tconst Input = () => <input type=\"text\" />;\n\n\tfunction focusInput() {\n\t\tif (!scratch) return;\n\n\t\tconst input = scratch.querySelector('input');\n\t\tinput.value = 'a word';\n\t\tinput.focus();\n\t\tinput.setSelectionRange(2, 5);\n\n\t\texpect(document.activeElement).to.equalNode(input);\n\n\t\treturn input;\n\t}\n\n\tfunction focusInputById() {\n\t\tif (!scratch) return;\n\n\t\t/** @type {HTMLInputElement} */\n\t\tconst input = scratch.querySelector('#input-0');\n\t\tinput.value = 'a word';\n\t\tinput.focus();\n\t\tinput.setSelectionRange(2, 5);\n\n\t\texpect(document.activeElement).to.equalNode(input);\n\n\t\treturn input;\n\t}\n\n\t/**\n\t * Validate an input tag has maintained focus\n\t * @param {HTMLInputElement} input The input to validate\n\t * @param {string} [message] Message to show if the activeElement is not\n\t * equal to the `input` parameter\n\t */\n\tfunction validateFocus(input, message) {\n\t\texpect(document.activeElement).to.equalNode(input, message);\n\t\texpect(input.selectionStart).to.equal(2);\n\t\texpect(input.selectionEnd).to.equal(5);\n\t}\n\n\t/**\n\t * @param {Array<number | string>} before\n\t * @param {Array<number | string>} after\n\t */\n\tfunction getListHtml(before, after) {\n\t\treturn div([\n\t\t\t...before.map(i => span(i)),\n\t\t\tinputStr(),\n\t\t\t...after.map(i => span(i))\n\t\t]);\n\t}\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit.skip('should maintain focus when swapping elements', () => {\n\t\trender(\n\t\t\t<List>\n\t\t\t\t<Input />\n\t\t\t\t<ListItem>fooo</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\tconst input = focusInput();\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([], ['fooo']));\n\n\t\trender(\n\t\t\t<List>\n\t\t\t\t<ListItem>fooo</ListItem>\n\t\t\t\t<Input />\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\t\tvalidateFocus(input);\n\t\texpect(scratch.innerHTML).to.equal(getListHtml(['fooo'], []));\n\t});\n\n\tit('should maintain focus when moving the input around', () => {\n\t\tfunction App({ showFirst, showLast }) {\n\t\t\treturn (\n\t\t\t\t<List>\n\t\t\t\t\t{showFirst ? <ListItem>1</ListItem> : null}\n\t\t\t\t\t<Input />\n\t\t\t\t\t{showLast ? <ListItem>2</ListItem> : null}\n\t\t\t\t</List>\n\t\t\t);\n\t\t}\n\n\t\trender(<App showFirst={true} showLast={true} />, scratch);\n\n\t\tlet input = focusInput();\n\t\trender(<App showFirst={false} showLast={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([], [2]));\n\t\tvalidateFocus(input, 'move from middle to beginning');\n\n\t\tinput = focusInput();\n\t\trender(<App showFirst={true} showLast={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([1], [2]));\n\t\tvalidateFocus(input, 'move from beginning to middle');\n\n\t\tinput = focusInput();\n\t\trender(<App showFirst={true} showLast={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([1], []));\n\t\tvalidateFocus(input, 'move from middle to end');\n\n\t\tinput = focusInput();\n\t\trender(<App showFirst={true} showLast={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([1], [2]));\n\t\tvalidateFocus(input, 'move from end to middle');\n\t});\n\n\tit('should maintain focus when adding children around input', () => {\n\t\trender(<DynamicList />, scratch);\n\n\t\tlet input = focusInput();\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling before');\n\n\t\tappend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling after');\n\n\t\tappend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling after again');\n\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling before again');\n\t});\n\n\tit('should maintain focus when adding children around input (unkeyed)', () => {\n\t\t// Related preactjs/preact#2446\n\n\t\trender(<DynamicList unkeyed />, scratch);\n\n\t\tlet input = focusInput();\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling before');\n\n\t\tappend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling after');\n\n\t\tappend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling after again');\n\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'insert sibling before again');\n\t});\n\n\tit('should maintain focus when conditional elements around input', () => {\n\t\trender(\n\t\t\t<List>\n\t\t\t\t<ListItem>0</ListItem>\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<Input />\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t<ListItem>3</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet input = focusInput();\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([0, 1], [2, 3]));\n\n\t\trender(\n\t\t\t<List>\n\t\t\t\t{false && <ListItem>0</ListItem>}\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<Input />\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t<ListItem>3</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([1], [2, 3]));\n\t\tvalidateFocus(input, 'remove sibling before');\n\n\t\trender(\n\t\t\t<List>\n\t\t\t\t{false && <ListItem>0</ListItem>}\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<Input />\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t{false && <ListItem>3</ListItem>}\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([1], [2]));\n\t\tvalidateFocus(input, 'remove sibling after');\n\n\t\trender(\n\t\t\t<List>\n\t\t\t\t{false && <ListItem>0</ListItem>}\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<Input />\n\t\t\t\t{false && <ListItem>2</ListItem>}\n\t\t\t\t{false && <ListItem>3</ListItem>}\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([1], []));\n\t\tvalidateFocus(input, 'remove sibling after 2');\n\n\t\trender(\n\t\t\t<List>\n\t\t\t\t{false && <ListItem>0</ListItem>}\n\t\t\t\t{false && <ListItem>1</ListItem>}\n\t\t\t\t<Input />\n\t\t\t\t{false && <ListItem>2</ListItem>}\n\t\t\t\t{false && <ListItem>3</ListItem>}\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(getListHtml([], []));\n\t\tvalidateFocus(input, 'remove sibling before 2');\n\t});\n\n\tit('should maintain focus when removing elements around input', () => {\n\t\trender(\n\t\t\t<DynamicList initialBefore={[0, 1]} initialAfter={[2, 3]} />,\n\t\t\tscratch\n\t\t);\n\n\t\tlet input = focusInput();\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\n\t\tshift();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'remove sibling before');\n\n\t\tpop();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'remove sibling after');\n\n\t\tpop();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'remove sibling after 2');\n\n\t\tshift();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'remove sibling before 2');\n\t});\n\n\tit('should  maintain focus when removing element directly before input', () => {\n\t\trender(\n\t\t\t<DynamicList initialBefore={[0, 1]} initialAfter={[2, 3]} />,\n\t\t\tscratch\n\t\t);\n\n\t\tlet input = focusInput();\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\n\t\tsetState({ before: [0] });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'remove sibling directly before input');\n\t});\n\n\tit('should maintain focus when adding input next to the current input', () => {\n\t\trender(<DynamicList as={Input} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\n\t\tlet input = focusInputById();\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'add input before');\n\n\t\tinput = focusInputById();\n\t\tappend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'add input after');\n\n\t\tinput = focusInputById();\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'add input first place');\n\n\t\tinput = focusInputById();\n\t\tprepend();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(getDynamicListHtml());\n\t\tvalidateFocus(input, 'add input before');\n\t});\n\n\tit('should maintain focus when hydrating', () => {\n\t\tconst html = div([span('1'), span('2'), span('3'), inputStr()]);\n\n\t\tscratch.innerHTML = html;\n\t\tconst input = focusInput();\n\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t<ListItem>3</ListItem>\n\t\t\t\t<Input />\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\tvalidateFocus(input);\n\t});\n\n\tit('should keep focus in Fragments', () => {\n\t\t/** @type {HTMLInputElement} */\n\t\tlet input;\n\n\t\t/** @type {() => void} */\n\t\tlet updateState;\n\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { active: false };\n\t\t\t\tupdateState = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h1>Heading</h1>\n\t\t\t\t\t\t{!this.state.active\n\t\t\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t\t\tfoobar\n\t\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t\tHello World\n\t\t\t\t\t\t\t\t\t\t<h2>yo</h2>\n\t\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t\t\t<input type=\"text\" ref={i => (input = i)} />\n\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t\tHello World\n\t\t\t\t\t\t\t\t\t\t<h2>yo</h2>\n\t\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t\t\tfoobar\n\t\t\t\t\t\t\t\t\t<input type=\"text\" ref={i => (input = i)} />\n\t\t\t\t\t\t\t\t</Fragment>}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tinput.focus();\n\t\tupdateState();\n\n\t\texpect(document.activeElement).to.equalNode(input, 'Before rerender');\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([h1('Heading'), 'Hello World', h2('yo'), 'foobar', inputStr()])\n\t\t);\n\t\texpect(document.activeElement).to.equalNode(input, 'After rerender');\n\t});\n\n\tit('should keep text selection', () => {\n\t\t/** @type {HTMLInputElement} */\n\t\tlet input;\n\n\t\t/** @type {() => void} */\n\t\tlet updateState;\n\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { active: false };\n\t\t\t\tupdateState = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h1>Heading</h1>\n\t\t\t\t\t\t{!this.state.active\n\t\t\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t\t\tfoobar\n\t\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t\tHello World\n\t\t\t\t\t\t\t\t\t\t<h2>yo</h2>\n\t\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t\t\t<input type=\"text\" ref={i => (input = i)} value=\"foobar\" />\n\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t\tHello World\n\t\t\t\t\t\t\t\t\t\t<h2>yo</h2>\n\t\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t\t\tfoobar\n\t\t\t\t\t\t\t\t\t<input type=\"text\" ref={i => (input = i)} value=\"foobar\" />\n\t\t\t\t\t\t\t\t</Fragment>}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tinput.focus();\n\t\tinput.setSelectionRange(2, 5);\n\t\tupdateState();\n\n\t\texpect(document.activeElement).to.equalNode(input, 'Before rerender');\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([h1('Heading'), 'Hello World', h2('yo'), 'foobar', inputStr()])\n\t\t);\n\t\texpect(input.selectionStart).to.equal(2);\n\t\texpect(input.selectionEnd).to.equal(5);\n\t\texpect(document.activeElement).to.equalNode(input, 'After rerender');\n\t});\n});\n"
  },
  {
    "path": "test/browser/fragments.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport {\n\tcreateElement,\n\trender,\n\tComponent,\n\tFragment,\n\tcreateContext\n} from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { span, div, ul, ol, li, section } from '../_util/dom';\nimport { logCall, clearLog, getLog } from '../_util/logCall';\n\n/* eslint-disable react/jsx-boolean-value */\n\ndescribe('Fragment', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tlet ops = [];\n\n\tfunction expectDomLogToBe(expectedOperations, message) {\n\t\texpect(getLog()).to.deep.equal(expectedOperations, message);\n\t}\n\n\tclass Stateful extends Component {\n\t\tcomponentDidUpdate() {\n\t\t\tops.push('Update Stateful');\n\t\t}\n\t\trender() {\n\t\t\treturn <div>Hello</div>;\n\t\t}\n\t}\n\n\tlet resetInsertBefore;\n\tlet resetAppendChild;\n\tlet resetRemove;\n\tlet resetRemoveText;\n\n\tbeforeAll(() => {\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetAppendChild = logCall(Element.prototype, 'appendChild');\n\t\tresetRemove = logCall(Element.prototype, 'remove');\n\t\tresetRemoveText = logCall(Text.prototype, 'remove');\n\t\t// logCall(CharacterData.prototype, 'remove');\n\t\t// TODO: Consider logging setting set data\n\t\t// ```\n\t\t// var orgData = Object.getOwnPropertyDescriptor(CharacterData.prototype, 'data')\n\t\t// Object.defineProperty(CharacterData.prototype, 'data', {\n\t\t// \t...orgData,\n\t\t// \tget() { return orgData.get.call(this) },\n\t\t// \tset(value) { console.log('setData', value); orgData.set.call(this, value); }\n\t\t// });\n\t\t// ```\n\t});\n\n\tafterAll(() => {\n\t\tresetInsertBefore();\n\t\tresetAppendChild();\n\t\tresetRemove();\n\t\tresetRemoveText();\n\t});\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t\tops = [];\n\n\t\tclearLog();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should not render empty Fragment', () => {\n\t\trender(<Fragment />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t});\n\n\tit('should render a single child', () => {\n\t\tclearLog();\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<span>foo</span>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('<span>foo</span>');\n\t\texpectDomLogToBe([\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>.appendChild(<span>foo)'\n\t\t]);\n\t});\n\n\tit('should render multiple children via noop renderer', () => {\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\thello <span>world</span>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('hello <span>world</span>');\n\t});\n\n\tit('should not crash with null as last child', () => {\n\t\tlet fn = () => {\n\t\t\trender(\n\t\t\t\t<Fragment>\n\t\t\t\t\t<span>world</span>\n\t\t\t\t\t{null}\n\t\t\t\t</Fragment>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t};\n\t\texpect(fn).not.to.throw();\n\t\texpect(scratch.innerHTML).to.equal('<span>world</span>');\n\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<span>world</span>\n\t\t\t\t<p>Hello</p>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<span>world</span><p>Hello</p>');\n\n\t\texpect(fn).not.to.throw();\n\t\texpect(scratch.innerHTML).to.equal('<span>world</span>');\n\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<span>world</span>\n\t\t\t\t{null}\n\t\t\t\t<span>world</span>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<span>world</span><span>world</span>');\n\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<span>world</span>\n\t\t\t\tHello\n\t\t\t\t<span>world</span>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<span>world</span>Hello<span>world</span>'\n\t\t);\n\t});\n\n\tit('should handle reordering components that return Fragments #1325', () => {\n\t\tclass X extends Component {\n\t\t\trender() {\n\t\t\t\treturn <Fragment>{this.props.children}</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender(props) {\n\t\t\t\tif (this.props.i === 0) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<X key={1}>1</X>\n\t\t\t\t\t\t\t<X key={2}>2</X>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<X key={2}>2</X>\n\t\t\t\t\t\t<X key={1}>1</X>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App i={0} />, scratch);\n\t\texpect(scratch.textContent).to.equal('12');\n\t\trender(<App i={1} />, scratch);\n\t\texpect(scratch.textContent).to.equal('21');\n\t});\n\n\tit('should handle changing node type within a Component that returns a Fragment #1326', () => {\n\t\tclass X extends Component {\n\t\t\trender() {\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\t/** @type {(newState: any) => void} */\n\t\tlet setState;\n\t\tclass App extends Component {\n\t\t\tconstructor(props, context) {\n\t\t\t\tsuper(props, context);\n\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tif (this.state.i === 0) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<X>\n\t\t\t\t\t\t\t\t<span>1</span>\n\t\t\t\t\t\t\t</X>\n\t\t\t\t\t\t\t<X>\n\t\t\t\t\t\t\t\t<span>2</span>\n\t\t\t\t\t\t\t\t<span>2</span>\n\t\t\t\t\t\t\t</X>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<X>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t</X>\n\t\t\t\t\t\t<X>\n\t\t\t\t\t\t\t<span>2</span>\n\t\t\t\t\t\t\t<span>2</span>\n\t\t\t\t\t\t</X>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(div([span(1), span(2), span(2)]));\n\n\t\tsetState({ i: 1 });\n\n\t\tclearLog();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(div([div(1), span(2), span(2)]));\n\t\texpectDomLogToBe([\n\t\t\t'<span>1.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>22.insertBefore(<div>1, <span>2)'\n\t\t]);\n\t});\n\n\tit('should preserve state of children with 1 level nesting', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Stateful key=\"a\" />\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t<div key=\"b\">World</div>\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.deep.equal('<div>Hello</div><div>World</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.deep.equal('<div>Hello</div>');\n\t});\n\n\tit('should preserve state between top-level fragments', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>\n\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe([]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe([]);\n\t});\n\n\tit('should preserve state of children nested at same level', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div></div><div>Hello</div>');\n\t\texpectDomLogToBe(['<div>Hello.insertBefore(<div>, <div>Hello)']);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe(['<div>.remove()']);\n\t});\n\n\tit('should not preserve state in non-top-level fragment nesting', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe([\n\t\t\t'<div>Hello.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>.appendChild(<div>Hello)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe([\n\t\t\t'<div>Hello.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t// Re-append the Stateful DOM since it has been re-parented\n\t\t\t'<div>.appendChild(<div>Hello)'\n\t\t]);\n\t});\n\n\tit('should not preserve state of children if nested 2 levels without siblings', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Stateful key=\"a\" />\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe([\n\t\t\t'<div>Hello.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>.appendChild(<div>Hello)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t\texpectDomLogToBe([\n\t\t\t'<div>Hello.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>.appendChild(<div>Hello)'\n\t\t]);\n\t});\n\n\tit('should just render children for fragments', () => {\n\t\tclass Comp extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>Child1</div>\n\t\t\t\t\t\t<div>Child2</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Child1</div><div>Child2</div>');\n\t});\n\n\tit('should not preserve state of children if nested 2 levels with siblings', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Stateful key=\"a\" />\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<div />\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div><div></div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should preserve state between array nested in fragment and fragment', () => {\n\t\t// In this test case, the children of the Fragment in Foo end up being the same when flattened.\n\t\t//\n\t\t// When condition == true, the children of the Fragment are a Stateful VNode.\n\t\t// When condition == false, the children of the Fragment are an Array containing a single\n\t\t// Stateful VNode.\n\t\t//\n\t\t// However, when each of these are flattened (in flattenChildren), they both become\n\t\t// an Array containing a single Stateful VNode. So when diff'ed they are compared together\n\t\t// and the state of Stateful is preserved\n\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>\n\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <Fragment>{[<Stateful key=\"a\" />]}</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should preserve state between top level fragment and array', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? [<Stateful key=\"a\" />]\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should not preserve state between array nested in fragment and double nested fragment', () => {\n\t\t// In this test case, the children of the Fragment in Foo end up being the different when flattened.\n\t\t//\n\t\t// When condition == true, the children of the Fragment are an Array of Stateful VNode.\n\t\t// When condition == false, the children of the Fragment are another Fragment whose children are\n\t\t// a single Stateful VNode.\n\t\t//\n\t\t// When each of these are flattened (in flattenChildren), the first Fragment stays the same\n\t\t// (Fragment -> [Stateful]). The second Fragment also doesn't change (flattening doesn't erase\n\t\t// Fragments) so it remains Fragment -> Fragment -> Stateful. Therefore when diff'ed these Fragments\n\t\t// separate the two Stateful VNodes into different trees and state is not preserved between them.\n\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>{[<Stateful key=\"a\" />]}</Fragment>\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should not preserve state between array nested in fragment and double nested array', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>{[<Stateful key=\"a\" />]}</Fragment>\n\t\t\t\t: [[<Stateful key=\"a\" />]];\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should preserve state between double nested fragment and double nested array', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t: [[<Stateful key=\"a\" />]];\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should not preserve state of children when the keys are different', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment key=\"a\">\n\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <Fragment key=\"b\">\n\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t\t<span>World</span>\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div><span>World</span>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should not preserve state between unkeyed and keyed fragment', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <Fragment key=\"a\">\n\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <Fragment>\n\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t</Fragment>;\n\t\t}\n\n\t\t// React & Preact: has the same behavior for components\n\t\t// https://codesandbox.io/s/57prmy5mx\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello</div>');\n\t});\n\n\tit('should preserve order for fragment switching', () => {\n\t\tlet set;\n\t\tclass Foo extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { isLoading: true, data: null };\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\t\t\trender(props, { isLoading, data }) {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>HEADER</div>\n\t\t\t\t\t\t{isLoading ? <div>Loading...</div> : null}\n\t\t\t\t\t\t{data ? <div>Content: {data}</div> : null}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>HEADER</div><div>Loading...</div>'\n\t\t);\n\n\t\tset({ isLoading: false, data: 2 });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>HEADER</div><div>Content: 2</div>'\n\t\t);\n\t});\n\n\tit('should preserve order for nested fragment switching w/ child return', () => {\n\t\tlet set;\n\t\tconst Wrapper = ({ children }) => <Fragment>{children}</Fragment>;\n\t\tclass Foo extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { isLoading: true, data: null };\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\t\t\trender(props, { isLoading, data }) {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>HEADER</div>\n\t\t\t\t\t\t{isLoading ? <div>Loading...</div> : null}\n\t\t\t\t\t\t{data ? <div>Content: {data}</div> : null}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Wrapper>\n\t\t\t\t<Foo />\n\t\t\t</Wrapper>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>HEADER</div><div>Loading...</div>'\n\t\t);\n\n\t\tset({ isLoading: false, data: 2 });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>HEADER</div><div>Content: 2</div>'\n\t\t);\n\t});\n\n\tit('should preserve order for nested fragment switching', () => {\n\t\tlet set;\n\t\tconst Wrapper = () => (\n\t\t\t<Fragment>\n\t\t\t\t<Foo />\n\t\t\t</Fragment>\n\t\t);\n\t\tclass Foo extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { isLoading: true, data: null };\n\t\t\t\tset = this.setState.bind(this);\n\t\t\t}\n\t\t\trender(props, { isLoading, data }) {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>HEADER</div>\n\t\t\t\t\t\t{isLoading ? <div>Loading...</div> : null}\n\t\t\t\t\t\t{data ? <div>Content: {data}</div> : null}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Wrapper />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>HEADER</div><div>Loading...</div>'\n\t\t);\n\n\t\tset({ isLoading: false, data: 2 });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>HEADER</div><div>Content: 2</div>'\n\t\t);\n\t});\n\n\tit('should preserve state with reordering in multiple levels', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment key=\"c\">\n\t\t\t\t\t\t\t<div>foo</div>\n\t\t\t\t\t\t\t<div key=\"b\">\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<div>boop</div>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<div>beep</div>\n\t\t\t\t\t\t<Fragment key=\"c\">\n\t\t\t\t\t\t\t<div key=\"b\">\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>bar</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\tconst htmlForTrue = div([div('foo'), div(div('Hello')), div('boop')]);\n\n\t\tconst htmlForFalse = div([div('beep'), div(div('Hello')), div('bar')]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal(htmlForFalse);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>barHellobeep.insertBefore(<div>bar, <div>beep)',\n\t\t\t\t'<div>Hellobarbeep.appendChild(<div>Hello)',\n\t\t\t\t'<div>barbeepHello.appendChild(<div>bar)'\n\t\t\t],\n\t\t\t'rendering true to false'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>beepHellofoo.appendChild(<div>Hello)',\n\t\t\t\t'<div>boopfooHello.appendChild(<div>boop)'\n\t\t\t],\n\t\t\t'rendering false to true'\n\t\t);\n\t});\n\n\tit('should not preserve state when switching between a keyed fragment and an array', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t<Fragment key=\"foo\">\n\t\t\t\t\t\t\t\t<span>1</span>\n\t\t\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t<span>2</span>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t{[<span>1</span>, <Stateful />]}\n\t\t\t\t\t\t<span>2</span>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\tconst html = div([span('1'), div('Hello'), span('2')]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]); // Component should not have updated (empty op log)\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpectDomLogToBe([\n\t\t\t'<span>1.remove()',\n\t\t\t'<div>Hello.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>2.insertBefore(<span>1, <span>2)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>12.insertBefore(<div>Hello, <span>2)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal([]); // Component should not have updated (empty op log)\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpectDomLogToBe([\n\t\t\t'<span>1.remove()',\n\t\t\t'<div>Hello.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>2.insertBefore(<span>1, <span>2)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>12.insertBefore(<div>Hello, <span>2)'\n\t\t]);\n\t});\n\n\tit('should preserve state when it does not change positions', () => {\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? [\n\t\t\t\t\t\t<span />,\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t]\n\t\t\t\t: [\n\t\t\t\t\t\t<span />,\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Stateful />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t];\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<span></span><div>Hello</div>');\n\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal('<span></span><div>Hello</div>');\n\t});\n\n\tit('should render nested Fragments', () => {\n\t\tclearLog();\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\tspam\n\t\t\t\t<Fragment>foo</Fragment>\n\t\t\t\t<Fragment />\n\t\t\t\tbar\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('spamfoobar');\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>spam.appendChild(#text)',\n\t\t\t'<div>spamfoo.appendChild(#text)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(\n\t\t\t<Fragment>\n\t\t\t\t<Fragment>foo</Fragment>\n\t\t\t\t<Fragment>bar</Fragment>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('foobar');\n\t\texpectDomLogToBe([\n\t\t\t'#text.remove()',\n\t\t\t'#text.remove()',\n\t\t\t'<div>foo.appendChild(#text)'\n\t\t]);\n\t});\n\n\tit('should render nested Fragments with siblings', () => {\n\t\tclearLog();\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>0</div>\n\t\t\t\t<div>1</div>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t\t<div>4</div>\n\t\t\t\t<div>5</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(0), div(1), div(2), div(3), div(4), div(5)])\n\t\t);\n\t});\n\n\tit('should respect keyed Fragments', () => {\n\t\t/** @type {() => void} */\n\t\tlet update;\n\n\t\tclass Comp extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { key: 'foo' };\n\t\t\t\tupdate = () => this.setState({ key: 'bar' });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <Fragment key={this.state.key}>foo</Fragment>;\n\t\t\t}\n\t\t}\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('foo');\n\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal('foo');\n\t});\n\n\tit('should support conditionally rendered children', () => {\n\t\t/** @type {() => void} */\n\t\tlet update;\n\n\t\tclass Comp extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { value: true };\n\t\t\t\tupdate = () => this.setState({ value: !this.state.value });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<span>0</span>\n\t\t\t\t\t\t{this.state.value && 'foo'}\n\t\t\t\t\t\t<span>1</span>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst html = contents => span('0') + contents + span('1');\n\n\t\trender(<Comp />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(html('foo'));\n\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(html(''));\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(html('foo'));\n\t});\n\n\tit('can modify the children of a Fragment', () => {\n\t\t/** @type {() => void} */\n\t\tlet push;\n\n\t\tclass List extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { values: [0, 1, 2] };\n\t\t\t\tpush = () =>\n\t\t\t\t\tthis.setState({\n\t\t\t\t\t\tvalues: [...this.state.values, this.state.values.length]\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t{this.state.values.map(value => (\n\t\t\t\t\t\t\t<div>{value}</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<List />, scratch);\n\t\texpect(scratch.textContent).to.equal('012');\n\n\t\tpush();\n\t\trerender();\n\n\t\texpect(scratch.textContent).to.equal('0123');\n\n\t\tpush();\n\t\trerender();\n\n\t\texpect(scratch.textContent).to.equal('01234');\n\t});\n\n\tit('should render sibling array children', () => {\n\t\tconst Group = ({ title, values }) => (\n\t\t\t<Fragment>\n\t\t\t\t<li>{title}</li>\n\t\t\t\t{values.map(value => (\n\t\t\t\t\t<li>{value}</li>\n\t\t\t\t))}\n\t\t\t</Fragment>\n\t\t);\n\n\t\tconst Todo = () => (\n\t\t\t<ul>\n\t\t\t\t<Group title={'A header'} values={['a', 'b']} />\n\t\t\t\t<Group title={'A divider'} values={['c', 'd']} />\n\t\t\t\t<li>A footer</li>\n\t\t\t</ul>\n\t\t);\n\n\t\trender(<Todo />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tul([\n\t\t\t\tli('A header'),\n\t\t\t\tli('a'),\n\t\t\t\tli('b'),\n\t\t\t\tli('A divider'),\n\t\t\t\tli('c'),\n\t\t\t\tli('d'),\n\t\t\t\tli('A footer')\n\t\t\t])\n\t\t);\n\t});\n\n\tit('should reorder Fragment children', () => {\n\t\tlet updateState;\n\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { active: false };\n\t\t\t\tupdateState = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h1>Heading</h1>\n\t\t\t\t\t\t{!this.state.active\n\t\t\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t\t\tfoobar\n\t\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t\tHello World\n\t\t\t\t\t\t\t\t\t\t<h2>yo</h2>\n\t\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t\t\t<input type=\"text\" />\n\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t\tHello World\n\t\t\t\t\t\t\t\t\t\t<h2>yo</h2>\n\t\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t\t\tfoobar\n\t\t\t\t\t\t\t\t\t<input type=\"text\" />\n\t\t\t\t\t\t\t\t</Fragment>}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><h1>Heading</h1>foobarHello World<h2>yo</h2><input type=\"text\"></div>'\n\t\t);\n\n\t\tupdateState();\n\n\t\t// See \"should preserve state between top level fragment and array\"\n\t\t// Perhaps rename test to \"should reorder **keyed** Fragment children\"\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><h1>Heading</h1>Hello World<h2>yo</h2>foobar<input type=\"text\"></div>'\n\t\t);\n\t});\n\n\tit('should render sibling fragments with multiple children in the correct order', () => {\n\t\trender(\n\t\t\t<ol>\n\t\t\t\t<li>0</li>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<li>1</li>\n\t\t\t\t\t<li>2</li>\n\t\t\t\t</Fragment>\n\t\t\t\t<li>3</li>\n\t\t\t\t<li>4</li>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<li>5</li>\n\t\t\t\t\t<li>6</li>\n\t\t\t\t</Fragment>\n\t\t\t\t<li>7</li>\n\t\t\t</ol>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.textContent).to.equal('01234567');\n\t});\n\n\tit('should support HOCs that return children', () => {\n\t\tconst text =\n\t\t\t\"Don't forget to tell these special people in your life just how special they are to you.\";\n\n\t\tclass BobRossProvider extends Component {\n\t\t\tgetChildContext() {\n\t\t\t\treturn { text };\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn props.children;\n\t\t\t}\n\t\t}\n\n\t\tfunction BobRossConsumer(props, context) {\n\t\t\treturn props.children(context.text);\n\t\t}\n\n\t\tconst Say = props => <div>{props.text}</div>;\n\n\t\tconst Speak = () => (\n\t\t\t<Fragment>\n\t\t\t\t<span>the top</span>\n\t\t\t\t<BobRossProvider>\n\t\t\t\t\t<span>a span</span>\n\t\t\t\t\t<BobRossConsumer>\n\t\t\t\t\t\t{text => [<Say text={text} />, <Say text={text} />]}\n\t\t\t\t\t</BobRossConsumer>\n\t\t\t\t\t<span>another span</span>\n\t\t\t\t</BobRossProvider>\n\t\t\t\t<span>a final span</span>\n\t\t\t</Fragment>\n\t\t);\n\n\t\trender(<Speak />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t[\n\t\t\t\tspan('the top'),\n\t\t\t\tspan('a span'),\n\t\t\t\tdiv(text),\n\t\t\t\tdiv(text),\n\t\t\t\tspan('another span'),\n\t\t\t\tspan('a final span')\n\t\t\t].join('')\n\t\t);\n\t});\n\n\tit('should support conditionally rendered Fragment', () => {\n\t\tconst Foo = ({ condition }) => (\n\t\t\t<ol>\n\t\t\t\t<li>0</li>\n\t\t\t\t{condition\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<li>1</li>\n\t\t\t\t\t\t\t<li>2</li>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: [<li>1</li>, <li>2</li>]}\n\t\t\t\t<li>3</li>\n\t\t\t</ol>\n\t\t);\n\n\t\tconst html = ol([li('0'), li('1'), li('2'), li('3')]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(html, 'initial render of true');\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>.appendChild(<li>0)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0.appendChild(<li>1)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>01.appendChild(<li>2)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>012.appendChild(<li>3)',\n\t\t\t\t'<div>.appendChild(<ol>0123)'\n\t\t\t],\n\t\t\t'initial render of true'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(html, 'rendering from true to false');\n\t\texpectDomLogToBe([], 'rendering from true to false');\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(html, 'rendering from false to true');\n\t\texpectDomLogToBe([], 'rendering from false to true');\n\t});\n\n\tit('should support conditionally rendered Fragment or null', () => {\n\t\tconst Foo = ({ condition }) => (\n\t\t\t<ol>\n\t\t\t\t<li>0</li>\n\t\t\t\t{condition\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<li>1</li>\n\t\t\t\t\t\t\t<li>2</li>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: null}\n\t\t\t\t<li>3</li>\n\t\t\t\t<li>4</li>\n\t\t\t</ol>\n\t\t);\n\n\t\tconst htmlForTrue = ol([li('0'), li('1'), li('2'), li('3'), li('4')]);\n\n\t\tconst htmlForFalse = ol([li('0'), li('3'), li('4')]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue, 'initial render of true');\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>.appendChild(<li>0)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0.appendChild(<li>1)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>01.appendChild(<li>2)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>012.appendChild(<li>3)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0123.appendChild(<li>4)',\n\t\t\t\t'<div>.appendChild(<ol>01234)'\n\t\t\t],\n\t\t\t'initial render of true'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t['<li>1.remove()', '<li>2.remove()'],\n\t\t\t'rendering from true to false'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>034.insertBefore(<li>1, <li>3)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0134.insertBefore(<li>2, <li>3)'\n\t\t\t],\n\t\t\t'rendering from false to true'\n\t\t);\n\t});\n\n\tit('should support moving Fragments between beginning and end', () => {\n\t\tconst Foo = ({ condition }) => (\n\t\t\t<ol>\n\t\t\t\t{condition\n\t\t\t\t\t? [\n\t\t\t\t\t\t\t<li>0</li>,\n\t\t\t\t\t\t\t<li>1</li>,\n\t\t\t\t\t\t\t<li>2</li>,\n\t\t\t\t\t\t\t<li>3</li>,\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<li>4</li>\n\t\t\t\t\t\t\t\t<li>5</li>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t]\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<li>4</li>\n\t\t\t\t\t\t\t\t<li>5</li>\n\t\t\t\t\t\t\t</Fragment>,\n\t\t\t\t\t\t\t<li>0</li>,\n\t\t\t\t\t\t\t<li>1</li>,\n\t\t\t\t\t\t\t<li>2</li>,\n\t\t\t\t\t\t\t<li>3</li>\n\t\t\t\t\t\t]}\n\t\t\t</ol>\n\t\t);\n\n\t\tconst htmlForTrue = ol([\n\t\t\tli('0'),\n\t\t\tli('1'),\n\t\t\tli('2'),\n\t\t\tli('3'),\n\t\t\tli('4'),\n\t\t\tli('5')\n\t\t]);\n\n\t\tconst htmlForFalse = ol([\n\t\t\tli('4'),\n\t\t\tli('5'),\n\t\t\tli('0'),\n\t\t\tli('1'),\n\t\t\tli('2'),\n\t\t\tli('3')\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue, 'initial render of true');\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<ol>012345.insertBefore(<li>4, <li>0)',\n\t\t\t'<ol>401235.insertBefore(<li>5, <li>0)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<ol>450123.appendChild(<li>4)',\n\t\t\t'<ol>501234.appendChild(<li>5)'\n\t\t]);\n\t});\n\n\tit('should support conditional beginning and end Fragments', () => {\n\t\tconst Foo = ({ condition }) => (\n\t\t\t<ol>\n\t\t\t\t{condition\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<li>0</li>\n\t\t\t\t\t\t\t<li>1</li>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: null}\n\t\t\t\t<li>2</li>\n\t\t\t\t<li>2</li>\n\t\t\t\t{condition\n\t\t\t\t\t? null\n\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t<li>3</li>\n\t\t\t\t\t\t\t<li>4</li>\n\t\t\t\t\t\t</Fragment>}\n\t\t\t</ol>\n\t\t);\n\n\t\tconst htmlForTrue = ol([li(0), li(1), li(2), li(2)]);\n\n\t\tconst htmlForFalse = ol([li(2), li(2), li(3), li(4)]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue, 'initial render of true');\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t// Remove 1 & 2 (replaced with null)\n\t\t\t'<li>0.remove()',\n\t\t\t'<li>1.remove()',\n\t\t\t// Mount 3 & 4\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>22.appendChild(<li>3)',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>223.appendChild(<li>4)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t// Remove 3 & 4 (replaced by null)\n\t\t\t'<li>3.remove()',\n\t\t\t'<li>4.remove()',\n\t\t\t// Insert 0 and 1\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>22.insertBefore(<li>0, <li>2)',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>022.insertBefore(<li>1, <li>2)'\n\t\t]);\n\t});\n\n\tit('should support nested conditional beginning and end Fragments', () => {\n\t\tconst Foo = ({ condition }) => (\n\t\t\t<ol>\n\t\t\t\t{condition\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t<li>0</li>\n\t\t\t\t\t\t\t\t\t<li>1</li>\n\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: null}\n\t\t\t\t<li>2</li>\n\t\t\t\t<li>3</li>\n\t\t\t\t{condition\n\t\t\t\t\t? null\n\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t\t<li>4</li>\n\t\t\t\t\t\t\t\t\t<li>5</li>\n\t\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>}\n\t\t\t</ol>\n\t\t);\n\n\t\tconst htmlForTrue = ol([li(0), li(1), li(2), li(3)]);\n\n\t\tconst htmlForFalse = ol([li(2), li(3), li(4), li(5)]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue, 'initial render of true');\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t// Remove 1 & 2 (replaced with null)\n\t\t\t'<li>0.remove()',\n\t\t\t'<li>1.remove()',\n\t\t\t// Mount 4 & 5\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>23.appendChild(<li>4)',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>234.appendChild(<li>5)'\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t// Remove 4 & 5 (replaced by null)\n\t\t\t'<li>4.remove()',\n\t\t\t'<li>5.remove()',\n\t\t\t// Insert 0 and 1 back into the DOM\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>23.insertBefore(<li>0, <li>2)',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>023.insertBefore(<li>1, <li>2)'\n\t\t]);\n\t});\n\n\tit('should preserve state with reordering in multiple levels with mixed # of Fragment siblings', () => {\n\t\t// Also fails if the # of divs outside the Fragment equals or exceeds\n\t\t// the # inside the Fragment for both conditions\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment key=\"c\">\n\t\t\t\t\t\t\t<div>foo</div>\n\t\t\t\t\t\t\t<div key=\"b\">\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<div>boop</div>\n\t\t\t\t\t\t<div>boop</div>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<div>beep</div>\n\t\t\t\t\t\t<Fragment key=\"c\">\n\t\t\t\t\t\t\t<div key=\"b\">\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>bar</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\tconst htmlForTrue = div([\n\t\t\tdiv('foo'),\n\t\t\tdiv(div('Hello')),\n\t\t\tdiv('boop'),\n\t\t\tdiv('boop')\n\t\t]);\n\n\t\tconst htmlForFalse = div([div('beep'), div(div('Hello')), div('bar')]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>boop.remove()',\n\t\t\t\t'<div>barHellobeep.insertBefore(<div>bar, <div>beep)',\n\t\t\t\t'<div>Hellobarbeep.appendChild(<div>Hello)',\n\t\t\t\t'<div>barbeepHello.appendChild(<div>bar)'\n\t\t\t],\n\t\t\t'rendering from true to false'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>beepHellofoo.appendChild(<div>Hello)',\n\t\t\t\t'<div>boopfooHello.appendChild(<div>boop)',\n\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t'<div>fooHelloboop.appendChild(<div>boop)'\n\t\t\t],\n\t\t\t'rendering from false to true'\n\t\t);\n\t});\n\n\tit('should preserve state with reordering in multiple levels with lots of Fragment siblings', () => {\n\t\t// Also fails if the # of divs outside the Fragment equals or exceeds\n\t\t// the # inside the Fragment for both conditions\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment key=\"c\">\n\t\t\t\t\t\t\t<div>foo</div>\n\t\t\t\t\t\t\t<div key=\"b\">\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<div>boop</div>\n\t\t\t\t\t\t<div>boop</div>\n\t\t\t\t\t\t<div>boop</div>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<div>beep</div>\n\t\t\t\t\t\t<div>beep</div>\n\t\t\t\t\t\t<div>beep</div>\n\t\t\t\t\t\t<Fragment key=\"c\">\n\t\t\t\t\t\t\t<div key=\"b\">\n\t\t\t\t\t\t\t\t<Stateful key=\"a\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div>bar</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\tconst htmlForTrue = div([\n\t\t\tdiv('foo'),\n\t\t\tdiv(div('Hello')),\n\t\t\tdiv('boop'),\n\t\t\tdiv('boop'),\n\t\t\tdiv('boop')\n\t\t]);\n\n\t\tconst htmlForFalse = div([\n\t\t\tdiv('beep'),\n\t\t\tdiv('beep'),\n\t\t\tdiv('beep'),\n\t\t\tdiv(div('Hello')),\n\t\t\tdiv('bar')\n\t\t]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>barHellobeepbeepbeep.insertBefore(<div>bar, <div>beep)',\n\t\t\t\t'<div>Hellobarbeepbeepbeep.appendChild(<div>Hello)',\n\t\t\t\t'<div>barbeepbeepbeepHello.appendChild(<div>bar)'\n\t\t\t],\n\t\t\t'rendering from true to false'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(ops).to.deep.equal(['Update Stateful', 'Update Stateful']);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>beepbeepbeepHellofoo.appendChild(<div>Hello)',\n\t\t\t\t'<div>beepbeepbeepfooHello.insertBefore(<div>foo, <div>beep)',\n\t\t\t\t'<div>foobeepbeepbeepHello.insertBefore(<div>Hello, <div>beep)'\n\t\t\t],\n\t\t\t'rendering from false to true'\n\t\t);\n\t});\n\n\tit('should correctly append children with siblings', () => {\n\t\t/**\n\t\t * @type {(props: { values: Array<string | number>}) => JSX.Element}\n\t\t */\n\t\tconst Foo = ({ values }) => (\n\t\t\t<ol>\n\t\t\t\t<li>a</li>\n\t\t\t\t<Fragment>\n\t\t\t\t\t{values.map(value => (\n\t\t\t\t\t\t<li>{value}</li>\n\t\t\t\t\t))}\n\t\t\t\t</Fragment>\n\t\t\t\t<li>b</li>\n\t\t\t</ol>\n\t\t);\n\n\t\tconst getHtml = values =>\n\t\t\tol([li('a'), ...values.map(value => li(value)), li('b')]);\n\n\t\tlet values = [0, 1, 2];\n\t\tclearLog();\n\t\trender(<Foo values={values} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tgetHtml(values),\n\t\t\t`original list: [${values.join(',')}]`\n\t\t);\n\n\t\tvalues.push(3);\n\n\t\tclearLog();\n\t\trender(<Foo values={values} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tgetHtml(values),\n\t\t\t`push 3: [${values.join(',')}]`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>a012b.insertBefore(<li>3, <li>b)'\n\t\t]);\n\n\t\tvalues.push(4);\n\n\t\tclearLog();\n\t\trender(<Foo values={values} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tgetHtml(values),\n\t\t\t`push 4: [${values.join(',')}]`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>a0123b.insertBefore(<li>4, <li>b)'\n\t\t]);\n\t});\n\n\tit('should render components that conditionally return Fragments', () => {\n\t\tconst Foo = ({ condition }) =>\n\t\t\tcondition\n\t\t\t\t? <Fragment>\n\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t\t<div>4</div>\n\t\t\t\t\t</div>;\n\n\t\tconst htmlForTrue = [div(1), div(2)].join('');\n\n\t\tconst htmlForFalse = div([div(3), div(4)]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForFalse);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>2.remove()',\n\t\t\t\t'#text.remove()',\n\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t'<div>.appendChild(<div>3)',\n\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t'<div>3.appendChild(<div>4)'\n\t\t\t],\n\t\t\t'rendering from true to false'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<div>3.remove()',\n\t\t\t\t'<div>4.remove()',\n\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t'<div>.appendChild(#text)',\n\t\t\t\t'<div>1.appendChild(<div>2)'\n\t\t\t],\n\t\t\t'rendering from false to true'\n\t\t);\n\t});\n\n\tit('should clear empty Fragments', () => {\n\t\tfunction Foo(props) {\n\t\t\tif (props.condition) {\n\t\t\t\treturn <Fragment>foo</Fragment>;\n\t\t\t}\n\t\t\treturn <Fragment />;\n\t\t}\n\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.textContent).to.equal('foo');\n\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.textContent).to.equal('');\n\t});\n\n\tit('should support conditionally rendered nested Fragments or null with siblings', () => {\n\t\tconst Foo = ({ condition }) => (\n\t\t\t<ol>\n\t\t\t\t<li>0</li>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<li>1</li>\n\t\t\t\t\t{condition\n\t\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t\t<li>2</li>\n\t\t\t\t\t\t\t\t<li>3</li>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t: null}\n\t\t\t\t\t<li>4</li>\n\t\t\t\t</Fragment>\n\t\t\t\t<li>5</li>\n\t\t\t</ol>\n\t\t);\n\n\t\tconst htmlForTrue = ol([\n\t\t\tli('0'),\n\t\t\tli('1'),\n\t\t\tli('2'),\n\t\t\tli('3'),\n\t\t\tli('4'),\n\t\t\tli('5')\n\t\t]);\n\n\t\tconst htmlForFalse = ol([li('0'), li('1'), li('4'), li('5')]);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue, 'initial render of true');\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>.appendChild(<li>0)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0.appendChild(<li>1)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>01.appendChild(<li>2)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>012.appendChild(<li>3)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0123.appendChild(<li>4)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>01234.appendChild(<li>5)',\n\t\t\t\t'<div>.appendChild(<ol>012345)'\n\t\t\t],\n\t\t\t'initial render of true'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForFalse,\n\t\t\t'rendering from true to false'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t['<li>2.remove()', '<li>3.remove()'],\n\t\t\t'rendering from true to false'\n\t\t);\n\n\t\tclearLog();\n\t\trender(<Foo condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\thtmlForTrue,\n\t\t\t'rendering from false to true'\n\t\t);\n\t\texpectDomLogToBe(\n\t\t\t[\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>0145.insertBefore(<li>2, <li>4)',\n\t\t\t\t'<li>.appendChild(#text)',\n\t\t\t\t'<ol>01245.insertBefore(<li>3, <li>4)'\n\t\t\t],\n\t\t\t'rendering from false to true'\n\t\t);\n\t});\n\n\tit('should render first child Fragment that wrap null components', () => {\n\t\tconst Empty = () => null;\n\t\tconst Foo = () => (\n\t\t\t<ol>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<Empty />\n\t\t\t\t</Fragment>\n\t\t\t\t<li>1</li>\n\t\t\t</ol>\n\t\t);\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(ol(li(1)));\n\t});\n\n\tit('should properly render Components that return Fragments and use shouldComponentUpdate #1415', () => {\n\t\tclass SubList extends Component {\n\t\t\tshouldComponentUpdate(nextProps) {\n\t\t\t\treturn nextProps.prop1 !== this.props.prop1;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t/** @type {(update: any) => void} */\n\t\tlet setState;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tsetState = update => this.setState(update);\n\n\t\t\t\tthis.state = { error: false };\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.error\n\t\t\t\t\t\t\t? <div>Error!</div>\n\t\t\t\t\t\t\t: <div>\n\t\t\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t\t\t<SubList prop1={this.state.error} />\n\t\t\t\t\t\t\t\t</div>}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst successHtml = div(div([div(1), div(2), div(3)]));\n\n\t\tconst errorHtml = div(div('Error!'));\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(successHtml);\n\n\t\tsetState({}); // Trigger sCU\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(successHtml);\n\n\t\tsetState({ error: true });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(errorHtml);\n\n\t\tsetState({ error: false });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(successHtml);\n\n\t\tsetState({}); // Trigger sCU again\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(successHtml);\n\t});\n\n\tit('should properly render Fragments whose last child is a component returning null', () => {\n\t\tlet Noop = () => null;\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ items: ['A', 'B', 'C'] });\n\t\t\t\tthis.state = {\n\t\t\t\t\titems: null\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.items && (\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t{this.state.items.map(v => (\n\t\t\t\t\t\t\t\t\t<div>{v}</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t<Noop />\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.textContent).to.equal('');\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.textContent).to.equal('ABC');\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>.appendChild(<div>A)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>A.appendChild(<div>B)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AB.appendChild(<div>C)'\n\t\t]);\n\t});\n\n\tit('should replace node in-between children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <section>B2</section> : <div>B1</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t<SetState />\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B1</div><div>C</div></div>`\n\t\t);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><section>B2</section><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>B1.remove()',\n\t\t\t'<section>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<section>B2, <div>C)'\n\t\t]);\n\t});\n\n\tit('should replace Fragment in-between children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<section>B3</section>\n\t\t\t\t\t\t\t<section>B4</section>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t<div>B1</div>\n\t\t\t\t\t\t\t<div>B2</div>\n\t\t\t\t\t\t</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t<SetState />\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\tdiv([div('A'), div('B1'), div('B2'), div('C')])\n\t\t);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\tdiv([div('A'), section('B3'), section('B4'), div('C')])\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>B1.remove()',\n\t\t\t'<div>B2.remove()',\n\t\t\t'<section>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<section>B3, <div>C)',\n\t\t\t'<section>.appendChild(#text)',\n\t\t\t'<div>AB3C.insertBefore(<section>B4, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert in-between children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <div>B</div> : null;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t<SetState />\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert in-between Fragments', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? [<div>B1</div>, <div>B2</div>] : null;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t<SetState />\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B1</div><div>B2</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B1, <div>C)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AB1C.insertBefore(<div>B2, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert in-between null children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <div>B</div> : null;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t{null}\n\t\t\t\t<SetState />\n\t\t\t\t{null}\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert Fragment in-between null children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<div>B1</div>\n\t\t\t\t\t\t\t<div>B2</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: null;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t{null}\n\t\t\t\t<SetState />\n\t\t\t\t{null}\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B1</div><div>B2</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B1, <div>C)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AB1C.insertBefore(<div>B2, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert in-between nested null children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <div>B</div> : null;\n\t\t\t}\n\t\t}\n\n\t\tfunction Outer() {\n\t\t\treturn <SetState />;\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t{null}\n\t\t\t\t<Outer />\n\t\t\t\t{null}\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert Fragment in-between nested null children', () => {\n\t\tlet update;\n\t\tclass SetState extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdate = () => this.setState({ active: true });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<div>B1</div>\n\t\t\t\t\t\t\t<div>B2</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: null;\n\t\t\t}\n\t\t}\n\n\t\tfunction Outer() {\n\t\t\treturn <SetState />;\n\t\t}\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t{null}\n\t\t\t\t<Outer />\n\t\t\t\t{null}\n\t\t\t\t<div>C</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\n\t\tclearLog();\n\t\tupdate();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B1</div><div>B2</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B1, <div>C)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AB1C.insertBefore(<div>B2, <div>C)'\n\t\t]);\n\t});\n\n\tit('should update at correct place', () => {\n\t\tlet updateA;\n\t\tclass A extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: true };\n\t\t\t\tupdateA = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <div>A</div> : <span>A2</span>;\n\t\t\t}\n\t\t}\n\n\t\tfunction B() {\n\t\t\treturn <div>B</div>;\n\t\t}\n\n\t\tfunction X(props) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\tfunction App(props) {\n\t\t\tlet b = props.condition ? <B /> : null;\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<X>\n\t\t\t\t\t\t<A />\n\t\t\t\t\t</X>\n\t\t\t\t\t<X>\n\t\t\t\t\t\t{b}\n\t\t\t\t\t\t<div>C</div>\n\t\t\t\t\t</X>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App condition={true} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A</div><div>B</div><div>C</div></div>`\n\t\t);\n\n\t\tclearLog();\n\t\trender(<App condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><div>A</div><div>C</div></div>`);\n\t\texpectDomLogToBe(['<div>B.remove()']);\n\n\t\tclearLog();\n\t\tupdateA();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(`<div><span>A2</span><div>C</div></div>`);\n\t\texpectDomLogToBe([\n\t\t\t'<div>A.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>C.insertBefore(<span>A2, <div>C)'\n\t\t]);\n\t});\n\n\tit('should update Fragment at correct place', () => {\n\t\tlet updateA;\n\t\tclass A extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: true };\n\t\t\t\tupdateA = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active\n\t\t\t\t\t? [<div>A1</div>, <div>A2</div>]\n\t\t\t\t\t: [<span>A3</span>, <span>A4</span>];\n\t\t\t}\n\t\t}\n\n\t\tfunction B() {\n\t\t\treturn <div>B</div>;\n\t\t}\n\n\t\tfunction X(props) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\tfunction App(props) {\n\t\t\tlet b = props.condition ? <B /> : null;\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<X>\n\t\t\t\t\t\t<A />\n\t\t\t\t\t</X>\n\t\t\t\t\t<X>\n\t\t\t\t\t\t{b}\n\t\t\t\t\t\t<div>C</div>\n\t\t\t\t\t</X>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App condition={true} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A1</div><div>A2</div><div>B</div><div>C</div></div>`\n\t\t);\n\n\t\tclearLog();\n\t\trender(<App condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><div>A1</div><div>A2</div><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe(['<div>B.remove()']);\n\n\t\tclearLog();\n\t\tupdateA();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t`<div><span>A3</span><span>A4</span><div>C</div></div>`\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>A1.remove()',\n\t\t\t'<div>A2.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>C.insertBefore(<span>A3, <div>C)',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>A3C.insertBefore(<span>A4, <div>C)'\n\t\t]);\n\t});\n\n\tit('should insert children correctly if sibling component DOM changes', () => {\n\t\t/** @type {() => void} */\n\t\tlet updateA;\n\t\tclass A extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: true };\n\t\t\t\tupdateA = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <div>A</div> : <span>A2</span>;\n\t\t\t}\n\t\t}\n\n\t\t/** @type {() => void} */\n\t\tlet updateB;\n\t\tclass B extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: false };\n\t\t\t\tupdateB = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.state.active ? <div>B</div> : null;\n\t\t\t}\n\t\t}\n\n\t\tfunction X(props) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<X>\n\t\t\t\t\t\t<A />\n\t\t\t\t\t</X>\n\t\t\t\t\t<X>\n\t\t\t\t\t\t<B />\n\t\t\t\t\t\t<div>C</div>\n\t\t\t\t\t</X>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(scratch.innerHTML).to.eql(div([div('A'), div('C')]), 'initial');\n\n\t\tclearLog();\n\t\tupdateB();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\tdiv([div('A'), div('B'), div('C')]),\n\t\t\t'updateB'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>AC.insertBefore(<div>B, <div>C)'\n\t\t]);\n\n\t\tclearLog();\n\t\tupdateA();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\tdiv([span('A2'), div('B'), div('C')]),\n\t\t\t'updateA'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>A.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>BC.insertBefore(<span>A2, <div>B)'\n\t\t]);\n\t});\n\n\tit('should correctly append children if last child changes DOM', () => {\n\t\t/** @type {() => void} */\n\t\tlet updateA;\n\t\tclass A extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: true };\n\t\t\t\tupdateA = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.active\n\t\t\t\t\t? [<div>A1</div>, <div>A2</div>]\n\t\t\t\t\t: [<span>A3</span>, <span>A4</span>];\n\t\t\t}\n\t\t}\n\n\t\t/** @type {() => void} */\n\t\tlet updateB;\n\t\tclass B extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: false };\n\t\t\t\tupdateB = () => this.setState(prev => ({ active: !prev.active }));\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<A />\n\t\t\t\t\t\t{this.state.active ? <div>B</div> : null}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<B />, scratch);\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t[div('A1'), div('A2')].join(''),\n\t\t\t'initial'\n\t\t);\n\n\t\tclearLog();\n\t\tupdateA();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t[span('A3'), span('A4')].join(''),\n\t\t\t'updateA'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>A1.remove()',\n\t\t\t'<div>A2.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>.appendChild(<span>A3)',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>A3.appendChild(<span>A4)'\n\t\t]);\n\n\t\tclearLog();\n\t\tupdateB();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eql(\n\t\t\t[span('A3'), span('A4'), div('B')].join(''),\n\t\t\t'updateB'\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>A3A4.appendChild(<div>B)'\n\t\t]);\n\t});\n\n\tit('should properly place conditional elements around strictly equal vnodes', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\n\t\tconst Children = () => (\n\t\t\t<Fragment>\n\t\t\t\t<div>Navigation</div>\n\t\t\t\t<div>Content</div>\n\t\t\t</Fragment>\n\t\t);\n\n\t\tclass Parent extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { panelPosition: 'bottom' };\n\t\t\t\ttoggle = this.tooglePanelPosition = this.tooglePanelPosition.bind(this);\n\t\t\t}\n\n\t\t\ttooglePanelPosition() {\n\t\t\t\tthis.setState({\n\t\t\t\t\tpanelPosition: this.state.panelPosition === 'top' ? 'bottom' : 'top'\n\t\t\t\t});\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.panelPosition === 'top' && <div>top panel</div>}\n\t\t\t\t\t\t{this.props.children}\n\t\t\t\t\t\t{this.state.panelPosition === 'bottom' && <div>bottom panel</div>}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst App = () => (\n\t\t\t<Parent>\n\t\t\t\t<Children />\n\t\t\t</Parent>\n\t\t);\n\n\t\tconst content = `<div>Navigation</div><div>Content</div>`;\n\t\tconst top = `<div><div>top panel</div>${content}</div>`;\n\t\tconst bottom = `<div>${content}<div>bottom panel</div></div>`;\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(bottom);\n\n\t\tclearLog();\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(top);\n\t\texpectDomLogToBe([\n\t\t\t'<div>bottom panel.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>NavigationContent.insertBefore(<div>top panel, <div>Navigation)'\n\t\t]);\n\n\t\tclearLog();\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(bottom);\n\t\texpectDomLogToBe([\n\t\t\t'<div>top panel.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>NavigationContent.appendChild(<div>bottom panel)'\n\t\t]);\n\n\t\tclearLog();\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(top);\n\t\texpectDomLogToBe([\n\t\t\t'<div>bottom panel.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>NavigationContent.insertBefore(<div>top panel, <div>Navigation)'\n\t\t]);\n\t});\n\n\tit('should efficiently unmount Fragment children', () => {\n\t\t// <div>1 => <span>1 and Fragment sibling unmounts. Does <span>1 get correct _nextDom pointer?\n\t\tfunction App({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\trender(<App condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(div([div(1), div(2), div('A')]));\n\n\t\tclearLog();\n\t\trender(<App condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(div([div(1), div('A')]));\n\t\texpectDomLogToBe(['<div>2.remove()']);\n\t});\n\n\tit('should efficiently unmount nested Fragment children', () => {\n\t\t// Fragment wrapping <div>2 and <div>3 unmounts. Does <div>1 get correct\n\t\t// _nextDom pointer to efficiently update DOM? _nextDom should be <div>A\n\t\tfunction App({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\tclearLog();\n\t\trender(<App condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(1), div(2), div(3), div('A'), div('B')])\n\t\t);\n\n\t\tclearLog();\n\t\trender(<App condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(div([div(1), div('A'), div('B')]));\n\t\texpectDomLogToBe(['<div>2.remove()', '<div>3.remove()']);\n\t});\n\n\tit('should properly unmount Fragment children around an unmounting null placeholder #2987', () => {\n\t\tconst arrayOf = (n, fill = 0) => new Array(n).fill(fill);\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\n\t\t\t\tthis.state = {\n\t\t\t\t\trenderFirstElement: true,\n\t\t\t\t\trenderLastElement: true,\n\t\t\t\t\tchildrenProps: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tarrayData: arrayOf(10).map((_, index) => ({\n\t\t\t\t\t\t\t\tkey: index + 5,\n\t\t\t\t\t\t\t\ttext: index + 5\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tarrayData: arrayOf(10).map((_, index) => ({\n\t\t\t\t\t\t\t\tkey: index + 15,\n\t\t\t\t\t\t\t\ttext: index + 15\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\t// eslint-disable-next-line react/no-did-mount-set-state\n\t\t\t\tthis.setState({\n\t\t\t\t\trenderFirstElement: false,\n\t\t\t\t\trenderLastElement: true,\n\t\t\t\t\tchildrenProps: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tarrayData: arrayOf(15).map((_, index) => ({\n\t\t\t\t\t\t\t\tkey: index,\n\t\t\t\t\t\t\t\ttext: index\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tarrayData: arrayOf(5).map((_, index) => ({\n\t\t\t\t\t\t\t\tkey: index + 15,\n\t\t\t\t\t\t\t\ttext: index + 15\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t});\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tconst { renderFirstElement, renderLastElement, childrenProps } =\n\t\t\t\t\tthis.state;\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{renderFirstElement && <div>This is the first div</div>}\n\t\t\t\t\t\t{childrenProps.map(({ arrayData }) => {\n\t\t\t\t\t\t\treturn arrayData.map(({ key, text }) => (\n\t\t\t\t\t\t\t\t<div key={key}>{text}</div>\n\t\t\t\t\t\t\t));\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{renderLastElement && <div>This is the last div</div>}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([\n\t\t\t\tdiv('This is the first div'),\n\t\t\t\tarrayOf(20)\n\t\t\t\t\t.map((_, i) => div(i + 5)) // 5 - 24\n\t\t\t\t\t.join(''),\n\t\t\t\tdiv('This is the last div')\n\t\t\t])\n\t\t);\n\n\t\t// Flush CDM setState call\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([\n\t\t\t\t// \"This is the first div\" is unmounted using a null placeholder pattern\n\t\t\t\tarrayOf(20)\n\t\t\t\t\t.map((_, i) => div(i)) // 0 - 19 (0 - 4 are inserted, 20 - 24 are unmounted)\n\t\t\t\t\t.join(''),\n\t\t\t\tdiv('This is the last div')\n\t\t\t])\n\t\t);\n\t});\n\n\tit('should efficiently place new children and unmount nested Fragment children', () => {\n\t\t// <div>4 is added and Fragment sibling unmounts. Does <div>4 get correct _nextDom pointer?\n\t\tfunction App({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<div>4</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\trender(<App condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(1), div(2), div(3), div('A'), div('B')])\n\t\t);\n\n\t\tclearLog();\n\t\trender(<App condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(1), div(4), div('A'), div('B')])\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>2.remove()',\n\t\t\t'<div>3.remove()',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>1AB.insertBefore(<div>4, <div>A)'\n\t\t]);\n\t});\n\n\tit('should not remove keyed elements', () => {\n\t\tlet deleteItem = () => {};\n\t\tconst Element = ({ item, deleteItem }) => (\n\t\t\t<Fragment>\n\t\t\t\t<div>Item: {item}</div>\n\t\t\t\t{''} {/* If you delete this, it works fine. */}\n\t\t\t</Fragment>\n\t\t);\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = {\n\t\t\t\t\titems: Array(10)\n\t\t\t\t\t\t.fill()\n\t\t\t\t\t\t.map((_, i) => i)\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender(_props, state) {\n\t\t\t\tdeleteItem = () => {\n\t\t\t\t\tthis.setState({\n\t\t\t\t\t\titems: this.state.items.filter(i => i !== this.state.items[2])\n\t\t\t\t\t});\n\t\t\t\t};\n\n\t\t\t\treturn state.items.map(item => (\n\t\t\t\t\t<Element item={item} deleteItem={deleteItem} key={item} />\n\t\t\t\t));\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>Item: 0</div> <div>Item: 1</div> <div>Item: 2</div> <div>Item: 3</div> <div>Item: 4</div> <div>Item: 5</div> <div>Item: 6</div> <div>Item: 7</div> <div>Item: 8</div> <div>Item: 9</div> '\n\t\t);\n\n\t\tclearLog();\n\t\tdeleteItem();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>Item: 0</div> <div>Item: 1</div> <div>Item: 3</div> <div>Item: 4</div> <div>Item: 5</div> <div>Item: 6</div> <div>Item: 7</div> <div>Item: 8</div> <div>Item: 9</div> '\n\t\t);\n\t\texpectDomLogToBe([\n\t\t\t'<div>Item: 2.remove()',\n\t\t\t'#text.remove()',\n\t\t\t'#text.remove()'\n\t\t]);\n\t});\n\n\tit('should efficiently unmount nested Fragment children when changing node type', () => {\n\t\t// <div>1 => <span>1 and Fragment sibling unmounts. Does <span>1 get correct _nextDom pointer?\n\t\tfunction App({ condition }) {\n\t\t\treturn condition\n\t\t\t\t? <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t\t\t<div>3</div>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>\n\t\t\t\t: <div>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<span>1</span>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</div>;\n\t\t}\n\n\t\trender(<App condition={true} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(1), div(2), div(3), div('A'), div('B')])\n\t\t);\n\n\t\tclearLog();\n\t\trender(<App condition={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(div([span(1), div('A'), div('B')]));\n\t\texpectDomLogToBe([\n\t\t\t'<div>1.remove()',\n\t\t\t'<div>2.remove()',\n\t\t\t'<div>3.remove()',\n\t\t\t'<span>.appendChild(#text)',\n\t\t\t'<div>AB.insertBefore(<span>1, <div>A)'\n\t\t]);\n\t});\n\n\tit('should swap nested fragments correctly', () => {\n\t\t/** @type {() => void} */\n\t\tlet swap;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { first: true };\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tif (this.state.first) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<p>1. Original item first paragraph</p>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t<p>2. Original item second paragraph</p>\n\t\t\t\t\t\t\t<button onClick={(swap = () => this.setState({ first: false }))}>\n\t\t\t\t\t\t\t\tClick me\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<p>1. Second item first paragraph</p>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<p>2. Second item second paragraph</p>\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t<button onClick={(swap = () => this.setState({ first: true }))}>\n\t\t\t\t\t\t\tClick me\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<p>1. Original item first paragraph</p><p>2. Original item second paragraph</p><button>Click me</button>'\n\t\t);\n\n\t\tswap();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<p>1. Second item first paragraph</p><p>2. Second item second paragraph</p><div></div><button>Click me</button>'\n\t\t);\n\n\t\tswap();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<p>1. Original item first paragraph</p><p>2. Original item second paragraph</p><button>Click me</button>'\n\t\t);\n\t});\n\n\tit('should efficiently unmount nested Fragment children when rerendering and reordering', () => {\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { condition: true };\n\t\t\t\ttoggle = () => this.setState({ condition: !this.state.condition });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.condition\n\t\t\t\t\t? <Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t\t<div>B</div>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t: <Fragment>\n\t\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t\t<div>A</div>\n\t\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t\t\t<div>1</div>\n\t\t\t\t\t\t\t<div>2</div>\n\t\t\t\t\t\t</Fragment>;\n\t\t\t}\n\t\t}\n\n\t\tclearLog();\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t[div(1), div('A'), div('B'), div(2)].join('')\n\t\t);\n\n\t\tclearLog();\n\t\ttoggle();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal([div('A'), div(1), div(2)].join(''));\n\t\texpectDomLogToBe(['<div>B.remove()', '<div>2A1.appendChild(<div>2)']);\n\t});\n\n\tit('Should retain content when parent rerenders', () => {\n\t\tlet toggle;\n\t\tconst ctx = createContext(null);\n\n\t\tclass Provider extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: props.value };\n\t\t\t\ttoggle = () => this.setState({ value: props.value + 1 });\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<ctx.Provider value={this.state.value}>{props.children}</ctx.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={1}>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<p>Hello world</p>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello world</p>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello world</p>');\n\t});\n\n\tit('Should retain content when parent rerenders w/ multiple children', () => {\n\t\tlet toggle;\n\t\tconst ctx = createContext(null);\n\n\t\tclass Provider extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: props.value };\n\t\t\t\ttoggle = () => this.setState({ value: props.value + 1 });\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<ctx.Provider value={this.state.value}>{props.children}</ctx.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={1}>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<p>Hello</p>\n\t\t\t\t\t\t\t<p>World</p>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello</p><p>World</p>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>Hello</p><p>World</p>');\n\t});\n\n\tit('Should retain content when parent rerenders w/ text children', () => {\n\t\tlet toggle;\n\t\tconst ctx = createContext(null);\n\n\t\tclass Provider extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: props.value };\n\t\t\t\ttoggle = () => this.setState({ value: props.value + 1 });\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<ctx.Provider value={this.state.value}>{props.children}</ctx.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={1}>\n\t\t\t\t\t\t<Fragment>Hello world</Fragment>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('Hello world');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('Hello world');\n\t});\n\n\tit('Should retain content when parent rerenders when deeper children are subscribed', () => {\n\t\tlet toggle;\n\t\tconst ctx = createContext(null);\n\n\t\tclass Provider extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: props.value };\n\t\t\t\ttoggle = () => this.setState({ value: props.value + 1 });\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn (\n\t\t\t\t\t<ctx.Provider value={this.state.value}>{props.children}</ctx.Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Provider value={1}>\n\t\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t\t<ctx.Consumer>\n\t\t\t\t\t\t\t\t{value => <p>I can count to {value}</p>}\n\t\t\t\t\t\t\t</ctx.Consumer>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Provider>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>I can count to 1</p>');\n\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>I can count to 2</p>');\n\t});\n});\n"
  },
  {
    "path": "test/browser/getDomSibling.test.jsx",
    "content": "import { createElement, render, Fragment } from '../../src/';\nimport { getDomSibling } from '../../src/component';\nimport { setupScratch, teardown } from '../_util/helpers';\n\ndescribe('getDomSibling', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tconst getRoot = dom => dom._children;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should find direct sibling', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>\n\t\t\t\t<div>B</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find direct text node sibling', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>A</div>B\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find nested text node sibling', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<div>A</div>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment>B</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find text node sibling with placeholder', () => {\n\t\trender(<div>A{null}B</div>, scratch);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find sibling with placeholder', () => {\n\t\trender(\n\t\t\t<div key=\"parent\">\n\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t{null}\n\t\t\t\t<div key=\"B\">B</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find sibling with nested placeholder', () => {\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">{null}</Fragment>\n\t\t\t\t<Fragment key=\"0.2\">\n\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find sibling in parent', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<div>A</div>\n\t\t\t\t</Fragment>\n\t\t\t\t<div>B</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tlet vnode = getRoot(scratch)._children[0]._children[0]._children[0];\n\t\texpect(getDomSibling(vnode)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find unrelated sibling from a DOM VNode', () => {\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<Fragment key=\"0.0.0\">\n\t\t\t\t\t\t<Fragment key=\"0.0.0.0\">\n\t\t\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">\n\t\t\t\t\t<Fragment key=\"0.1.0\" />\n\t\t\t\t\t<Fragment key=\"0.1.1\" />\n\t\t\t\t\t<Fragment key=\"0.1.2\" />\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.2\">\n\t\t\t\t\t<Fragment key=\"0.2.0\" />\n\t\t\t\t\t<Fragment key=\"0.2.1\" />\n\t\t\t\t\t<Fragment key=\"0.2.2\">\n\t\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet divAVNode =\n\t\t\tgetRoot(scratch)._children[0]._children[0]._children[0]._children[0]\n\t\t\t\t._children[0];\n\t\texpect(divAVNode.type).to.equal('div');\n\t\texpect(getDomSibling(divAVNode)).to.equalNode(\n\t\t\tscratch.firstChild.childNodes[1]\n\t\t);\n\t});\n\n\tit('should find unrelated sibling from a Fragment VNode', () => {\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<Fragment key=\"0.0.0\">\n\t\t\t\t\t\t<Fragment key=\"0.0.0.0\">\n\t\t\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">\n\t\t\t\t\t<Fragment key=\"0.1.0\">\n\t\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet fragment =\n\t\t\tgetRoot(scratch)._children[0]._children[0]._children[0]._children[0];\n\t\texpect(fragment.type).to.equal(Fragment);\n\t\texpect(getDomSibling(fragment)).to.equalNode(\n\t\t\tscratch.firstChild.childNodes[1]\n\t\t);\n\t});\n\n\tit('should find unrelated sibling from a Component VNode', () => {\n\t\tconst Foo = props => props.children;\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<Fragment key=\"0.0.0\">\n\t\t\t\t\t\t<Foo key=\"0.0.0.0\">\n\t\t\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t\t\t</Foo>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">\n\t\t\t\t\t<Fragment key=\"0.1.0\">\n\t\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet foo =\n\t\t\tgetRoot(scratch)._children[0]._children[0]._children[0]._children[0];\n\t\texpect(foo.type).to.equal(Foo);\n\t\texpect(getDomSibling(foo)).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find sibling through components', () => {\n\t\tconst Foo = props => props.children;\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Foo key=\"0.0\">\n\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t</Foo>\n\t\t\t\t<Foo key=\"0.1\" />\n\t\t\t\t<Foo key=\"0.2\">\n\t\t\t\t\t<Foo key=\"0.2.0\">\n\t\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t\t</Foo>\n\t\t\t\t</Foo>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet divAVNode = getRoot(scratch)._children[0]._children[0]._children[0];\n\t\texpect(divAVNode.type).to.equal('div');\n\t\texpect(getDomSibling(divAVNode)).to.equalNode(\n\t\t\tscratch.firstChild.childNodes[1]\n\t\t);\n\t});\n\n\tit('should find sibling rendered in Components that wrap JSX children', () => {\n\t\tconst Foo = props => <p key=\"p\">{props.children}</p>;\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t<Foo key=\"Foo\">\n\t\t\t\t\t<span key=\"span\">a span</span>\n\t\t\t\t</Foo>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet divAVNode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(divAVNode.type).to.equal('div');\n\n\t\tlet sibling = getDomSibling(divAVNode);\n\t\texpect(sibling).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should find sibling rendered in Components without JSX children', () => {\n\t\tconst Foo = props => <p key=\"p\">A paragraph</p>;\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t<Foo key=\"Foo\" />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet divAVNode = getRoot(scratch)._children[0]._children[0];\n\t\texpect(divAVNode.type).to.equal('div');\n\n\t\tlet sibling = getDomSibling(divAVNode);\n\t\texpect(sibling).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should climb through Components without JSX children', () => {\n\t\tconst divAVNode = <div key=\"A\">A</div>;\n\t\tconst Foo = () => divAVNode;\n\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Foo key=\"Foo\" />\n\t\t\t\t<div key=\"B\">B</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet sibling = getDomSibling(divAVNode);\n\t\texpect(sibling).to.equalNode(scratch.firstChild.childNodes[1]);\n\t});\n\n\tit('should return null if last sibling', () => {\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">\n\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.2\">\n\t\t\t\t\t<div key=\"C\">C</div>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tconst divCVNode = getRoot(scratch)._children[0]._children[2]._children[0];\n\t\texpect(getDomSibling(divCVNode)).to.equal(null);\n\t});\n\n\tit('should return null if no sibling', () => {\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<Fragment key=\"0.0.0\">\n\t\t\t\t\t\t<Fragment key=\"0.0.0.0\">\n\t\t\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">\n\t\t\t\t\t<Fragment key=\"0.1.0\">{null}</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet divAVNode =\n\t\t\tgetRoot(scratch)._children[0]._children[0]._children[0]._children[0]\n\t\t\t\t._children[0];\n\t\texpect(getDomSibling(divAVNode)).to.equal(null);\n\t});\n\n\tit('should return null if no sibling with lots of empty trees', () => {\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<Fragment key=\"0.0\">\n\t\t\t\t\t<Fragment key=\"0.0.0\">\n\t\t\t\t\t\t<Fragment key=\"0.0.0.0\">\n\t\t\t\t\t\t\t<div key=\"A\">A</div>\n\t\t\t\t\t\t</Fragment>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.1\">\n\t\t\t\t\t<Fragment key=\"0.1.0\" />\n\t\t\t\t\t<Fragment key=\"0.1.1\" />\n\t\t\t\t\t<Fragment key=\"0.1.2\" />\n\t\t\t\t</Fragment>\n\t\t\t\t<Fragment key=\"0.2\">\n\t\t\t\t\t<Fragment key=\"0.2.0\" />\n\t\t\t\t\t<Fragment key=\"0.2.1\" />\n\t\t\t\t\t<Fragment key=\"0.2.2\">{null}</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet divAVNode =\n\t\t\tgetRoot(scratch)._children[0]._children[0]._children[0]._children[0]\n\t\t\t\t._children[0];\n\t\texpect(getDomSibling(divAVNode)).to.equal(null);\n\t});\n\n\tit('should return null if current parent has no siblings (even if parent has siblings at same level)', () => {\n\t\tlet divAVNode = <div key=\"A\">A</div>;\n\n\t\trender(\n\t\t\t<div key=\"0\">\n\t\t\t\t<div key=\"0.0\">\n\t\t\t\t\t<div key=\"0.0.0\" />\n\t\t\t\t\t{divAVNode}\n\t\t\t\t\t<Fragment key=\"0.1.2\" />\n\t\t\t\t</div>\n\t\t\t\t<div key=\"0.1\">\n\t\t\t\t\t<Fragment key=\"0.1.0\" />\n\t\t\t\t\t<div key=\"B\">B</div>\n\t\t\t\t</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(getDomSibling(divAVNode)).to.equal(null);\n\t});\n});\n"
  },
  {
    "path": "test/browser/hydrate.test.jsx",
    "content": "import { createElement, hydrate, Fragment, Component } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport {\n\tsetupScratch,\n\tteardown,\n\tsortAttributes,\n\tserializeHtml,\n\tspyOnElementAttributes,\n\tcreateEvent\n} from '../_util/helpers';\nimport { ul, li, div } from '../_util/dom';\nimport { logCall, clearLog, getLog } from '../_util/logCall';\nimport { vi } from 'vitest';\n\ndescribe('hydrate()', () => {\n\t/** @type {HTMLElement} */\n\tlet scratch;\n\tlet attributesSpy;\n\n\tconst List = ({ children }) => <ul>{children}</ul>;\n\tconst ListItem = ({ children, onClick = null }) => (\n\t\t<li onClick={onClick}>{children}</li>\n\t);\n\n\tlet resetAppendChild;\n\tlet resetInsertBefore;\n\tlet resetRemove;\n\tlet resetRemoveText;\n\tlet resetRemoveComment;\n\tlet resetSetAttribute;\n\tlet resetRemoveAttribute;\n\tlet rerender;\n\n\tbeforeAll(() => {\n\t\tresetAppendChild = logCall(Element.prototype, 'appendChild');\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetRemove = logCall(Element.prototype, 'remove');\n\t\tresetRemoveComment = logCall(Comment.prototype, 'remove');\n\t\tresetRemoveText = logCall(Text.prototype, 'remove');\n\t\tresetSetAttribute = logCall(Element.prototype, 'setAttribute');\n\t\tresetRemoveAttribute = logCall(Element.prototype, 'removeAttribute');\n\t});\n\n\tafterAll(() => {\n\t\tresetAppendChild();\n\t\tresetInsertBefore();\n\t\tresetRemove();\n\t\tresetRemoveText();\n\t\tresetSetAttribute();\n\t\tresetRemoveAttribute();\n\t\tresetRemoveComment();\n\t});\n\n\tbeforeEach(() => {\n\t\trerender = setupRerender();\n\t\tscratch = setupScratch();\n\t\tattributesSpy = spyOnElementAttributes();\n\t\tclearLog();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\t// Test for preactjs/preact#4340\n\tit('should respect defaultValue in hydrate', () => {\n\t\tscratch.innerHTML = '<input value=\"foo\">';\n\t\thydrate(<input defaultValue=\"foo\" />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('foo');\n\t});\n\n\tit('should respect defaultChecked in hydrate', () => {\n\t\tscratch.innerHTML = '<input checked=\"true\">';\n\t\thydrate(<input defaultChecked />, scratch);\n\t\texpect(scratch.firstChild.checked).to.equal(true);\n\t});\n\n\tit('should reuse existing DOM', () => {\n\t\tconst onClickSpy = vi.fn();\n\t\tconst html = ul([li('1'), li('2'), li('3')]);\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\thydrate(\n\t\t\t<ul>\n\t\t\t\t<li>1</li>\n\t\t\t\t<li>2</li>\n\t\t\t\t<li onClick={onClickSpy}>3</li>\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(onClickSpy).not.toHaveBeenCalled();\n\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\n\t\texpect(onClickSpy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should skip comment nodes between dom nodes', () => {\n\t\tscratch.innerHTML = '<p><i>0</i><!-- c --><b>1</b></p>';\n\t\thydrate(\n\t\t\t<p>\n\t\t\t\t<i>0</i>\n\t\t\t\t<b>1</b>\n\t\t\t</p>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal('<p><i>0</i><b>1</b></p>');\n\t\texpect(getLog()).to.deep.equal(['Comment.remove()']);\n\t});\n\n\tit('should reuse existing DOM when given components', () => {\n\t\tconst onClickSpy = vi.fn();\n\t\tconst html = ul([li('1'), li('2'), li('3')]);\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t<ListItem onClick={onClickSpy}>3</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(onClickSpy).not.toHaveBeenCalled();\n\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\n\t\texpect(onClickSpy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should properly set event handlers to existing DOM when given components', () => {\n\t\tconst proto = Element.prototype;\n\t\tvi.spyOn(proto, 'addEventListener');\n\n\t\tconst clickHandlers = [vi.fn(), vi.fn(), vi.fn()];\n\n\t\tconst html = ul([li('1'), li('2'), li('3')]);\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<ListItem onClick={clickHandlers[0]}>1</ListItem>\n\t\t\t\t<ListItem onClick={clickHandlers[1]}>2</ListItem>\n\t\t\t\t<ListItem onClick={clickHandlers[2]}>3</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(proto.addEventListener).toHaveBeenCalledTimes(3);\n\t\texpect(clickHandlers[2]).not.toHaveBeenCalled();\n\n\t\tscratch.querySelector('li:last-child').dispatchEvent(createEvent('click'));\n\t\texpect(clickHandlers[2]).toHaveBeenCalledTimes(1);\n\t});\n\n\tit('should add missing nodes to existing DOM when hydrating', () => {\n\t\tconst html = ul([li('1')]);\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t<ListItem>3</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(ul([li('1'), li('2'), li('3')]));\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ul>1.appendChild(<li>2)',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ul>12.appendChild(<li>3)'\n\t\t]);\n\t});\n\n\tit('should remove extra nodes from existing DOM when hydrating', () => {\n\t\tconst html = ul([li('1'), li('2'), li('3'), li('4')]);\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t<ListItem>3</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(ul([li('1'), li('2'), li('3')]));\n\t\texpect(getLog()).to.deep.equal(['<li>4.remove()']);\n\t});\n\n\tit('should not update attributes on existing DOM', () => {\n\t\tscratch.innerHTML =\n\t\t\t'<div><span before-hydrate=\"test\" same-value=\"foo\" different-value=\"a\">Test</span></div>';\n\t\tlet vnode = (\n\t\t\t<div>\n\t\t\t\t<span same-value=\"foo\" different-value=\"b\" new-value=\"c\">\n\t\t\t\t\tTest\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t);\n\n\t\tclearLog();\n\t\thydrate(vnode, scratch);\n\n\t\texpect(attributesSpy).not.toHaveBeenCalled();\n\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t'<div><span before-hydrate=\"test\" different-value=\"a\" same-value=\"foo\">Test</span></div>'\n\t\t\t)\n\t\t);\n\t\texpect(getLog()).to.deep.equal([]);\n\t});\n\n\tit('should update class attribute via className prop', () => {\n\t\tscratch.innerHTML = '<div class=\"foo\">bar</div>';\n\t\thydrate(<div className=\"foo\">bar</div>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div class=\"foo\">bar</div>');\n\t});\n\n\tit('should correctly hydrate with Fragments', () => {\n\t\tconst html = ul([li('1'), li('2'), li('3'), li('4')]);\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\tconst clickHandlers = [vi.fn(), vi.fn(), vi.fn(), vi.fn()];\n\n\t\thydrate(\n\t\t\t<List>\n\t\t\t\t<ListItem onClick={clickHandlers[0]}>1</ListItem>\n\t\t\t\t<Fragment>\n\t\t\t\t\t<ListItem onClick={clickHandlers[1]}>2</ListItem>\n\t\t\t\t\t<ListItem onClick={clickHandlers[2]}>3</ListItem>\n\t\t\t\t</Fragment>\n\t\t\t\t<ListItem onClick={clickHandlers[3]}>4</ListItem>\n\t\t\t</List>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(clickHandlers[2]).not.toHaveBeenCalled();\n\n\t\tscratch\n\t\t\t.querySelector('li:nth-child(3)')\n\t\t\t.dispatchEvent(createEvent('click'));\n\n\t\texpect(clickHandlers[2]).toHaveBeenCalledOnce();\n\t});\n\n\tit('should correctly hydrate root Fragments', () => {\n\t\tconst html = [\n\t\t\tul([li('1'), li('2'), li('3'), li('4')]),\n\t\t\tdiv('sibling')\n\t\t].join('');\n\n\t\tscratch.innerHTML = html;\n\t\tclearLog();\n\n\t\tconst clickHandlers = [vi.fn(), vi.fn(), vi.fn(), vi.fn(), vi.fn()];\n\n\t\thydrate(\n\t\t\t<Fragment>\n\t\t\t\t<List>\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<ListItem onClick={clickHandlers[0]}>1</ListItem>\n\t\t\t\t\t\t<ListItem onClick={clickHandlers[1]}>2</ListItem>\n\t\t\t\t\t</Fragment>\n\t\t\t\t\t<ListItem onClick={clickHandlers[2]}>3</ListItem>\n\t\t\t\t\t<ListItem onClick={clickHandlers[3]}>4</ListItem>\n\t\t\t\t</List>\n\t\t\t\t<div onClick={clickHandlers[4]}>sibling</div>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(html);\n\t\texpect(getLog()).to.deep.equal([]);\n\t\texpect(clickHandlers[2]).not.toHaveBeenCalled();\n\n\t\tscratch\n\t\t\t.querySelector('li:nth-child(3)')\n\t\t\t.dispatchEvent(createEvent('click'));\n\n\t\texpect(clickHandlers[2]).toHaveBeenCalledTimes(1);\n\t\texpect(clickHandlers[4]).not.toHaveBeenCalled();\n\n\t\tscratch.querySelector('div').dispatchEvent(createEvent('click'));\n\n\t\texpect(clickHandlers[2]).toHaveBeenCalledTimes(1);\n\t\texpect(clickHandlers[4]).toHaveBeenCalledTimes(1);\n\t});\n\n\tit('should override incorrect pre-existing DOM with VNodes passed into render', () => {\n\t\tconst initialHtml = [\n\t\t\tdiv('sibling'),\n\t\t\tul([li('1'), li('4'), li('3'), li('2')])\n\t\t].join('');\n\n\t\tscratch.innerHTML = initialHtml;\n\t\tclearLog();\n\n\t\thydrate(\n\t\t\t<Fragment>\n\t\t\t\t<List>\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<ListItem>1</ListItem>\n\t\t\t\t\t\t<ListItem>2</ListItem>\n\t\t\t\t\t</Fragment>\n\t\t\t\t\t<ListItem>3</ListItem>\n\t\t\t\t\t<ListItem>4</ListItem>\n\t\t\t\t</List>\n\t\t\t\t<div>sibling</div>\n\t\t\t</Fragment>,\n\t\t\tscratch\n\t\t);\n\n\t\tconst finalHtml = [\n\t\t\tul([li('1'), li('2'), li('3'), li('4')]),\n\t\t\tdiv('sibling')\n\t\t].join('');\n\n\t\texpect(scratch.innerHTML).to.equal(finalHtml);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>sibling1234.insertBefore(<ul>1234, <div>sibling)'\n\t\t]);\n\t});\n\n\tit('should not merge attributes with node created by the DOM', () => {\n\t\tconst html = htmlString => {\n\t\t\tconst div = document.createElement('div');\n\t\t\tdiv.innerHTML = htmlString;\n\t\t\treturn div.firstChild;\n\t\t};\n\n\t\t// prettier-ignore\n\t\tconst DOMElement = html`<div><a foo=\"bar\"></a></div>`;\n\t\tscratch.appendChild(DOMElement);\n\n\t\tconst preactElement = (\n\t\t\t<div>\n\t\t\t\t<a />\n\t\t\t</div>\n\t\t);\n\n\t\thydrate(preactElement, scratch);\n\t\texpect(attributesSpy).not.toHaveBeenCalled();\n\t\texpect(scratch).to.have.property(\n\t\t\t'innerHTML',\n\t\t\t'<div><a foo=\"bar\"></a></div>'\n\t\t);\n\t});\n\n\tit('should attach event handlers', () => {\n\t\tlet spy = vi.fn();\n\t\tscratch.innerHTML = '<span>Test</span>';\n\t\tlet vnode = <span onClick={spy}>Test</span>;\n\n\t\thydrate(vnode, scratch);\n\n\t\tscratch.firstChild.click();\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\t// #2237\n\tit('should not redundantly add text nodes', () => {\n\t\tscratch.innerHTML = '<div id=\"test\"><p>hello bar</p></div>';\n\t\tconst element = document.getElementById('test');\n\t\tconst Component = props => <p>hello {props.foo}</p>;\n\n\t\thydrate(<Component foo=\"bar\" />, element);\n\t\texpect(element.innerHTML).to.equal('<p>hello bar</p>');\n\t});\n\n\tit('should not remove values', () => {\n\t\tscratch.innerHTML =\n\t\t\t'<select><option value=\"0\">Zero</option><option selected value=\"2\">Two</option></select>';\n\t\tconst App = () => {\n\t\t\tconst options = [\n\t\t\t\t{\n\t\t\t\t\tvalue: '0',\n\t\t\t\t\tlabel: 'Zero'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: '2',\n\t\t\t\t\tlabel: 'Two'\n\t\t\t\t}\n\t\t\t];\n\n\t\t\treturn (\n\t\t\t\t<select value=\"2\">\n\t\t\t\t\t{options.map(({ disabled, label, value }) => (\n\t\t\t\t\t\t<option key={label} disabled={disabled} value={value}>\n\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t))}\n\t\t\t\t</select>\n\t\t\t);\n\t\t};\n\n\t\thydrate(<App />, scratch);\n\t\texpect(sortAttributes(scratch.innerHTML)).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t'<select><option value=\"0\">Zero</option><option selected=\"\" value=\"2\">Two</option></select>'\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should deopt for trees introduced in hydrate (append)', () => {\n\t\tscratch.innerHTML = '<div id=\"test\"><p class=\"hi\">hello bar</p></div>';\n\t\tconst Component = props => <p class=\"hi\">hello {props.foo}</p>;\n\t\tconst element = document.getElementById('test');\n\t\thydrate(\n\t\t\t<Fragment>\n\t\t\t\t<Component foo=\"bar\" />\n\t\t\t\t<Component foo=\"baz\" />\n\t\t\t</Fragment>,\n\t\t\telement\n\t\t);\n\t\texpect(element.innerHTML).to.equal(\n\t\t\t'<p class=\"hi\">hello bar</p><p class=\"hi\">hello baz</p>'\n\t\t);\n\t});\n\n\tit('should deopt for trees introduced in hydrate (insert before)', () => {\n\t\tscratch.innerHTML = '<div id=\"test\"><p class=\"hi\">hello bar</p></div>';\n\t\tconst Component = props => <p class=\"hi\">hello {props.foo}</p>;\n\t\tconst element = document.getElementById('test');\n\t\thydrate(\n\t\t\t<Fragment>\n\t\t\t\t<Component foo=\"baz\" />\n\t\t\t\t<Component foo=\"bar\" />\n\t\t\t</Fragment>,\n\t\t\telement\n\t\t);\n\t\texpect(element.innerHTML).to.equal(\n\t\t\t'<p class=\"hi\">hello baz</p><p class=\"hi\">hello bar</p>'\n\t\t);\n\t});\n\n\tit('should skip comment nodes', () => {\n\t\tscratch.innerHTML = '<p>hello <!-- c -->foo</p>';\n\t\thydrate(<p>hello {'foo'}</p>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>hello foo</p>');\n\t\texpect(getLog()).to.deep.equal(['Comment.remove()']);\n\t});\n\n\tit('should skip over multiple comment nodes', () => {\n\t\tscratch.innerHTML = '<p>hello <!-- a --><!-- b -->foo</p>';\n\t\thydrate(<p>hello {'foo'}</p>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>hello foo</p>');\n\t\texpect(getLog()).to.deep.equal(['Comment.remove()', 'Comment.remove()']);\n\t});\n\n\tit('should work with error boundaries', () => {\n\t\tscratch.innerHTML = '<div>Hello, World!</div>';\n\t\tclass Root extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = {};\n\t\t\t}\n\n\t\t\tcomponentDidCatch(error) {\n\t\t\t\tthis.setState({ error });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tif (!this.state.error) {\n\t\t\t\t\treturn <App />;\n\t\t\t\t} else {\n\t\t\t\t\treturn <div>Error!</div>;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfunction App() {\n\t\t\tthrow Error();\n\t\t\treturn createElement('div', {}, 'Hello, World!');\n\t\t}\n\n\t\thydrate(<Root />, scratch);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>Error!</div>');\n\t});\n});\n"
  },
  {
    "path": "test/browser/isValidElement.test.js",
    "content": "import { createElement, isValidElement, Component } from 'preact';\nimport { isValidElementTests } from '../shared/isValidElementTests';\n\nisValidElementTests(expect, isValidElement, createElement, Component);\n"
  },
  {
    "path": "test/browser/keys.test.jsx",
    "content": "import { createElement, Component, render, createRef } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { logCall, clearLog, getLog } from '../_util/logCall';\nimport { div } from '../_util/dom';\nimport { vi } from 'vitest';\n\ndescribe('keys', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tlet rerender;\n\n\t/** @type {string[]} */\n\tlet ops;\n\n\tfunction createStateful(name) {\n\t\treturn class Stateful extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tif (typeof props.ref === 'function') {\n\t\t\t\t\tprops.ref(this);\n\t\t\t\t} else if (props.ref) {\n\t\t\t\t\tprops.ref.current = this;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcomponentDidUpdate() {\n\t\t\t\tif (typeof this.props.ref === 'function') {\n\t\t\t\t\tthis.props.ref(this);\n\t\t\t\t} else if (this.props.ref) {\n\t\t\t\t\tthis.props.ref.current = this;\n\t\t\t\t}\n\t\t\t\tops.push(`Update ${name}`);\n\t\t\t}\n\t\t\tcomponentDidMount() {\n\t\t\t\tops.push(`Mount ${name}`);\n\t\t\t}\n\t\t\tcomponentWillUnmount() {\n\t\t\t\tops.push(`Unmount ${name}`);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>{name}</div>;\n\t\t\t}\n\t\t};\n\t}\n\n\t/** @type {(props: {values: any[]}) => any} */\n\tconst List = props => (\n\t\t<ol>\n\t\t\t{props.values.map(value => (\n\t\t\t\t<li key={value}>{value}</li>\n\t\t\t))}\n\t\t</ol>\n\t);\n\n\t/**\n\t * Move an element in an array from one index to another\n\t * @param {any[]} values The array of values\n\t * @param {number} from The index to move from\n\t * @param {number} to The index to move to\n\t */\n\tfunction move(values, from, to) {\n\t\tconst value = values[from];\n\t\tvalues.splice(from, 1);\n\t\tvalues.splice(to, 0, value);\n\t}\n\n\tlet resetAppendChild;\n\tlet resetInsertBefore;\n\tlet resetRemoveChild;\n\tlet resetRemove;\n\tlet resetRemoveText;\n\n\tbeforeAll(() => {\n\t\tresetAppendChild = logCall(Element.prototype, 'appendChild');\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetRemoveChild = logCall(Element.prototype, 'removeChild');\n\t\tresetRemove = logCall(Element.prototype, 'remove');\n\t\tresetRemoveText = logCall(Text.prototype, 'remove');\n\t});\n\n\tafterAll(() => {\n\t\tresetAppendChild();\n\t\tresetInsertBefore();\n\t\tresetRemoveChild();\n\t\tresetRemove();\n\t\tresetRemoveText();\n\t});\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t\tops = [];\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tclearLog();\n\t});\n\n\t// https://fb.me/react-special-props\n\tit('should not pass key in props', () => {\n\t\tconst Foo = vi.fn(function Foo() {\n\t\t\treturn null;\n\t\t});\n\t\trender(<Foo key=\"foo\" />, scratch);\n\t\texpect(Foo.mock.calls[0][0]).to.deep.equal({});\n\t});\n\n\tit('should update in-place keyed DOM nodes', () => {\n\t\trender(\n\t\t\t<ul>\n\t\t\t\t<li key=\"0\">a</li>\n\t\t\t\t<li key=\"1\">b</li>\n\t\t\t\t<li key=\"2\">c</li>\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><li>a</li><li>b</li><li>c</li></ul>'\n\t\t);\n\n\t\trender(\n\t\t\t<ul>\n\t\t\t\t<li key=\"0\">x</li>\n\t\t\t\t<li key=\"1\">y</li>\n\t\t\t\t<li key=\"2\">z</li>\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><li>x</li><li>y</li><li>z</li></ul>'\n\t\t);\n\t});\n\n\t// See preactjs/preact-compat#21\n\tit('should remove orphaned keyed nodes', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>1</div>\n\t\t\t\t<li key=\"a\">a</li>\n\t\t\t\t<li key=\"b\">b</li>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<div>2</div>\n\t\t\t\t<li key=\"b\">b</li>\n\t\t\t\t<li key=\"c\">c</li>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>2</div><li>b</li><li>c</li></div>'\n\t\t);\n\t});\n\n\tit('should remove keyed nodes (#232)', () => {\n\t\tclass App extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tsetTimeout(() => this.setState({ opened: true, loading: true }), 10);\n\t\t\t\tsetTimeout(() => this.setState({ opened: true, loading: false }), 20);\n\t\t\t}\n\n\t\t\trender({ opened, loading }) {\n\t\t\t\treturn (\n\t\t\t\t\t<BusyIndicator id=\"app\" busy={loading}>\n\t\t\t\t\t\t<div>This div needs to be here for this to break</div>\n\t\t\t\t\t\t{opened && !loading && <div>{[]}</div>}\n\t\t\t\t\t</BusyIndicator>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass BusyIndicator extends Component {\n\t\t\trender({ children, busy }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div class={busy ? 'busy' : ''}>\n\t\t\t\t\t\t{children && children.length ? (\n\t\t\t\t\t\t\tchildren\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div class=\"busy-placeholder\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<div class=\"indicator\">\n\t\t\t\t\t\t\t<div>indicator</div>\n\t\t\t\t\t\t\t<div>indicator</div>\n\t\t\t\t\t\t\t<div>indicator</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\trender(<App opened loading />, scratch);\n\t\trender(<App opened />, scratch);\n\n\t\tconst html = String(scratch.firstChild.innerHTML).replace(/ class=\"\"/g, '');\n\t\texpect(html).to.equal(\n\t\t\t'<div>This div needs to be here for this to break</div><div></div><div class=\"indicator\"><div>indicator</div><div>indicator</div><div>indicator</div></div>'\n\t\t);\n\t});\n\n\tit('should append new keyed elements', () => {\n\t\tconst values = ['a', 'b'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('ab');\n\n\t\tvalues.push('c');\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abc');\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>ab.appendChild(<li>c)'\n\t\t]);\n\t});\n\n\tit('should remove keyed elements from the end', () => {\n\t\tconst values = ['a', 'b', 'c', 'd'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd');\n\n\t\tvalues.pop();\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abc');\n\t\texpect(getLog()).to.deep.equal(['<li>d.remove()']);\n\t});\n\n\tit('should prepend keyed elements to the beginning', () => {\n\t\tconst values = ['b', 'c'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('bc');\n\n\t\tvalues.unshift('a');\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abc');\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>bc.insertBefore(<li>a, <li>b)'\n\t\t]);\n\t});\n\n\tit('should remove keyed elements from the beginning', () => {\n\t\tconst values = ['z', 'a', 'b', 'c'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('zabc');\n\n\t\tvalues.shift();\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abc');\n\t\texpect(getLog()).to.deep.equal(['<li>z.remove()']);\n\t});\n\n\tit('should insert new keyed children in the middle', () => {\n\t\tconst values = ['a', 'c'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('ac');\n\n\t\tvalues.splice(1, 0, 'b');\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abc');\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>ac.insertBefore(<li>b, <li>c)'\n\t\t]);\n\t});\n\n\tit('should remove keyed children from the middle', () => {\n\t\tconst values = ['a', 'b', 'x', 'y', 'z', 'c', 'd'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abxyzcd');\n\n\t\tvalues.splice(2, 3);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd');\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>x.remove()',\n\t\t\t'<li>y.remove()',\n\t\t\t'<li>z.remove()'\n\t\t]);\n\t});\n\n\tit('should move keyed children to the beginning', () => {\n\t\tconst values = ['b', 'c', 'd', 'a'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('bcda');\n\n\t\tmove(values, values.length - 1, 0);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd');\n\t\texpect(getLog()).to.deep.equal(['<ol>bcda.insertBefore(<li>a, <li>b)']);\n\t});\n\n\tit('should move multiple keyed children to the beginning', () => {\n\t\tconst values = ['c', 'd', 'e', 'a', 'b'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('cdeab');\n\n\t\tmove(values, values.length - 1, 0);\n\t\tmove(values, values.length - 1, 0);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcde');\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<ol>cdeab.insertBefore(<li>a, <li>c)',\n\t\t\t'<ol>acdeb.insertBefore(<li>b, <li>c)'\n\t\t]);\n\t});\n\n\tit('should swap keyed children efficiently', () => {\n\t\trender(<List values={['a', 'b']} />, scratch);\n\t\texpect(scratch.textContent).to.equal('ab');\n\n\t\tclearLog();\n\n\t\trender(<List values={['b', 'a']} />, scratch);\n\t\texpect(scratch.textContent).to.equal('ba');\n\n\t\texpect(getLog()).to.deep.equal(['<ol>ab.appendChild(<li>a)']);\n\t});\n\n\tit('should swap existing keyed children in the middle of a list efficiently', () => {\n\t\tconst values = ['a', 'b', 'c', 'd'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd');\n\n\t\t// swap\n\t\tmove(values, 1, 2);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('acbd', 'initial swap');\n\t\texpect(getLog()).to.deep.equal(\n\t\t\t['<ol>abcd.insertBefore(<li>b, <li>d)'],\n\t\t\t'initial swap'\n\t\t);\n\n\t\t// swap back\n\t\tmove(values, 2, 1);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd', 'swap back');\n\t\texpect(getLog()).to.deep.equal(\n\t\t\t['<ol>acbd.insertBefore(<li>c, <li>d)'],\n\t\t\t'swap back'\n\t\t);\n\t});\n\n\tit('should move keyed children to the end of the list', () => {\n\t\tconst values = ['a', 'b', 'c', 'd'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd');\n\n\t\t// move to end\n\t\tmove(values, 0, values.length - 1);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('bcda', 'move to end');\n\t\texpect(getLog()).to.deep.equal(\n\t\t\t['<ol>abcd.appendChild(<li>a)'],\n\t\t\t'move to end'\n\t\t);\n\n\t\t// move to beginning\n\t\tmove(values, values.length - 1, 0);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcd', 'move to beginning');\n\t\texpect(getLog()).to.deep.equal(\n\t\t\t['<ol>bcda.insertBefore(<li>a, <li>b)'],\n\t\t\t'move to beginning'\n\t\t);\n\t});\n\n\tit('should move keyed children to the beginning on longer list', () => {\n\t\t// Preact v10 worst case\n\t\tconst values = ['a', 'b', 'c', 'd', 'e', 'f'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcdef');\n\n\t\tmove(values, 4, 1);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('aebcdf');\n\t\texpect(getLog()).to.deep.equal(['<ol>abcdef.insertBefore(<li>e, <li>b)']);\n\t});\n\n\tit('should move keyed children to the end on longer list', () => {\n\t\tconst values = ['a', 'b', 'c', 'd', 'e', 'f'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('abcdef');\n\n\t\tmove(values, 1, values.length - 2);\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('acdebf');\n\t\texpect(getLog()).to.deep.equal(['<ol>abcdef.insertBefore(<li>b, <li>f)']);\n\t});\n\n\tit('should reverse keyed children effectively', () => {\n\t\tconst values = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal(values.join(''));\n\n\t\t// reverse list\n\t\tvalues.reverse();\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal(values.join(''));\n\t\t// expect(getLog()).to.have.lengthOf(9);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<ol>abcdefghij.insertBefore(<li>j, <li>a)',\n\t\t\t'<ol>jabcdefghi.insertBefore(<li>i, <li>a)',\n\t\t\t'<ol>jiabcdefgh.insertBefore(<li>h, <li>a)',\n\t\t\t'<ol>jihabcdefg.insertBefore(<li>g, <li>a)',\n\t\t\t'<ol>jihgabcdef.insertBefore(<li>f, <li>a)',\n\t\t\t'<ol>jihgfabcde.insertBefore(<li>e, <li>a)',\n\t\t\t'<ol>jihgfeabcd.insertBefore(<li>d, <li>a)',\n\t\t\t'<ol>jihgfedabc.insertBefore(<li>c, <li>a)',\n\t\t\t'<ol>jihgfedcab.appendChild(<li>a)'\n\t\t]);\n\t});\n\n\tit('should properly remove children of memoed components', () => {\n\t\tconst values = [1, 2, 3, 4, 5, 6, 7, 8, 9];\n\n\t\tclass Item extends Component {\n\t\t\tshouldComponentUpdate(props) {\n\t\t\t\treturn props.value !== this.props.value;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <li>{this.props.value}</li>;\n\t\t\t}\n\t\t}\n\n\t\tfunction App({ values }) {\n\t\t\treturn (\n\t\t\t\t<ul>\n\t\t\t\t\t{values.map(value => (\n\t\t\t\t\t\t<Item key={value} value={value} />\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t);\n\t\t}\n\n\t\trender(<App values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal(values.join(''));\n\n\t\tclearLog();\n\t\tvalues.splice(3, 3);\n\n\t\trender(<App values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal(values.join(''));\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>4.remove()',\n\t\t\t'<li>5.remove()',\n\t\t\t'<li>6.remove()'\n\t\t]);\n\t});\n\n\tit(\"should not preserve state when a component's keys are different\", () => {\n\t\tconst Stateful = createStateful('Stateful');\n\n\t\tfunction Foo({ condition }) {\n\t\t\treturn condition ? <Stateful key=\"a\" /> : <Stateful key=\"b\" />;\n\t\t}\n\n\t\tops = [];\n\t\trender(<Foo condition />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Stateful</div>');\n\t\texpect(ops).to.deep.equal(['Mount Stateful'], 'initial mount');\n\n\t\tops = [];\n\t\trender(<Foo condition={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Stateful</div>');\n\t\texpect(ops).to.deep.equal(\n\t\t\t['Unmount Stateful', 'Mount Stateful'],\n\t\t\t'switching keys 1'\n\t\t);\n\n\t\tops = [];\n\t\trender(<Foo condition />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Stateful</div>');\n\t\texpect(ops).to.deep.equal(\n\t\t\t['Unmount Stateful', 'Mount Stateful'],\n\t\t\t'switching keys 2'\n\t\t);\n\t});\n\n\tit('should not preserve state between an unkeyed and keyed component', () => {\n\t\t// React and Preact v8 behavior: https://codesandbox.io/s/57prmy5mx\n\n\t\tconst Stateful = createStateful('Stateful');\n\n\t\tfunction Foo({ keyed }) {\n\t\t\treturn keyed ? <Stateful key=\"a\" /> : <Stateful />;\n\t\t}\n\n\t\tops = [];\n\t\trender(<Foo keyed />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Stateful</div>');\n\t\texpect(ops).to.deep.equal(['Mount Stateful'], 'initial mount with key');\n\n\t\tops = [];\n\t\trender(<Foo keyed={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Stateful</div>');\n\t\texpect(ops).to.deep.equal(\n\t\t\t['Unmount Stateful', 'Mount Stateful'],\n\t\t\t'switching from keyed to unkeyed'\n\t\t);\n\n\t\tops = [];\n\t\trender(<Foo keyed />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Stateful</div>');\n\t\texpect(ops).to.deep.equal(\n\t\t\t['Unmount Stateful', 'Mount Stateful'],\n\t\t\t'switching from unkeyed to keyed'\n\t\t);\n\t});\n\n\tit('should not preserve state when keys change with multiple children', () => {\n\t\t// React & Preact v8 behavior: https://codesandbox.io/s/8l3p6lz9kj\n\n\t\tconst Stateful1 = createStateful('Stateful1');\n\t\tconst Stateful2 = createStateful('Stateful2');\n\n\t\tlet Stateful1Ref;\n\t\tlet Stateful2Ref;\n\t\tlet Stateful1MovedRef;\n\t\tlet Stateful2MovedRef;\n\n\t\tfunction Foo({ moved }) {\n\t\t\treturn moved ? (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Stateful1 key=\"c\" ref={c => (Stateful1MovedRef = c)} />\n\t\t\t\t\t<div>2</div>\n\t\t\t\t\t<Stateful2 key=\"d\" ref={c => (Stateful2MovedRef = c)} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Stateful1 key=\"a\" ref={c => (Stateful1Ref = c)} />\n\t\t\t\t\t<div>2</div>\n\t\t\t\t\t<Stateful2 key=\"b\" ref={c => (Stateful2Ref = c)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst expectedHtml = div([\n\t\t\tdiv(1),\n\t\t\tdiv('Stateful1'),\n\t\t\tdiv(2),\n\t\t\tdiv('Stateful2')\n\t\t]);\n\n\t\tops = [];\n\t\trender(<Foo moved={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(expectedHtml);\n\t\texpect(ops).to.deep.equal(['Mount Stateful1', 'Mount Stateful2']);\n\t\texpect(Stateful1Ref).to.exist;\n\t\texpect(Stateful2Ref).to.exist;\n\n\t\tops = [];\n\t\trender(<Foo moved />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(expectedHtml);\n\t\texpect(ops).to.deep.equal([\n\t\t\t'Unmount Stateful1',\n\t\t\t'Unmount Stateful2',\n\t\t\t'Mount Stateful1',\n\t\t\t'Mount Stateful2'\n\t\t]);\n\t\texpect(Stateful1MovedRef).to.not.equal(Stateful1Ref);\n\t\texpect(Stateful2MovedRef).to.not.equal(Stateful2Ref);\n\n\t\tops = [];\n\t\trender(<Foo moved={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(expectedHtml);\n\t\texpect(ops).to.deep.equal([\n\t\t\t'Unmount Stateful1',\n\t\t\t'Unmount Stateful2',\n\t\t\t'Mount Stateful1',\n\t\t\t'Mount Stateful2'\n\t\t]);\n\t\texpect(Stateful1Ref).to.not.equal(Stateful1MovedRef);\n\t\texpect(Stateful2Ref).to.not.equal(Stateful2MovedRef);\n\t});\n\n\tit('should preserve state when moving keyed children components', () => {\n\t\t// React & Preact v8 behavior: https://codesandbox.io/s/8l3p6lz9kj\n\n\t\tconst Stateful1 = createStateful('Stateful1');\n\t\tconst Stateful2 = createStateful('Stateful2');\n\n\t\tlet Stateful1Ref;\n\t\tlet Stateful2Ref;\n\t\tlet Stateful1MovedRef;\n\t\tlet Stateful2MovedRef;\n\n\t\tfunction Foo({ moved }) {\n\t\t\treturn moved ? (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Stateful2\n\t\t\t\t\t\tkey=\"b\"\n\t\t\t\t\t\tref={c => (c ? (Stateful2MovedRef = c) : undefined)}\n\t\t\t\t\t/>\n\t\t\t\t\t<div>2</div>\n\t\t\t\t\t<Stateful1\n\t\t\t\t\t\tkey=\"a\"\n\t\t\t\t\t\tref={c => (c ? (Stateful1MovedRef = c) : undefined)}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Stateful1 key=\"a\" ref={c => (c ? (Stateful1Ref = c) : undefined)} />\n\t\t\t\t\t<div>2</div>\n\t\t\t\t\t<Stateful2 key=\"b\" ref={c => (c ? (Stateful2Ref = c) : undefined)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst htmlForFalse = div([\n\t\t\tdiv(1),\n\t\t\tdiv('Stateful1'),\n\t\t\tdiv(2),\n\t\t\tdiv('Stateful2')\n\t\t]);\n\n\t\tconst htmlForTrue = div([\n\t\t\tdiv(1),\n\t\t\tdiv('Stateful2'),\n\t\t\tdiv(2),\n\t\t\tdiv('Stateful1')\n\t\t]);\n\n\t\tops = [];\n\t\trender(<Foo moved={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForFalse);\n\t\texpect(ops).to.deep.equal(['Mount Stateful1', 'Mount Stateful2']);\n\t\texpect(Stateful1Ref).to.exist;\n\t\texpect(Stateful2Ref).to.exist;\n\n\t\tops = [];\n\t\trender(<Foo moved />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForTrue);\n\t\texpect(ops).to.deep.equal(['Update Stateful2', 'Update Stateful1']);\n\t\texpect(Stateful1MovedRef).to.equal(Stateful1Ref);\n\t\texpect(Stateful2MovedRef).to.equal(Stateful2Ref);\n\n\t\tops = [];\n\t\trender(<Foo moved={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(htmlForFalse);\n\t\texpect(ops).to.deep.equal(['Update Stateful1', 'Update Stateful2']);\n\t\texpect(Stateful1Ref).to.equal(Stateful1MovedRef);\n\t\texpect(Stateful2Ref).to.equal(Stateful2MovedRef);\n\t});\n\n\tit('should effectively iterate on large lists', async () => {\n\t\tconst newItems = () =>\n\t\t\tArray(100)\n\t\t\t\t.fill(0)\n\t\t\t\t.map((item, i) => i);\n\n\t\tlet set,\n\t\t\tmutatedNodes = [];\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { items: newItems() };\n\t\t\t\tset = this.set = this.set.bind(this);\n\t\t\t\tthis.ref = createRef();\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\tconst observer = new MutationObserver(listener);\n\t\t\t\tobserver.observe(this.ref.current, { childList: true });\n\n\t\t\t\tfunction listener(mutations) {\n\t\t\t\t\tfor (const { addedNodes } of mutations) {\n\t\t\t\t\t\tfor (const node of Array.from(addedNodes)) {\n\t\t\t\t\t\t\tmutatedNodes.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tset() {\n\t\t\t\tconst currentItems = this.state.items;\n\t\t\t\tconst items = newItems().filter(id => {\n\t\t\t\t\tconst isVisible = currentItems.includes(id);\n\t\t\t\t\treturn id >= 20 && id <= 80 ? !isVisible : isVisible;\n\t\t\t\t});\n\t\t\t\tthis.setState({ items });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div ref={this.ref}>\n\t\t\t\t\t\t{this.state.items.map(i => (\n\t\t\t\t\t\t\t<div key={i}>{i}</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tset();\n\t\trerender();\n\n\t\treturn new Promise(resolve => {\n\t\t\tsetTimeout(() => {\n\t\t\t\texpect(mutatedNodes.length).to.equal(0);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t});\n\n\tit('should effectively iterate on large component lists', async () => {\n\t\tconst newItems = () =>\n\t\t\tArray(100)\n\t\t\t\t.fill(0)\n\t\t\t\t.map((item, i) => i);\n\n\t\tlet set,\n\t\t\tmutatedNodes = [];\n\n\t\tconst Row = ({ i }) => <p>{i}</p>;\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { items: newItems() };\n\t\t\t\tset = this.set = this.set.bind(this);\n\t\t\t\tthis.ref = createRef();\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\tconst observer = new MutationObserver(listener);\n\t\t\t\tobserver.observe(this.ref.current, { childList: true });\n\n\t\t\t\tfunction listener(mutations) {\n\t\t\t\t\tfor (const { addedNodes } of mutations) {\n\t\t\t\t\t\tfor (const node of Array.from(addedNodes)) {\n\t\t\t\t\t\t\tmutatedNodes.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tset() {\n\t\t\t\tconst currentItems = this.state.items;\n\t\t\t\tconst items = newItems().filter(id => {\n\t\t\t\t\tconst isVisible = currentItems.includes(id);\n\t\t\t\t\treturn id >= 20 && id <= 80 ? !isVisible : isVisible;\n\t\t\t\t});\n\t\t\t\tthis.setState({ items });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div ref={this.ref}>\n\t\t\t\t\t\t{this.state.items.map(i => (\n\t\t\t\t\t\t\t<Row key={i} i={i} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tset();\n\t\trerender();\n\n\t\treturn new Promise(resolve => {\n\t\t\tsetTimeout(() => {\n\t\t\t\texpect(mutatedNodes.length).to.equal(0);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t});\n\n\tit('should not preserve state when switching between keyed and unkeyed components as children', () => {\n\t\t// React & Preact v8 behavior: https://codesandbox.io/s/8l3p6lz9kj\n\n\t\tconst Stateful1 = createStateful('Stateful1');\n\t\tconst Stateful2 = createStateful('Stateful2');\n\n\t\tlet Stateful1Ref;\n\t\tlet Stateful2Ref;\n\t\tlet Stateful1MovedRef;\n\t\tlet Stateful2MovedRef;\n\n\t\tfunction Foo({ unkeyed }) {\n\t\t\treturn unkeyed ? (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Stateful1 ref={c => (Stateful2MovedRef = c)} />\n\t\t\t\t\t<div>2</div>\n\t\t\t\t\t<Stateful2 ref={c => (Stateful1MovedRef = c)} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Stateful1 key=\"a\" ref={c => (Stateful1Ref = c)} />\n\t\t\t\t\t<div>2</div>\n\t\t\t\t\t<Stateful2 key=\"b\" ref={c => (Stateful2Ref = c)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst expectedHtml = div([\n\t\t\tdiv(1),\n\t\t\tdiv('Stateful1'),\n\t\t\tdiv(2),\n\t\t\tdiv('Stateful2')\n\t\t]);\n\n\t\tops = [];\n\t\trender(<Foo unkeyed={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(expectedHtml);\n\t\texpect(ops).to.deep.equal(['Mount Stateful1', 'Mount Stateful2']);\n\t\texpect(Stateful1Ref).to.exist;\n\t\texpect(Stateful2Ref).to.exist;\n\n\t\tops = [];\n\t\trender(<Foo unkeyed />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(expectedHtml);\n\t\texpect(ops).to.deep.equal([\n\t\t\t'Unmount Stateful1',\n\t\t\t'Unmount Stateful2',\n\t\t\t'Mount Stateful1',\n\t\t\t'Mount Stateful2'\n\t\t]);\n\t\texpect(Stateful1MovedRef).to.not.equal(Stateful1Ref);\n\t\texpect(Stateful2MovedRef).to.not.equal(Stateful2Ref);\n\n\t\tops = [];\n\t\trender(<Foo unkeyed={false} />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(expectedHtml);\n\t\texpect(ops).to.deep.equal([\n\t\t\t'Unmount Stateful1',\n\t\t\t'Unmount Stateful2',\n\t\t\t'Mount Stateful1',\n\t\t\t'Mount Stateful2'\n\t\t]);\n\t\texpect(Stateful1Ref).to.not.equal(Stateful1MovedRef);\n\t\texpect(Stateful2Ref).to.not.equal(Stateful2MovedRef);\n\t});\n\n\tit('should handle full reorders', () => {\n\t\tconst keys = {\n\t\t\tApple: `Apple_1`,\n\t\t\tOrange: `Orange_1`,\n\t\t\tBanana: `Banana_1`,\n\t\t\tGrape: `Grape_1`,\n\t\t\tKiwi: `Kiwi_1`,\n\t\t\tCherry: `Cherry_1`\n\t\t};\n\n\t\tlet sort;\n\n\t\tclass App extends Component {\n\t\t\torder;\n\n\t\t\tstate = { items: ['Apple', 'Grape', 'Cherry', 'Orange', 'Banana'] };\n\n\t\t\tsort() {\n\t\t\t\tthis.order = this.order === 'ASC' ? 'DESC' : 'ASC';\n\t\t\t\tconst items = [...this.state.items].sort((a, b) =>\n\t\t\t\t\tthis.order === 'ASC' ? a.localeCompare(b) : b.localeCompare(a)\n\t\t\t\t);\n\t\t\t\tthis.setState({ items });\n\t\t\t}\n\n\t\t\trender(_, { items }) {\n\t\t\t\tsort = this.sort.bind(this);\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{items.map(item => (\n\t\t\t\t\t\t\t<div key={keys[item]}>{item}</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst expected = values => {\n\t\t\treturn values.map(key => `<div>${key}</div>`).join('');\n\t\t};\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.eq(\n\t\t\t`<div>${expected(['Apple', 'Grape', 'Cherry', 'Orange', 'Banana'])}</div>`\n\t\t);\n\n\t\tlet sorted = ['Apple', 'Grape', 'Cherry', 'Orange', 'Banana'].sort((a, b) =>\n\t\t\ta.localeCompare(b)\n\t\t);\n\t\tsort();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eq(`<div>${expected(sorted)}</div>`);\n\n\t\tsorted = ['Apple', 'Grape', 'Cherry', 'Orange', 'Banana'].sort((a, b) =>\n\t\t\tb.localeCompare(a)\n\t\t);\n\t\tsort();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.eq(`<div>${expected(sorted)}</div>`);\n\t});\n\n\tit('should handle keyed replacements', () => {\n\t\tconst actions = [];\n\t\tclass Comp extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tactions.push('mounted ' + this.props.i);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = props => {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={props.y} i={1} />\n\t\t\t\t\t{false}\n\t\t\t\t\t<Comp i={2} />\n\t\t\t\t\t<Comp i={3} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"2\" />, scratch);\n\t\texpect(actions).to.deep.equal([\n\t\t\t'mounted 1',\n\t\t\t'mounted 2',\n\t\t\t'mounted 3',\n\t\t\t'mounted 1'\n\t\t]);\n\t});\n\n\tit('should handle hole prepend', () => {\n\t\tconst actions = [];\n\t\tclass Comp extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tactions.push('mounted ' + this.props.i);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = props => {\n\t\t\treturn props.y === '2' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t{null}\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"2\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\t});\n\n\tit('should handle hole replace', () => {\n\t\tconst actions = [];\n\t\tclass Comp extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tactions.push('mounted ' + this.props.i);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = props => {\n\t\t\treturn props.y === '1' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t{null}\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"2\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal([\n\t\t\t'mounted 1',\n\t\t\t'mounted 2',\n\t\t\t'mounted 3',\n\t\t\t'mounted 2'\n\t\t]);\n\t});\n\n\tit('should handle hole insert', () => {\n\t\tconst actions = [];\n\t\tclass Comp extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tactions.push('mounted ' + this.props.i);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = props => {\n\t\t\treturn props.y === '2' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t{null}\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"2\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\t});\n\n\tit('should handle hole apppend', () => {\n\t\tconst actions = [];\n\t\tclass Comp extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tactions.push('mounted ' + this.props.i);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = props => {\n\t\t\treturn props.y === '2' ? (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<Comp key={1} i={1} />\n\t\t\t\t\t<Comp key={2} i={2} />\n\t\t\t\t\t<Comp key={3} i={3} />\n\t\t\t\t\t{null}\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"2\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\t});\n\n\t// Issue #4973: Test growing list diff\n\tit('should correctly diff a growing list of keyed children', () => {\n\t\tlet values = [0, 1, 2, 3, 4];\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('01234');\n\n\t\tvalues = [2, 3, 4, 5, 6];\n\t\tclearLog();\n\n\t\trender(<List values={values} />, scratch);\n\t\texpect(scratch.textContent).to.equal('23456');\n\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<li>0.remove()',\n\t\t\t'<li>1.remove()',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>234.appendChild(<li>5)',\n\t\t\t'<li>.appendChild(#text)',\n\t\t\t'<ol>2345.appendChild(<li>6)'\n\t\t]);\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentDidCatch.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component, Fragment } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi, expect } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/* eslint-disable react/display-name */\n\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#componentDidCatch', () => {\n\t\t/** @type {Error} */\n\t\tlet expectedError;\n\n\t\t/** @type {typeof import('../../../').Component} */\n\t\tlet ThrowErr;\n\t\tclass Receiver extends Component {\n\t\t\tcomponentDidCatch(error) {\n\t\t\t\tthis.setState({ error });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn this.state.error\n\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t: this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tlet thrower;\n\n\t\tvi.spyOn(Receiver.prototype, 'componentDidCatch');\n\t\tvi.spyOn(Receiver.prototype, 'render');\n\n\t\tfunction throwExpectedError() {\n\t\t\tthrow (expectedError = new Error('Error!'));\n\t\t}\n\n\t\tbeforeEach(() => {\n\t\t\tThrowErr = class ThrowErr extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthrower = this;\n\t\t\t\t}\n\n\t\t\t\tcomponentDidCatch() {\n\t\t\t\t\texpect.fail(\"Throwing component should not catch it's own error.\");\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>ThrowErr: componentDidCatch</div>;\n\t\t\t\t}\n\t\t\t};\n\t\t\tvi.spyOn(ThrowErr.prototype, 'componentDidCatch');\n\n\t\t\texpectedError = undefined;\n\n\t\t\tReceiver.prototype.componentDidCatch.mockClear();\n\t\t\tReceiver.prototype.render.mockClear();\n\t\t});\n\n\t\tafterEach(() => {\n\t\t\texpect(\n\t\t\t\tThrowErr.prototype.componentDidCatch,\n\t\t\t\t\"Throwing component should not catch it's own error.\"\n\t\t\t).not.toHaveBeenCalled();\n\t\t\tthrower = undefined;\n\t\t});\n\n\t\tit('should be called when child fails in constructor', () => {\n\t\t\tclass ThrowErr extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t\tcomponentDidCatch() {\n\t\t\t\t\texpect.fail(\"Throwing component should not catch it's own error\");\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\t// https://github.com/preactjs/preact/issues/1570\n\t\tit('should handle double child throws', () => {\n\t\t\tconst Child = ({ i }) => {\n\t\t\t\tthrow new Error(`error! ${i}`);\n\t\t\t};\n\n\t\t\tconst fn = () =>\n\t\t\t\trender(\n\t\t\t\t\t<Receiver>\n\t\t\t\t\t\t{[1, 2].map(i => (\n\t\t\t\t\t\t\t<Child key={i} i={i} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Receiver>,\n\t\t\t\t\tscratch\n\t\t\t\t);\n\t\t\texpect(fn).to.not.throw();\n\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('Error: error! 2');\n\t\t});\n\n\t\tit('should be called when child fails in componentWillMount', () => {\n\t\t\tThrowErr.prototype.componentWillMount = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in render', () => {\n\t\t\tThrowErr.prototype.render = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentDidMount', () => {\n\t\t\tThrowErr.prototype.componentDidMount = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in getDerivedStateFromProps', () => {\n\t\t\tThrowErr.getDerivedStateFromProps = throwExpectedError;\n\n\t\t\tvi.spyOn(ThrowErr.prototype, 'render');\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t\texpect(ThrowErr.prototype.render).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should be called when child fails in getSnapshotBeforeUpdate', () => {\n\t\t\tThrowErr.prototype.getSnapshotBeforeUpdate = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\tthrower.forceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentDidUpdate', () => {\n\t\t\tThrowErr.prototype.componentDidUpdate = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tthrower.forceUpdate();\n\t\t\trerender();\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentWillUpdate', () => {\n\t\t\tThrowErr.prototype.componentWillUpdate = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tthrower.forceUpdate();\n\t\t\trerender();\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentWillReceiveProps', () => {\n\t\t\tThrowErr.prototype.componentWillReceiveProps = throwExpectedError;\n\n\t\t\tlet receiver;\n\t\t\tclass Receiver extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { foo: 'bar' };\n\t\t\t\t\treceiver = this;\n\t\t\t\t}\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <ThrowErr foo={this.state.foo} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver.prototype, 'componentDidCatch');\n\t\t\trender(<Receiver />, scratch);\n\n\t\t\treceiver.setState({ foo: 'baz' });\n\t\t\trerender();\n\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in shouldComponentUpdate', () => {\n\t\t\tThrowErr.prototype.shouldComponentUpdate = throwExpectedError;\n\n\t\t\tlet receiver;\n\t\t\tclass Receiver extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { foo: 'bar' };\n\t\t\t\t\treceiver = this;\n\t\t\t\t}\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <ThrowErr foo={this.state.foo} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver.prototype, 'componentDidCatch');\n\t\t\trender(<Receiver />, scratch);\n\n\t\t\treceiver.setState({ foo: 'baz' });\n\t\t\trerender();\n\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentWillUnmount', () => {\n\t\t\tThrowErr.prototype.componentWillUnmount = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<div />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when applying a Component ref', () => {\n\t\t\tconst Foo = props => <div ref={props.ref} />;\n\n\t\t\tconst ref = value => {\n\t\t\t\tif (value) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// In React, an error boundary handles it's own refs:\n\t\t\t// https://codesandbox.io/s/react-throwing-refs-lk958\n\t\t\tclass Receiver extends Component {\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <Foo ref={ref} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver.prototype, 'componentDidCatch');\n\t\t\trender(<Receiver />, scratch);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when applying a DOM ref', () => {\n\t\t\tconst ref = value => {\n\t\t\t\tif (value) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// In React, an error boundary handles it's own refs:\n\t\t\t// https://codesandbox.io/s/react-throwing-refs-lk958\n\t\t\tclass Receiver extends Component {\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <div ref={ref} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver.prototype, 'componentDidCatch');\n\t\t\trender(<Receiver />, scratch);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when unmounting a ref', () => {\n\t\t\tconst ref = value => {\n\t\t\t\tif (value == null) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tThrowErr.prototype.render = () => <div ref={ref} />;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<div />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledOnce();\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when functional child fails', () => {\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child inside a Fragment fails', () => {\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should re-render with new content', () => {\n\t\t\tclass ThrowErr extends Component {\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\tthrow new Error('Error contents');\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn 'No error!?!?';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error contents');\n\t\t});\n\n\t\tit('should be able to adapt and rethrow errors', () => {\n\t\t\tlet adaptedError;\n\t\t\tclass Adapter extends Component {\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\tthrow (adaptedError = new Error(\n\t\t\t\t\t\t'Adapted ' +\n\t\t\t\t\t\t\tString(error && 'message' in error ? error.message : error)\n\t\t\t\t\t));\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\tvi.spyOn(Adapter.prototype, 'componentDidCatch');\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Adapter>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Adapter>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(Adapter.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\tadaptedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\n\t\t\trerender();\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Adapted Error!');\n\t\t});\n\n\t\tit('should bubble on repeated errors', () => {\n\t\t\tclass Adapter extends Component {\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\t// Try to handle the error\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\t// But fail at doing so\n\t\t\t\t\tif (this.state.error) {\n\t\t\t\t\t\tthrow this.state.error;\n\t\t\t\t\t}\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\tvi.spyOn(Adapter.prototype, 'componentDidCatch');\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Adapter>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Adapter>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(Adapter.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error!');\n\t\t});\n\n\t\tit('should bubble on ignored errors', () => {\n\t\t\tclass Adapter extends Component {\n\t\t\t\tcomponentDidCatch() {\n\t\t\t\t\t// Ignore the error\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrow new Error('Error!');\n\t\t\t}\n\n\t\t\tvi.spyOn(Adapter.prototype, 'componentDidCatch');\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Adapter>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Adapter>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(Adapter.prototype.componentDidCatch).toHaveBeenCalled();\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalled();\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error!');\n\t\t});\n\n\t\tit('should not bubble on caught errors', () => {\n\t\t\tclass TopReceiver extends Component {\n\t\t\t\tcomponentDidCatch(error) {\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{this.state.error\n\t\t\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t\t\t: this.props.children}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\tvi.spyOn(TopReceiver.prototype, 'componentDidCatch');\n\n\t\t\trender(\n\t\t\t\t<TopReceiver>\n\t\t\t\t\t<Receiver>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Receiver>\n\t\t\t\t</TopReceiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(TopReceiver.prototype.componentDidCatch).not.toHaveBeenCalled();\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error!');\n\t\t});\n\n\t\tit('should be called through non-component parent elements', () => {\n\t\t\tThrowErr.prototype.render = throwExpectedError;\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</div>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit('should bubble up when ref throws on component that is not an error boundary', () => {\n\t\t\tconst ref = value => {\n\t\t\t\tif (value) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\treturn <div ref={ref} />;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.prototype.componentDidCatch).toHaveBeenCalledWith(\n\t\t\t\texpectedError,\n\t\t\t\texpect.anything()\n\t\t\t);\n\t\t});\n\n\t\tit.skip('should successfully unmount constantly throwing ref', () => {\n\t\t\tconst buggyRef = throwExpectedError;\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\treturn <div ref={buggyRef}>ThrowErr</div>;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Error: Error!</div>');\n\t\t});\n\n\t\tit('should pass errorInfo on render error', () => {\n\t\t\tlet info;\n\t\t\tclass Receiver extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { error: null };\n\t\t\t\t}\n\t\t\t\tcomponentDidCatch(error, errorInfo) {\n\t\t\t\t\tinfo = errorInfo;\n\t\t\t\t\tthis.setState({ error });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tif (this.state.error) return <div />;\n\t\t\t\t\treturn this.props.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrow new Error('fail');\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(info).to.deep.equal({});\n\t\t});\n\n\t\t// New test mirroring React example but using shouldComponentUpdate instead of memo\n\t\tit('should recover and render siblings when child throws once and uses shouldComponentUpdate', () => {\n\t\t\tlet causeError = true;\n\n\t\t\tconst Render = ({ n }) => <p>test {n}</p>;\n\n\t\t\tclass TestWithSCU extends Component {\n\t\t\t\tshouldComponentUpdate(nextProps) {\n\t\t\t\t\treturn nextProps.n !== this.props.n;\n\t\t\t\t}\n\t\t\t\trender(props) {\n\t\t\t\t\tconst { n } = props;\n\t\t\t\t\tif (n === 2 && causeError) {\n\t\t\t\t\t\tthrow new Error('test error');\n\t\t\t\t\t}\n\t\t\t\t\treturn <Render n={n} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass App extends Component {\n\t\t\t\tcomponentDidCatch() {\n\t\t\t\t\tcauseError = false;\n\t\t\t\t\tthis.setState({});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<h1>Example</h1>\n\t\t\t\t\t\t\t<TestWithSCU n={1} />\n\t\t\t\t\t\t\t<TestWithSCU n={2} />\n\t\t\t\t\t\t\t<TestWithSCU n={3} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(App.prototype, 'componentDidCatch');\n\t\t\trender(<App />, scratch);\n\t\t\trerender();\n\n\t\t\texpect(App.prototype.componentDidCatch).toHaveBeenCalledOnce();\n\t\t\texpect(scratch.textContent).to.equal('Exampletest 1test 2test 3');\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentDidMount.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#componentDidMount', () => {\n\t\tit('is invoked after refs are set', () => {\n\t\t\tconst spy = vi.fn();\n\n\t\t\tclass App extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\t\t\texpect(spy).toHaveBeenCalledWith(scratch.firstChild);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div ref={spy} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(spy).toHaveBeenCalledWith(scratch.firstChild);\n\t\t});\n\n\t\tit('supports multiple setState callbacks', () => {\n\t\t\tconst spy = vi.fn();\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { count: 0 };\n\t\t\t\t}\n\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\tthis.setState({ count: 1 }, spy);\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\tthis.setState({ count: 2 }, spy);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\n\t\t\trerender();\n\t\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentDidUpdate.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#componentDidUpdate', () => {\n\t\tit('should be passed previous props and state', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet updateState;\n\n\t\t\tlet prevPropsArg;\n\t\t\tlet prevStateArg;\n\t\t\tlet snapshotArg;\n\t\t\tlet curProps;\n\t\t\tlet curState;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t\tupdateState = () =>\n\t\t\t\t\t\tthis.setState({\n\t\t\t\t\t\t\tvalue: this.state.value + 1\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\t// NOTE: Don't do this in real production code!\n\t\t\t\t\t// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: state.value + 1\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentDidUpdate(prevProps, prevState, snapshot) {\n\t\t\t\t\t// These object references might be updated later so copy\n\t\t\t\t\t// object so we can assert their values at this snapshot in time\n\t\t\t\t\tprevPropsArg = { ...prevProps };\n\t\t\t\t\tprevStateArg = { ...prevState };\n\t\t\t\t\tsnapshotArg = snapshot;\n\n\t\t\t\t\tcurProps = { ...this.props };\n\t\t\t\t\tcurState = { ...this.state };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.state.value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Expectation:\n\t\t\t// `prevState` in componentDidUpdate should be\n\t\t\t// the state before setState and getDerivedStateFromProps was called.\n\t\t\t// `this.state` in componentDidUpdate should be\n\t\t\t// the updated state after getDerivedStateFromProps was called.\n\n\t\t\t// Initial render\n\t\t\t// state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n\t\t\trender(<Foo foo=\"foo\" />, scratch);\n\t\t\texpect(scratch.firstChild.textContent).to.be.equal('1');\n\t\t\texpect(prevPropsArg).to.be.undefined;\n\t\t\texpect(prevStateArg).to.be.undefined;\n\t\t\texpect(snapshotArg).to.be.undefined;\n\t\t\texpect(curProps).to.be.undefined;\n\t\t\texpect(curState).to.be.undefined;\n\n\t\t\t// New props\n\t\t\t// state.value: 1 -> 2 in gDSFP\n\t\t\trender(<Foo foo=\"bar\" />, scratch);\n\t\t\texpect(scratch.firstChild.textContent).to.be.equal('2');\n\t\t\texpect(prevPropsArg).to.deep.equal({ foo: 'foo' });\n\t\t\texpect(prevStateArg).to.deep.equal({ value: 1 });\n\t\t\texpect(snapshotArg).to.be.undefined;\n\t\t\texpect(curProps).to.deep.equal({ foo: 'bar' });\n\t\t\texpect(curState).to.deep.equal({ value: 2 });\n\n\t\t\t// New state\n\t\t\t// state.value: 2 -> 3 in updateState, 3 -> 4 in gDSFP\n\t\t\tupdateState();\n\t\t\trerender();\n\t\t\texpect(scratch.firstChild.textContent).to.be.equal('4');\n\t\t\texpect(prevPropsArg).to.deep.equal({ foo: 'bar' });\n\t\t\texpect(prevStateArg).to.deep.equal({ value: 2 });\n\t\t\texpect(snapshotArg).to.be.undefined;\n\t\t\texpect(curProps).to.deep.equal({ foo: 'bar' });\n\t\t\texpect(curState).to.deep.equal({ value: 4 });\n\t\t});\n\n\t\tit('cDU should not be called when sDU returned false', () => {\n\t\t\tlet spy = vi.fn();\n\t\t\tlet c;\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tc = this;\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tcomponentDidUpdate(prevProps) {\n\t\t\t\t\tspy(prevProps);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\tc.setState({});\n\t\t\trerender();\n\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit(\"prevState argument should be the same object if state doesn't change\", () => {\n\t\t\tlet changeProps, cduPrevState, cduCurrentState;\n\n\t\t\tclass PropsProvider extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { value: 0 };\n\t\t\t\t\tchangeProps = this.changeReceiverProps.bind(this);\n\t\t\t\t}\n\t\t\t\tchangeReceiverProps() {\n\t\t\t\t\tlet value = (this.state.value + 1) % 2;\n\t\t\t\t\tthis.setState({\n\t\t\t\t\t\tvalue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <PropsReceiver value={this.state.value} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass PropsReceiver extends Component {\n\t\t\t\tcomponentDidUpdate(prevProps, prevState) {\n\t\t\t\t\tcduPrevState = prevState;\n\t\t\t\t\tcduCurrentState = this.state;\n\t\t\t\t}\n\t\t\t\trender({ value }) {\n\t\t\t\t\treturn <div>{value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<PropsProvider />, scratch);\n\n\t\t\tchangeProps();\n\t\t\trerender();\n\n\t\t\texpect(cduPrevState).to.equal(cduCurrentState);\n\t\t});\n\n\t\tit('prevState argument should be a different object if state does change', () => {\n\t\t\tlet updateState, cduPrevState, cduCurrentState;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { value: 0 };\n\t\t\t\t\tupdateState = this.updateState.bind(this);\n\t\t\t\t}\n\t\t\t\tupdateState() {\n\t\t\t\t\tlet value = (this.state.value + 1) % 2;\n\t\t\t\t\tthis.setState({\n\t\t\t\t\t\tvalue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcomponentDidUpdate(prevProps, prevState) {\n\t\t\t\t\tcduPrevState = prevState;\n\t\t\t\t\tcduCurrentState = this.state;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.state.value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(cduPrevState).to.not.equal(cduCurrentState);\n\t\t});\n\n\t\tit(\"prevProps argument should be the same object if props don't change\", () => {\n\t\t\tlet updateState, cduPrevProps, cduCurrentProps;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { value: 0 };\n\t\t\t\t\tupdateState = this.updateState.bind(this);\n\t\t\t\t}\n\t\t\t\tupdateState() {\n\t\t\t\t\tlet value = (this.state.value + 1) % 2;\n\t\t\t\t\tthis.setState({\n\t\t\t\t\t\tvalue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcomponentDidUpdate(prevProps) {\n\t\t\t\t\tcduPrevProps = prevProps;\n\t\t\t\t\tcduCurrentProps = this.props;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.state.value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(cduPrevProps).to.equal(cduCurrentProps);\n\t\t});\n\n\t\tit('prevProps argument should be a different object if props do change', () => {\n\t\t\tlet changeProps, cduPrevProps, cduCurrentProps;\n\n\t\t\tclass PropsProvider extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { value: 0 };\n\t\t\t\t\tchangeProps = this.changeReceiverProps.bind(this);\n\t\t\t\t}\n\t\t\t\tchangeReceiverProps() {\n\t\t\t\t\tlet value = (this.state.value + 1) % 2;\n\t\t\t\t\tthis.setState({\n\t\t\t\t\t\tvalue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <PropsReceiver value={this.state.value} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass PropsReceiver extends Component {\n\t\t\t\tcomponentDidUpdate(prevProps) {\n\t\t\t\t\tcduPrevProps = prevProps;\n\t\t\t\t\tcduCurrentProps = this.props;\n\t\t\t\t}\n\t\t\t\trender({ value }) {\n\t\t\t\t\treturn <div>{value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<PropsProvider />, scratch);\n\n\t\t\tchangeProps();\n\t\t\trerender();\n\n\t\t\texpect(cduPrevProps).to.not.equal(cduCurrentProps);\n\t\t});\n\n\t\tit('is invoked after refs are set', () => {\n\t\t\tconst spy = vi.fn();\n\t\t\tlet inst;\n\t\t\tlet i = 0;\n\n\t\t\tclass App extends Component {\n\t\t\t\tcomponentDidUpdate() {\n\t\t\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\t\t\texpect(spy).toHaveBeenCalledWith(scratch.firstChild);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tlet ref = null;\n\n\t\t\t\t\tif (i > 0) {\n\t\t\t\t\t\t// Add ref after mount (i > 0)\n\t\t\t\t\t\tref = spy;\n\t\t\t\t\t}\n\n\t\t\t\t\ti++;\n\t\t\t\t\tinst = this;\n\t\t\t\t\treturn <div ref={ref} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\n\t\t\tinst.setState({});\n\t\t\trerender();\n\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(spy).toHaveBeenCalledWith(scratch.firstChild);\n\t\t});\n\n\t\tit('should be called after children are mounted', () => {\n\t\t\tlet log = [];\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tlog.push('Inner mounted');\n\n\t\t\t\t\t// Verify that the component is actually mounted when this\n\t\t\t\t\t// callback is invoked.\n\t\t\t\t\texpect(scratch.querySelector('#inner')).to.not.equal(null);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div id=\"inner\" />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tcomponentDidUpdate() {\n\t\t\t\t\tlog.push('Outer updated');\n\t\t\t\t}\n\n\t\t\t\trender(props) {\n\t\t\t\t\treturn props.renderInner ? <Inner /> : <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Outer renderInner={false} />, scratch);\n\t\t\trender(<Outer renderInner />, scratch);\n\n\t\t\texpect(log).to.deep.equal(['Inner mounted', 'Outer updated']);\n\t\t});\n\n\t\tit('should be called after parent DOM elements are updated', () => {\n\t\t\tlet setValue;\n\t\t\tlet outerChildText;\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor(p, c) {\n\t\t\t\t\tsuper(p, c);\n\n\t\t\t\t\tthis.state = { i: 0 };\n\t\t\t\t\tsetValue = i => this.setState({ i });\n\t\t\t\t}\n\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<Inner i={i} {...props} />\n\t\t\t\t\t\t\t<p id=\"parent-child\">Outer: {i}</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentDidUpdate() {\n\t\t\t\t\t// At this point, the parent's <p> tag should've been updated with the latest value\n\t\t\t\t\touterChildText = scratch.querySelector('#parent-child').textContent;\n\t\t\t\t}\n\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <div>Inner: {i}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Inner.prototype, 'componentDidUpdate');\n\n\t\t\t// Initial render\n\t\t\trender(<Outer />, scratch);\n\t\t\texpect(Inner.prototype.componentDidUpdate).not.toHaveBeenCalled();\n\n\t\t\t// Set state with a new i\n\t\t\tconst newValue = 5;\n\t\t\tsetValue(newValue);\n\t\t\trerender();\n\n\t\t\texpect(Inner.prototype.componentDidUpdate).toHaveBeenCalled();\n\t\t\texpect(outerChildText).to.equal(`Outer: ${newValue.toString()}`);\n\t\t});\n\n\t\tit('should not interfere with setState callbacks', () => {\n\t\t\tlet invocation;\n\n\t\t\tclass Child extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tthis.props.setValue(10);\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <p>Hello world</p>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tshow: false,\n\t\t\t\t\t\tcount: null\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\tthis.setState({ show: true });\n\t\t\t\t}\n\n\t\t\t\tcomponentDidUpdate() {}\n\n\t\t\t\trender() {\n\t\t\t\t\tif (this.state.show) {\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Child\n\t\t\t\t\t\t\t\tsetValue={i =>\n\t\t\t\t\t\t\t\t\tthis.setState({ count: i }, () => {\n\t\t\t\t\t\t\t\t\t\tinvocation = this.state;\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\n\t\t\trerender();\n\t\t\texpect(invocation.count).to.equal(10);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentWillMount.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../_util/helpers';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#componentWillMount', () => {\n\t\tit('should update state when called setState in componentWillMount', () => {\n\t\t\tlet componentState;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\tthis.setState({ value: 1 });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tcomponentState = this.state;\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\n\t\t\texpect(componentState).to.deep.equal({ value: 1 });\n\t\t});\n\n\t\tit('should invoke setState callbacks when setState is called in componentWillMount', () => {\n\t\t\tlet componentState;\n\t\t\tlet callback = vi.fn();\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\tthis.setState({ value: 1 }, callback);\n\t\t\t\t\tthis.setState({ value: 2 }, () => {\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t\tthis.setState({ value: 3 }, callback);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tcomponentState = this.state;\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\n\t\t\texpect(componentState).to.deep.equal({ value: 2 });\n\t\t\texpect(callback).toHaveBeenCalledTimes(2);\n\n\t\t\trerender();\n\n\t\t\texpect(componentState).to.deep.equal({ value: 3 });\n\t\t\texpect(callback).toHaveBeenCalledTimes(3);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentWillReceiveProps.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#componentWillReceiveProps', () => {\n\t\tit('should update state when called setState in componentWillReceiveProps', () => {\n\t\t\tlet componentState;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tdummy: 0\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\t// eslint-disable-next-line react/no-did-mount-set-state\n\t\t\t\t\tthis.setState({ dummy: 1 });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Bar dummy={this.state.dummy} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass Bar extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentWillReceiveProps() {\n\t\t\t\t\tthis.setState({ value: 1 });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tcomponentState = this.state;\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\trerender();\n\n\t\t\texpect(componentState).to.deep.equal({ value: 1 });\n\n\t\t\tconst cWRP = Foo.prototype.componentWillReceiveProps;\n\t\t\tdelete Foo.prototype.componentWillReceiveProps;\n\n\t\t\tFoo.prototype.shouldComponentUpdate = cWRP;\n\n\t\t\trender(null, scratch);\n\t\t\trender(<Foo />, scratch);\n\t\t\trerender();\n\n\t\t\texpect(componentState, 'via shouldComponentUpdate').to.deep.equal({\n\t\t\t\tvalue: 1\n\t\t\t});\n\n\t\t\tdelete Foo.prototype.shouldComponentUpdate;\n\t\t\tFoo.prototype.componentWillUpdate = cWRP;\n\n\t\t\trender(null, scratch);\n\t\t\trender(<Foo />, scratch);\n\t\t\trerender();\n\n\t\t\texpect(componentState, 'via componentWillUpdate').to.deep.equal({\n\t\t\t\tvalue: 1\n\t\t\t});\n\t\t});\n\n\t\tit('should NOT be called on initial render', () => {\n\t\t\tclass ReceivePropsComponent extends Component {\n\t\t\t\tcomponentWillReceiveProps() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(ReceivePropsComponent.prototype, 'componentWillReceiveProps');\n\t\t\trender(<ReceivePropsComponent />, scratch);\n\t\t\texpect(\n\t\t\t\tReceivePropsComponent.prototype.componentWillReceiveProps\n\t\t\t).not.toHaveBeenCalled();\n\t\t});\n\n\t\t// See last paragraph of cWRP section https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops\n\t\tit('should not be called on setState or forceUpdate', () => {\n\t\t\tlet spy = vi.fn();\n\t\t\tlet spyInner = vi.fn();\n\t\t\tlet c;\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillReceiveProps() {\n\t\t\t\t\tspyInner();\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>foo</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tc = this;\n\t\t\t\t}\n\n\t\t\t\tcomponentWillReceiveProps() {\n\t\t\t\t\tspy();\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <Inner />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Outer />, scratch);\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\n\t\t\tc.setState({});\n\t\t\trerender();\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\t\t\texpect(spyInner).toHaveBeenCalledOnce();\n\t\t\tspy.mockClear();\n\t\t\tspyInner.mockClear();\n\n\t\t\tc.forceUpdate();\n\t\t\trerender();\n\t\t\texpect(spy).not.toHaveBeenCalled();\n\t\t\texpect(spyInner).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should be called when rerender with new props from parent', () => {\n\t\t\tlet doRender;\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor(p, c) {\n\t\t\t\t\tsuper(p, c);\n\t\t\t\t\tthis.state = { i: 0 };\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tdoRender = () => this.setState({ i: this.state.i + 1 });\n\t\t\t\t}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <Inner i={i} {...props} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\texpect(this.props.i).to.be.equal(0);\n\t\t\t\t}\n\t\t\t\tcomponentWillReceiveProps(nextProps) {\n\t\t\t\t\texpect(nextProps.i).to.be.equal(1);\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillReceiveProps');\n\t\t\tvi.spyOn(Outer.prototype, 'componentDidMount');\n\n\t\t\t// Initial render\n\t\t\trender(<Outer />, scratch);\n\t\t\texpect(Inner.prototype.componentWillReceiveProps).not.toHaveBeenCalled();\n\n\t\t\t// Rerender inner with new props\n\t\t\tdoRender();\n\t\t\trerender();\n\t\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalled();\n\t\t});\n\n\t\tit('should be called when rerender with new props from parent even with setState/forceUpdate in child', () => {\n\t\t\tlet setStateAndUpdateProps;\n\t\t\tlet forceUpdateAndUpdateProps;\n\t\t\tlet cWRPSpy = vi.fn();\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor(p, c) {\n\t\t\t\t\tsuper(p, c);\n\t\t\t\t\tthis.state = { i: 0 };\n\t\t\t\t\tthis.update = this.update.bind(this);\n\t\t\t\t}\n\t\t\t\tupdate() {\n\t\t\t\t\tthis.setState({ i: this.state.i + 1 });\n\t\t\t\t}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <Inner i={i} update={this.update} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\texpect(this.props.i).to.be.equal(0);\n\n\t\t\t\t\tsetStateAndUpdateProps = () => {\n\t\t\t\t\t\tthis.setState({});\n\t\t\t\t\t\tthis.props.update();\n\t\t\t\t\t};\n\t\t\t\t\tforceUpdateAndUpdateProps = () => {\n\t\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t\t\tthis.props.update();\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentWillReceiveProps(nextProps) {\n\t\t\t\t\tcWRPSpy(nextProps.i);\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Initial render\n\t\t\trender(<Outer />, scratch);\n\t\t\texpect(cWRPSpy).not.toHaveBeenCalled();\n\n\t\t\t// setState in inner component and update with new props\n\t\t\tsetStateAndUpdateProps();\n\t\t\trerender();\n\t\t\texpect(cWRPSpy).toHaveBeenCalledWith(1);\n\n\t\t\t// forceUpdate in inner component and update with new props\n\t\t\tforceUpdateAndUpdateProps();\n\t\t\trerender();\n\t\t\texpect(cWRPSpy).toHaveBeenCalledWith(2);\n\t\t});\n\n\t\tit('should be called in right execution order', () => {\n\t\t\tlet doRender;\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor(p, c) {\n\t\t\t\t\tsuper(p, c);\n\t\t\t\t\tthis.state = { i: 0 };\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tdoRender = () => this.setState({ i: this.state.i + 1 });\n\t\t\t\t}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <Inner i={i} {...props} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentDidUpdate() {\n\t\t\t\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalled();\n\t\t\t\t\texpect(Inner.prototype.componentWillUpdate).toHaveBeenCalled();\n\t\t\t\t}\n\t\t\t\tcomponentWillReceiveProps() {\n\t\t\t\t\texpect(Inner.prototype.componentWillUpdate).not.toHaveBeenCalled();\n\t\t\t\t\texpect(Inner.prototype.componentDidUpdate).not.toHaveBeenCalled();\n\t\t\t\t}\n\t\t\t\tcomponentWillUpdate() {\n\t\t\t\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalled();\n\t\t\t\t\texpect(Inner.prototype.componentDidUpdate).not.toHaveBeenCalled();\n\t\t\t\t}\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalled();\n\t\t\t\t\texpect(Inner.prototype.componentWillUpdate).not.toHaveBeenCalled();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillReceiveProps');\n\t\t\tvi.spyOn(Inner.prototype, 'componentDidUpdate');\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillUpdate');\n\t\t\tvi.spyOn(Inner.prototype, 'shouldComponentUpdate');\n\t\t\tvi.spyOn(Outer.prototype, 'componentDidMount');\n\n\t\t\trender(<Outer />, scratch);\n\t\t\tdoRender();\n\t\t\trerender();\n\n\t\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalledBefore(\n\t\t\t\tInner.prototype.componentWillUpdate\n\t\t\t);\n\t\t\texpect(Inner.prototype.componentWillReceiveProps).toHaveBeenCalledBefore(\n\t\t\t\tInner.prototype.shouldComponentUpdate\n\t\t\t);\n\t\t\texpect(Inner.prototype.componentWillUpdate).toHaveBeenCalledBefore(\n\t\t\t\tInner.prototype.componentDidUpdate\n\t\t\t);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentWillUnmount.test.jsx",
    "content": "import { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('top-level componentWillUnmount', () => {\n\t\tit('should invoke componentWillUnmount for top-level components', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn 'foo';\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass Bar extends Component {\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn 'bar';\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Foo.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Foo.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\tvi.spyOn(Bar.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Bar.prototype, 'componentWillUnmount');\n\t\t\tvi.spyOn(Bar.prototype, 'render');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(Foo.prototype.componentDidMount).toHaveBeenCalledOnce();\n\n\t\t\trender(<Bar />, scratch);\n\t\t\texpect(Foo.prototype.componentWillUnmount).toHaveBeenCalledOnce();\n\t\t\texpect(Bar.prototype.componentDidMount).toHaveBeenCalledOnce();\n\n\t\t\trender(<div />, scratch);\n\t\t\texpect(Bar.prototype.componentWillUnmount).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should only remove dom after componentWillUnmount was called', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tcomponentWillUnmount() {\n\t\t\t\t\texpect(document.getElementById('foo')).to.not.equal(null);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div id=\"foo\" />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\trender(null, scratch);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/componentWillUpdate.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#componentWillUpdate', () => {\n\t\tit('should NOT be called on initial render', () => {\n\t\t\tclass ReceivePropsComponent extends Component {\n\t\t\t\tcomponentWillUpdate() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(ReceivePropsComponent.prototype, 'componentWillUpdate');\n\t\t\trender(<ReceivePropsComponent />, scratch);\n\t\t\texpect(\n\t\t\t\tReceivePropsComponent.prototype.componentWillUpdate\n\t\t\t).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should be called when rerender with new props from parent', () => {\n\t\t\tlet doRender;\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor(p, c) {\n\t\t\t\t\tsuper(p, c);\n\t\t\t\t\tthis.state = { i: 0 };\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tdoRender = () => this.setState({ i: this.state.i + 1 });\n\t\t\t\t}\n\t\t\t\trender(props, { i }) {\n\t\t\t\t\treturn <Inner i={i} {...props} />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillUpdate(nextProps, nextState) {\n\t\t\t\t\texpect(nextProps).to.be.deep.equal({ i: 1 });\n\t\t\t\t\texpect(nextState).to.be.deep.equal({});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(Inner.prototype, 'componentWillUpdate');\n\t\t\tvi.spyOn(Outer.prototype, 'componentDidMount');\n\n\t\t\t// Initial render\n\t\t\trender(<Outer />, scratch);\n\t\t\texpect(Inner.prototype.componentWillUpdate).not.toHaveBeenCalled();\n\n\t\t\t// Rerender inner with new props\n\t\t\tdoRender();\n\t\t\trerender();\n\t\t\texpect(Inner.prototype.componentWillUpdate).toHaveBeenCalled();\n\t\t});\n\n\t\tit('should be called on new state', () => {\n\t\t\tlet doRender;\n\t\t\tclass ReceivePropsComponent extends Component {\n\t\t\t\tcomponentWillUpdate() {}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tdoRender = () => this.setState({ i: this.state.i + 1 });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(ReceivePropsComponent.prototype, 'componentWillUpdate');\n\t\t\trender(<ReceivePropsComponent />, scratch);\n\t\t\texpect(\n\t\t\t\tReceivePropsComponent.prototype.componentWillUpdate\n\t\t\t).not.toHaveBeenCalled();\n\n\t\t\tdoRender();\n\t\t\trerender();\n\t\t\texpect(\n\t\t\t\tReceivePropsComponent.prototype.componentWillUpdate\n\t\t\t).toHaveBeenCalled();\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/getDerivedStateFromError.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/* eslint-disable react/display-name */\n\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#getDerivedStateFromError', () => {\n\t\t/** @type {Error} */\n\t\tlet expectedError;\n\n\t\t/** @type {typeof import('../../../').Component} */\n\t\tlet ThrowErr;\n\n\t\tlet thrower;\n\n\t\tclass Receiver extends Component {\n\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\treturn { error };\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.state.error\n\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t: this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Receiver, 'getDerivedStateFromError');\n\t\tvi.spyOn(Receiver.prototype, 'render');\n\n\t\tfunction throwExpectedError() {\n\t\t\tthrow (expectedError = new Error('Error!'));\n\t\t}\n\n\t\tbeforeEach(() => {\n\t\t\tThrowErr = class ThrowErr extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthrower = this;\n\t\t\t\t}\n\n\t\t\t\tstatic getDerivedStateFromError() {\n\t\t\t\t\texpect.fail(\"Throwing component should not catch it's own error.\");\n\t\t\t\t\treturn {};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>ThrowErr: getDerivedStateFromError</div>;\n\t\t\t\t}\n\t\t\t};\n\t\t\tvi.spyOn(ThrowErr, 'getDerivedStateFromError');\n\n\t\t\texpectedError = undefined;\n\n\t\t\tReceiver.getDerivedStateFromError.mockClear();\n\t\t\tReceiver.prototype.render.mockClear();\n\t\t});\n\n\t\tafterEach(() => {\n\t\t\texpect(\n\t\t\t\tThrowErr.getDerivedStateFromError,\n\t\t\t\t\"Throwing component should not catch it's own error.\"\n\t\t\t).not.toHaveBeenCalled();\n\t\t\tthrower = undefined;\n\t\t});\n\n\t\tit('should be called when child fails in constructor', () => {\n\t\t\tclass ThrowErr extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromError() {\n\t\t\t\t\texpect.fail(\"Throwing component should not catch it's own error\");\n\t\t\t\t\treturn {};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\t// https://github.com/preactjs/preact/issues/1570\n\t\tit('should handle double child throws', () => {\n\t\t\tconst Child = ({ i }) => {\n\t\t\t\tthrow new Error(`error! ${i}`);\n\t\t\t};\n\n\t\t\tconst fn = () =>\n\t\t\t\trender(\n\t\t\t\t\t<Receiver>\n\t\t\t\t\t\t{[1, 2].map(i => (\n\t\t\t\t\t\t\t<Child key={i} i={i} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</Receiver>,\n\t\t\t\t\tscratch\n\t\t\t\t);\n\t\t\texpect(fn).to.not.throw();\n\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('Error: error! 2');\n\t\t});\n\n\t\tit('should be called when child fails in componentWillMount', () => {\n\t\t\tThrowErr.prototype.componentWillMount = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in render', () => {\n\t\t\tThrowErr.prototype.render = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentDidMount', () => {\n\t\t\tThrowErr.prototype.componentDidMount = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in getDerivedStateFromProps', () => {\n\t\t\tThrowErr.getDerivedStateFromProps = throwExpectedError;\n\n\t\t\tvi.spyOn(ThrowErr.prototype, 'render');\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t\texpect(ThrowErr.prototype.render).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should be called when child fails in getSnapshotBeforeUpdate', () => {\n\t\t\tThrowErr.prototype.getSnapshotBeforeUpdate = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\tthrower.forceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentDidUpdate', () => {\n\t\t\tThrowErr.prototype.componentDidUpdate = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tthrower.forceUpdate();\n\t\t\trerender();\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentWillUpdate', () => {\n\t\t\tThrowErr.prototype.componentWillUpdate = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tthrower.forceUpdate();\n\t\t\trerender();\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentWillReceiveProps', () => {\n\t\t\tThrowErr.prototype.componentWillReceiveProps = throwExpectedError;\n\n\t\t\tlet receiver;\n\t\t\tclass Receiver extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { foo: 'bar' };\n\t\t\t\t\treceiver = this;\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <ThrowErr foo={this.state.foo} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver, 'getDerivedStateFromError');\n\t\t\trender(<Receiver />, scratch);\n\n\t\t\treceiver.setState({ foo: 'baz' });\n\t\t\trerender();\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in shouldComponentUpdate', () => {\n\t\t\tThrowErr.prototype.shouldComponentUpdate = throwExpectedError;\n\n\t\t\tlet receiver;\n\t\t\tclass Receiver extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { foo: 'bar' };\n\t\t\t\t\treceiver = this;\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <ThrowErr foo={this.state.foo} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver, 'getDerivedStateFromError');\n\t\t\trender(<Receiver />, scratch);\n\n\t\t\treceiver.setState({ foo: 'baz' });\n\t\t\trerender();\n\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when child fails in componentWillUnmount', () => {\n\t\t\tThrowErr.prototype.componentWillUnmount = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<div />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when applying a Component ref', () => {\n\t\t\tconst Foo = props => <div ref={props.ref} />;\n\n\t\t\tconst ref = value => {\n\t\t\t\tif (value) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// In React, an error boundary handles it's own refs:\n\t\t\t// https://codesandbox.io/s/react-throwing-refs-lk958\n\t\t\tclass Receiver extends Component {\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <Foo ref={ref} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver, 'getDerivedStateFromError');\n\t\t\trender(<Receiver />, scratch);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when applying a DOM ref', () => {\n\t\t\tconst ref = value => {\n\t\t\t\tif (value) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t// In React, an error boundary handles it's own refs:\n\t\t\t// https://codesandbox.io/s/react-throwing-refs-lk958\n\t\t\tclass Receiver extends Component {\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.error\n\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t: <div ref={ref} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Receiver, 'getDerivedStateFromError');\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when unmounting a ref', () => {\n\t\t\tconst ref = value => {\n\t\t\t\tif (value == null) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tThrowErr.prototype.render = () => <div ref={ref} />;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<div />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledOnce();\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should be called when functional child fails', () => {\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should re-render with new content', () => {\n\t\t\tclass ThrowErr extends Component {\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\tthrow new Error('Error contents');\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn 'No error!?!?';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error contents');\n\t\t});\n\n\t\tit('should be able to adapt and rethrow errors', () => {\n\t\t\tlet adaptedError;\n\t\t\tclass Adapter extends Component {\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\tthrow (adaptedError = new Error(\n\t\t\t\t\t\t'Adapted ' +\n\t\t\t\t\t\t\tString(error && 'message' in error ? error.message : error)\n\t\t\t\t\t));\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\tvi.spyOn(Adapter, 'getDerivedStateFromError');\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Adapter>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Adapter>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(Adapter.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\tadaptedError\n\t\t\t);\n\n\t\t\trerender();\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Adapted Error!');\n\t\t});\n\n\t\tit('should bubble on repeated errors', () => {\n\t\t\tclass Adapter extends Component {\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\t// But fail at doing so\n\t\t\t\t\tif (this.state.error) {\n\t\t\t\t\t\tthrow this.state.error;\n\t\t\t\t\t}\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\tvi.spyOn(Adapter, 'getDerivedStateFromError');\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Adapter>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Adapter>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(Adapter.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error!');\n\t\t});\n\n\t\tit('should bubble on ignored errors', () => {\n\t\t\tclass Adapter extends Component {\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\t// Ignore the error\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.props.children}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrow new Error('Error!');\n\t\t\t}\n\n\t\t\tvi.spyOn(Adapter, 'getDerivedStateFromError');\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<Adapter>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Adapter>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(Adapter.getDerivedStateFromError).toHaveBeenCalled();\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalled();\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error!');\n\t\t});\n\n\t\tit('should not bubble on caught errors', () => {\n\t\t\tclass TopReceiver extends Component {\n\t\t\t\tstatic getDerivedStateFromError(error) {\n\t\t\t\t\treturn { error };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{this.state.error\n\t\t\t\t\t\t\t\t? String(this.state.error)\n\t\t\t\t\t\t\t\t: this.props.children}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\tthrowExpectedError();\n\t\t\t}\n\n\t\t\tvi.spyOn(TopReceiver, 'getDerivedStateFromError');\n\n\t\t\trender(\n\t\t\t\t<TopReceiver>\n\t\t\t\t\t<Receiver>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</Receiver>\n\t\t\t\t</TopReceiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(TopReceiver.getDerivedStateFromError).not.toHaveBeenCalled();\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t\texpect(scratch).to.have.property('textContent', 'Error: Error!');\n\t\t});\n\n\t\tit('should be called through non-component parent elements', () => {\n\t\t\tThrowErr.prototype.render = throwExpectedError;\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<ThrowErr />\n\t\t\t\t\t</div>\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit('should bubble up when ref throws on component that is not an error boundary', () => {\n\t\t\tconst ref = value => {\n\t\t\t\tif (value) {\n\t\t\t\t\tthrowExpectedError();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\treturn <div ref={ref} />;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(Receiver.getDerivedStateFromError).toHaveBeenCalledWith(\n\t\t\t\texpectedError\n\t\t\t);\n\t\t});\n\n\t\tit.skip('should successfully unmount constantly throwing ref', () => {\n\t\t\tconst buggyRef = throwExpectedError;\n\n\t\t\tfunction ThrowErr() {\n\t\t\t\treturn <div ref={buggyRef}>ThrowErr</div>;\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<Receiver>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Receiver>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(scratch.innerHTML).to.equal('<div>Error: Error!</div>');\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/getDerivedStateFromProps.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('static getDerivedStateFromProps', () => {\n\t\tit('should set initial state with value returned from getDerivedStateFromProps', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tstatic getDerivedStateFromProps(props) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfoo: props.foo,\n\t\t\t\t\t\tbar: 'bar'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div className={`${this.state.foo} ${this.state.bar}`} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo foo=\"foo\" />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.be.equal('foo bar');\n\t\t});\n\n\t\tit('should update initial state with value returned from getDerivedStateFromProps', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tfoo: 'foo',\n\t\t\t\t\t\tbar: 'bar'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tfoo: `not-${state.foo}`\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div className={`${this.state.foo} ${this.state.bar}`} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('not-foo bar');\n\t\t});\n\n\t\tit(\"should update the instance's state with the value returned from getDerivedStateFromProps when props change\", () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 'initial'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props) {\n\t\t\t\t\tif (props.update) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tvalue: 'updated'\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\tcomponentDidUpdate() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div className={this.state.value} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo, 'getDerivedStateFromProps');\n\t\t\tvi.spyOn(Foo.prototype, 'componentDidMount');\n\t\t\tvi.spyOn(Foo.prototype, 'componentDidUpdate');\n\n\t\t\trender(<Foo update={false} />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('initial');\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.componentDidMount).toHaveBeenCalledTimes(1); // verify mount occurred\n\t\t\texpect(Foo.prototype.componentDidUpdate).toHaveBeenCalledTimes(0);\n\n\t\t\trender(<Foo update />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('updated');\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalledTimes(2);\n\t\t\texpect(Foo.prototype.componentDidMount).toHaveBeenCalledTimes(1);\n\t\t\texpect(Foo.prototype.componentDidUpdate).toHaveBeenCalledTimes(1); // verify update occurred\n\t\t});\n\n\t\tit(\"should update the instance's state with the value returned from getDerivedStateFromProps when state changes\", () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 'initial'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\t// Don't change state for call that happens after the constructor\n\t\t\t\t\tif (state.value === 'initial') {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: state.value + ' derived'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\t// eslint-disable-next-line react/no-did-mount-set-state\n\t\t\t\t\tthis.setState({ value: 'updated' });\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div className={this.state.value} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo, 'getDerivedStateFromProps');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('initial');\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalledTimes(1);\n\n\t\t\trerender(); // call rerender to handle cDM setState call\n\t\t\texpect(scratch.firstChild.className).to.equal('updated derived');\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalledTimes(2);\n\t\t});\n\n\t\tit('should NOT modify state if null is returned', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tfoo: 'foo',\n\t\t\t\t\t\tbar: 'bar'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps() {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div className={`${this.state.foo} ${this.state.bar}`} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo, 'getDerivedStateFromProps');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('foo bar');\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalled();\n\t\t});\n\n\t\t// NOTE: Difference from React\n\t\t// React v16.3.2 warns if undefined if returned from getDerivedStateFromProps\n\t\tit('should NOT modify state if undefined is returned', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tfoo: 'foo',\n\t\t\t\t\t\tbar: 'bar'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div className={`${this.state.foo} ${this.state.bar}`} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo, 'getDerivedStateFromProps');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(scratch.firstChild.className).to.equal('foo bar');\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalled();\n\t\t});\n\n\t\tit('should NOT invoke deprecated lifecycles (cWM/cWRP) if new static gDSFP is present', () => {\n\t\t\tclass Foo extends Component {\n\t\t\t\tstatic getDerivedStateFromProps() {}\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentWillReceiveProps() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo, 'getDerivedStateFromProps');\n\t\t\tvi.spyOn(Foo.prototype, 'componentWillMount');\n\t\t\tvi.spyOn(Foo.prototype, 'componentWillReceiveProps');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\texpect(Foo.getDerivedStateFromProps).toHaveBeenCalled();\n\t\t\texpect(Foo.prototype.componentWillMount).not.toHaveBeenCalled();\n\t\t\texpect(Foo.prototype.componentWillReceiveProps).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('is not called if neither state nor props have changed', () => {\n\t\t\tlet logs = [];\n\t\t\tlet childRef;\n\n\t\t\tclass Parent extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { parentRenders: 0 };\n\t\t\t\t}\n\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\tlogs.push('parent getDerivedStateFromProps');\n\t\t\t\t\treturn state.parentRenders + 1;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tlogs.push('parent render');\n\t\t\t\t\treturn <Child parentRenders={this.state.parentRenders} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Child extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tchildRef = this;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tlogs.push('child render');\n\t\t\t\t\treturn this.props.parentRenders;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Parent />, scratch);\n\t\t\texpect(logs).to.deep.equal([\n\t\t\t\t'parent getDerivedStateFromProps',\n\t\t\t\t'parent render',\n\t\t\t\t'child render'\n\t\t\t]);\n\n\t\t\tlogs = [];\n\t\t\tchildRef.setState({});\n\t\t\trerender();\n\t\t\texpect(logs).to.deep.equal(['child render']);\n\t\t});\n\n\t\t// TODO: Investigate this test:\n\t\t// [should not override state with stale values if prevState is spread within getDerivedStateFromProps](https://github.com/facebook/react/blob/25dda90c1ecb0c662ab06e2c80c1ee31e0ae9d36/packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js#L1035)\n\n\t\tit('should be passed next props and state', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet updateState;\n\n\t\t\tlet propsArg;\n\t\t\tlet stateArg;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t\tupdateState = () =>\n\t\t\t\t\t\tthis.setState({\n\t\t\t\t\t\t\tvalue: this.state.value + 1\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\t// These object references might be updated later so copy\n\t\t\t\t\t// object so we can assert their values at this snapshot in time\n\t\t\t\t\tpropsArg = { ...props };\n\t\t\t\t\tstateArg = { ...state };\n\n\t\t\t\t\t// NOTE: Don't do this in real production code!\n\t\t\t\t\t// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: state.value + 1\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.state.value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Initial render\n\t\t\t// state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n\t\t\trender(<Foo foo=\"foo\" />, scratch);\n\n\t\t\tlet element = scratch.firstChild;\n\t\t\texpect(element.textContent).to.be.equal('1');\n\t\t\texpect(propsArg).to.deep.equal({\n\t\t\t\tfoo: 'foo'\n\t\t\t});\n\t\t\texpect(stateArg).to.deep.equal({\n\t\t\t\tvalue: 0\n\t\t\t});\n\n\t\t\t// New Props\n\t\t\t// state.value: 1 -> 2 in gDSFP\n\t\t\trender(<Foo foo=\"bar\" />, scratch);\n\t\t\texpect(element.textContent).to.be.equal('2');\n\t\t\texpect(propsArg).to.deep.equal({\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\t\t\texpect(stateArg).to.deep.equal({\n\t\t\t\tvalue: 1\n\t\t\t});\n\n\t\t\t// New state\n\t\t\t// state.value: 2 -> 3 in updateState, 3 -> 4 in gDSFP\n\t\t\tupdateState();\n\t\t\trerender();\n\t\t\texpect(element.textContent).to.be.equal('4');\n\t\t\texpect(propsArg).to.deep.equal({\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\t\t\texpect(stateArg).to.deep.equal({\n\t\t\t\tvalue: 3\n\t\t\t});\n\n\t\t\t// New Props (see #1446)\n\t\t\t// 4 -> 5 in gDSFP\n\t\t\trender(<Foo foo=\"baz\" />, scratch);\n\t\t\texpect(element.textContent).to.be.equal('5');\n\t\t\texpect(stateArg).to.deep.equal({\n\t\t\t\tvalue: 4\n\t\t\t});\n\n\t\t\t// New Props (see #1446)\n\t\t\t// 5 -> 6 in gDSFP\n\t\t\trender(<Foo foo=\"qux\" />, scratch);\n\t\t\texpect(element.textContent).to.be.equal('6');\n\t\t\texpect(stateArg).to.deep.equal({\n\t\t\t\tvalue: 5\n\t\t\t});\n\t\t});\n\n\t\t// From preactjs/preact#1170\n\t\tit('should NOT mutate state on mount, only create new versions', () => {\n\t\t\tconst stateConstant = {};\n\t\t\tlet componentState;\n\n\t\t\tclass Stateful extends Component {\n\t\t\t\tstatic getDerivedStateFromProps() {\n\t\t\t\t\treturn { key: 'value' };\n\t\t\t\t}\n\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper(...arguments);\n\t\t\t\t\tthis.state = stateConstant;\n\t\t\t\t}\n\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tcomponentState = this.state;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Stateful />, scratch);\n\n\t\t\t// Verify captured object references didn't get mutated\n\t\t\texpect(componentState).to.deep.equal({ key: 'value' });\n\t\t\texpect(stateConstant).to.deep.equal({});\n\t\t});\n\n\t\tit('should NOT mutate state on update, only create new versions', () => {\n\t\t\tconst initialState = {};\n\t\t\tconst capturedStates = [];\n\n\t\t\tlet setState;\n\n\t\t\tclass Stateful extends Component {\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\treturn { value: (state.value || 0) + 1 };\n\t\t\t\t}\n\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper(...arguments);\n\t\t\t\t\tthis.state = initialState;\n\t\t\t\t\tcapturedStates.push(this.state);\n\n\t\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t\t}\n\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tcapturedStates.push(this.state);\n\t\t\t\t}\n\n\t\t\t\tcomponentDidUpdate() {\n\t\t\t\t\tcapturedStates.push(this.state);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Stateful />, scratch);\n\n\t\t\tsetState({ value: 10 });\n\t\t\trerender();\n\n\t\t\t// Verify captured object references didn't get mutated\n\t\t\texpect(capturedStates).to.deep.equal([{}, { value: 1 }, { value: 11 }]);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/getSnapshotBeforeUpdate.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#getSnapshotBeforeUpdate', () => {\n\t\tit('should pass the return value from getSnapshotBeforeUpdate to componentDidUpdate', () => {\n\t\t\tlet log = [];\n\n\t\t\tclass MyComponent extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(nextProps, prevState) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: prevState.value + 1\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tgetSnapshotBeforeUpdate(prevProps, prevState) {\n\t\t\t\t\tlog.push(\n\t\t\t\t\t\t`getSnapshotBeforeUpdate() prevProps:${prevProps.value} prevState:${prevState.value}`\n\t\t\t\t\t);\n\t\t\t\t\treturn 'abc';\n\t\t\t\t}\n\t\t\t\tcomponentDidUpdate(prevProps, prevState, snapshot) {\n\t\t\t\t\tlog.push(\n\t\t\t\t\t\t`componentDidUpdate() prevProps:${prevProps.value} prevState:${prevState.value} snapshot:${snapshot}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tlog.push('render');\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<MyComponent value=\"foo\" />, scratch);\n\t\t\texpect(log).to.deep.equal(['render']);\n\t\t\tlog = [];\n\n\t\t\trender(<MyComponent value=\"bar\" />, scratch);\n\t\t\texpect(log).to.deep.equal([\n\t\t\t\t'render',\n\t\t\t\t'getSnapshotBeforeUpdate() prevProps:foo prevState:1',\n\t\t\t\t'componentDidUpdate() prevProps:foo prevState:1 snapshot:abc'\n\t\t\t]);\n\t\t\tlog = [];\n\n\t\t\trender(<MyComponent value=\"baz\" />, scratch);\n\t\t\texpect(log).to.deep.equal([\n\t\t\t\t'render',\n\t\t\t\t'getSnapshotBeforeUpdate() prevProps:bar prevState:2',\n\t\t\t\t'componentDidUpdate() prevProps:bar prevState:2 snapshot:abc'\n\t\t\t]);\n\t\t\tlog = [];\n\n\t\t\trender(<div />, scratch, scratch.firstChild);\n\t\t\texpect(log).to.deep.equal([]);\n\t\t});\n\n\t\tit('should call getSnapshotBeforeUpdate before mutations are committed', () => {\n\t\t\tlet log = [];\n\n\t\t\tclass MyComponent extends Component {\n\t\t\t\tgetSnapshotBeforeUpdate(prevProps) {\n\t\t\t\t\tlog.push('getSnapshotBeforeUpdate');\n\t\t\t\t\texpect(this.divRef.textContent).to.equal(`value:${prevProps.value}`);\n\t\t\t\t\treturn 'foobar';\n\t\t\t\t}\n\t\t\t\tcomponentDidUpdate(prevProps, prevState, snapshot) {\n\t\t\t\t\tlog.push('componentDidUpdate');\n\t\t\t\t\texpect(this.divRef.textContent).to.equal(`value:${this.props.value}`);\n\t\t\t\t\texpect(snapshot).to.equal('foobar');\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tlog.push('render');\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tref={ref => (this.divRef = ref)}\n\t\t\t\t\t\t>{`value:${this.props.value}`}</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<MyComponent value=\"foo\" />, scratch);\n\t\t\texpect(log).to.deep.equal(['render']);\n\t\t\tlog = [];\n\n\t\t\trender(<MyComponent value=\"bar\" />, scratch);\n\t\t\texpect(log).to.deep.equal([\n\t\t\t\t'render',\n\t\t\t\t'getSnapshotBeforeUpdate',\n\t\t\t\t'componentDidUpdate'\n\t\t\t]);\n\t\t});\n\n\t\tit('should be passed the previous props and state', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet updateState;\n\n\t\t\tlet prevPropsArg;\n\t\t\tlet prevStateArg;\n\t\t\tlet curProps;\n\t\t\tlet curState;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t\tupdateState = () =>\n\t\t\t\t\t\tthis.setState({\n\t\t\t\t\t\t\tvalue: this.state.value + 1\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\t// NOTE: Don't do this in real production code!\n\t\t\t\t\t// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: state.value + 1\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tgetSnapshotBeforeUpdate(prevProps, prevState) {\n\t\t\t\t\t// These object references might be updated later so copy\n\t\t\t\t\t// object so we can assert their values at this snapshot in time\n\t\t\t\t\tprevPropsArg = { ...prevProps };\n\t\t\t\t\tprevStateArg = { ...prevState };\n\n\t\t\t\t\tcurProps = { ...this.props };\n\t\t\t\t\tcurState = { ...this.state };\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.state.value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Expectation:\n\t\t\t// `prevState` in getSnapshotBeforeUpdate should be\n\t\t\t// the state before setState or getDerivedStateFromProps was called.\n\t\t\t// `this.state` in getSnapshotBeforeUpdate should be\n\t\t\t// the updated state after getDerivedStateFromProps was called.\n\n\t\t\t// Initial render\n\t\t\t// state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n\t\t\trender(<Foo foo=\"foo\" />, scratch);\n\t\t\tconst element = scratch.firstChild;\n\n\t\t\texpect(element.textContent).to.be.equal('1');\n\t\t\texpect(prevPropsArg).to.be.undefined;\n\t\t\texpect(prevStateArg).to.be.undefined;\n\t\t\texpect(curProps).to.be.undefined;\n\t\t\texpect(curState).to.be.undefined;\n\n\t\t\t// New props\n\t\t\t// state.value: 1 -> 2 in gDSFP\n\t\t\trender(<Foo foo=\"bar\" />, scratch);\n\n\t\t\texpect(element.textContent).to.be.equal('2');\n\t\t\texpect(prevPropsArg).to.deep.equal({\n\t\t\t\tfoo: 'foo'\n\t\t\t});\n\t\t\texpect(prevStateArg).to.deep.equal({\n\t\t\t\tvalue: 1\n\t\t\t});\n\t\t\texpect(curProps).to.deep.equal({\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\t\t\texpect(curState).to.deep.equal({\n\t\t\t\tvalue: 2\n\t\t\t});\n\n\t\t\t// New state\n\t\t\t// state.value: 2 -> 3 in updateState, 3 -> 4 in gDSFP\n\t\t\tupdateState();\n\t\t\trerender();\n\t\t\texpect(element.textContent).to.be.equal('4');\n\t\t\texpect(prevPropsArg).to.deep.equal({\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\t\t\texpect(prevStateArg).to.deep.equal({\n\t\t\t\tvalue: 2\n\t\t\t});\n\t\t\texpect(curProps).to.deep.equal({\n\t\t\t\tfoo: 'bar'\n\t\t\t});\n\t\t\texpect(curState).to.deep.equal({\n\t\t\t\tvalue: 4\n\t\t\t});\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/lifecycle.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should call nested new lifecycle methods in the right order', () => {\n\t\tlet updateOuterState;\n\t\tlet updateInnerState;\n\t\tlet forceUpdateOuter;\n\t\tlet forceUpdateInner;\n\n\t\tlet log;\n\t\tfunction logger(msg) {\n\t\t\treturn function () {\n\t\t\t\t// return true for shouldComponentUpdate\n\t\t\t\tlog.push(msg);\n\t\t\t\treturn true;\n\t\t\t};\n\t\t}\n\n\t\tclass Outer extends Component {\n\t\t\tstatic getDerivedStateFromProps() {\n\t\t\t\tlog.push('outer getDerivedStateFromProps');\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tlog.push('outer constructor');\n\n\t\t\t\tthis.state = { value: 0 };\n\t\t\t\tforceUpdateOuter = () =>\n\t\t\t\t\tthis.forceUpdate(() => log.push('outer forceUpdate callback'));\n\t\t\t\tupdateOuterState = () =>\n\t\t\t\t\tthis.setState(\n\t\t\t\t\t\tprevState => ({ value: prevState.value % 2 }),\n\t\t\t\t\t\t() => log.push('outer setState callback')\n\t\t\t\t\t);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tlog.push('outer render');\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Inner x={this.props.x} outerValue={this.state.value} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tObject.assign(Outer.prototype, {\n\t\t\tcomponentDidMount: logger('outer componentDidMount'),\n\t\t\tshouldComponentUpdate: logger('outer shouldComponentUpdate'),\n\t\t\tgetSnapshotBeforeUpdate: logger('outer getSnapshotBeforeUpdate'),\n\t\t\tcomponentDidUpdate: logger('outer componentDidUpdate'),\n\t\t\tcomponentWillUnmount: logger('outer componentWillUnmount')\n\t\t});\n\n\t\tclass Inner extends Component {\n\t\t\tstatic getDerivedStateFromProps() {\n\t\t\t\tlog.push('inner getDerivedStateFromProps');\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tlog.push('inner constructor');\n\n\t\t\t\tthis.state = { value: 0 };\n\t\t\t\tforceUpdateInner = () =>\n\t\t\t\t\tthis.forceUpdate(() => log.push('inner forceUpdate callback'));\n\t\t\t\tupdateInnerState = () =>\n\t\t\t\t\tthis.setState(\n\t\t\t\t\t\tprevState => ({ value: prevState.value % 2 }),\n\t\t\t\t\t\t() => log.push('inner setState callback')\n\t\t\t\t\t);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tlog.push('inner render');\n\t\t\t\treturn (\n\t\t\t\t\t<span>\n\t\t\t\t\t\t{this.props.x} {this.props.outerValue} {this.state.value}\n\t\t\t\t\t</span>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tObject.assign(Inner.prototype, {\n\t\t\tcomponentDidMount: logger('inner componentDidMount'),\n\t\t\tshouldComponentUpdate: logger('inner shouldComponentUpdate'),\n\t\t\tgetSnapshotBeforeUpdate: logger('inner getSnapshotBeforeUpdate'),\n\t\t\tcomponentDidUpdate: logger('inner componentDidUpdate'),\n\t\t\tcomponentWillUnmount: logger('inner componentWillUnmount')\n\t\t});\n\n\t\t// Constructor & mounting\n\t\tlog = [];\n\t\trender(<Outer x={1} />, scratch);\n\t\texpect(log).to.deep.equal([\n\t\t\t'outer constructor',\n\t\t\t'outer getDerivedStateFromProps',\n\t\t\t'outer render',\n\t\t\t'inner constructor',\n\t\t\t'inner getDerivedStateFromProps',\n\t\t\t'inner render',\n\t\t\t'inner componentDidMount',\n\t\t\t'outer componentDidMount'\n\t\t]);\n\n\t\t// Outer & Inner props update\n\t\tlog = [];\n\t\trender(<Outer x={2} />, scratch);\n\t\t// Note: we differ from react here in that we apply changes to the dom\n\t\t// as we find them while diffing. React on the other hand separates this\n\t\t// into specific phases, meaning changes to the dom are only flushed\n\t\t// once the whole diff-phase is complete. This is why\n\t\t// \"outer getSnapshotBeforeUpdate\" is called just before the \"inner\" hooks.\n\t\t// For react this call would be right before \"outer componentDidUpdate\"\n\t\texpect(log).to.deep.equal([\n\t\t\t'outer getDerivedStateFromProps',\n\t\t\t'outer shouldComponentUpdate',\n\t\t\t'outer render',\n\t\t\t'outer getSnapshotBeforeUpdate',\n\t\t\t'inner getDerivedStateFromProps',\n\t\t\t'inner shouldComponentUpdate',\n\t\t\t'inner render',\n\t\t\t'inner getSnapshotBeforeUpdate',\n\t\t\t'inner componentDidUpdate',\n\t\t\t'outer componentDidUpdate'\n\t\t]);\n\n\t\t// Outer state update & Inner props update\n\t\tlog = [];\n\t\tupdateOuterState();\n\t\trerender();\n\t\texpect(log).to.deep.equal([\n\t\t\t'outer getDerivedStateFromProps',\n\t\t\t'outer shouldComponentUpdate',\n\t\t\t'outer render',\n\t\t\t'outer getSnapshotBeforeUpdate',\n\t\t\t'inner getDerivedStateFromProps',\n\t\t\t'inner shouldComponentUpdate',\n\t\t\t'inner render',\n\t\t\t'inner getSnapshotBeforeUpdate',\n\t\t\t'inner componentDidUpdate',\n\t\t\t'outer componentDidUpdate',\n\t\t\t'outer setState callback'\n\t\t]);\n\n\t\t// Inner state update\n\t\tlog = [];\n\t\tupdateInnerState();\n\t\trerender();\n\t\texpect(log).to.deep.equal([\n\t\t\t'inner getDerivedStateFromProps',\n\t\t\t'inner shouldComponentUpdate',\n\t\t\t'inner render',\n\t\t\t'inner getSnapshotBeforeUpdate',\n\t\t\t'inner componentDidUpdate',\n\t\t\t'inner setState callback'\n\t\t]);\n\n\t\t// Force update Outer\n\t\tlog = [];\n\t\tforceUpdateOuter();\n\t\trerender();\n\t\texpect(log).to.deep.equal([\n\t\t\t'outer getDerivedStateFromProps',\n\t\t\t'outer render',\n\t\t\t'outer getSnapshotBeforeUpdate',\n\t\t\t'inner getDerivedStateFromProps',\n\t\t\t'inner shouldComponentUpdate',\n\t\t\t'inner render',\n\t\t\t'inner getSnapshotBeforeUpdate',\n\t\t\t'inner componentDidUpdate',\n\t\t\t'outer forceUpdate callback',\n\t\t\t'outer componentDidUpdate'\n\t\t]);\n\n\t\t// Force update Inner\n\t\tlog = [];\n\t\tforceUpdateInner();\n\t\trerender();\n\t\texpect(log).to.deep.equal([\n\t\t\t'inner getDerivedStateFromProps',\n\t\t\t'inner render',\n\t\t\t'inner getSnapshotBeforeUpdate',\n\t\t\t'inner forceUpdate callback',\n\t\t\t'inner componentDidUpdate'\n\t\t]);\n\n\t\t// Unmounting Outer & Inner\n\t\tlog = [];\n\t\trender(<table />, scratch);\n\t\texpect(log).to.deep.equal([\n\t\t\t'outer componentWillUnmount',\n\t\t\t'inner componentWillUnmount'\n\t\t]);\n\t});\n\n\tdescribe('#constructor and component(Did|Will)(Mount|Unmount)', () => {\n\t\tlet setState;\n\t\tclass Outer extends Component {\n\t\t\tconstructor(p, c) {\n\t\t\t\tsuper(p, c);\n\t\t\t\tthis.state = { show: true };\n\t\t\t\tsetState = s => this.setState(s);\n\t\t\t}\n\t\t\trender(props, { show }) {\n\t\t\t\treturn <div>{show && <Inner {...props} />}</div>;\n\t\t\t}\n\t\t}\n\n\t\tclass LifecycleTestComponent extends Component {\n\t\t\tcomponentWillMount() {}\n\t\t\tcomponentDidMount() {}\n\t\t\tcomponentWillUnmount() {}\n\t\t\trender() {\n\t\t\t\treturn <div />;\n\t\t\t}\n\t\t}\n\n\t\tclass Inner extends LifecycleTestComponent {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<InnerMost />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass InnerMost extends LifecycleTestComponent {\n\t\t\trender() {\n\t\t\t\treturn <div />;\n\t\t\t}\n\t\t}\n\n\t\tlet spies = [\n\t\t\t'componentWillMount',\n\t\t\t'componentDidMount',\n\t\t\t'componentWillUnmount'\n\t\t];\n\n\t\tlet verifyLifecycleMethods = TestComponent => {\n\t\t\tlet proto = TestComponent.prototype;\n\t\t\tspies.forEach(s => vi.spyOn(proto, s));\n\t\t\tlet reset = () => spies.forEach(s => proto[s].mockClear());\n\n\t\t\tit('should be invoked for components on initial render', () => {\n\t\t\t\treset();\n\t\t\t\trender(<Outer />, scratch);\n\t\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t\t\texpect(proto.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\t\tproto.componentDidMount\n\t\t\t\t);\n\t\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t\t});\n\n\t\t\tit('should be invoked for components on unmount', () => {\n\t\t\t\treset();\n\t\t\t\tsetState({ show: false });\n\t\t\t\trerender();\n\n\t\t\t\texpect(proto.componentWillUnmount).toHaveBeenCalled();\n\t\t\t});\n\n\t\t\tit('should be invoked for components on re-render', () => {\n\t\t\t\treset();\n\t\t\t\tsetState({ show: true });\n\t\t\t\trerender();\n\n\t\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t\t\texpect(proto.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\t\tproto.componentDidMount\n\t\t\t\t);\n\t\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t\t});\n\t\t};\n\n\t\tdescribe('inner components', () => {\n\t\t\tverifyLifecycleMethods(Inner);\n\t\t});\n\n\t\tdescribe('innermost components', () => {\n\t\t\tverifyLifecycleMethods(InnerMost);\n\t\t});\n\n\t\tdescribe('when shouldComponentUpdate() returns false', () => {\n\t\t\tlet setState;\n\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { show: true };\n\t\t\t\t\tsetState = s => this.setState(s);\n\t\t\t\t}\n\t\t\t\trender(props, { show }) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t{show && (\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<Inner {...props} />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tcomponentWillMount() {}\n\t\t\t\tcomponentDidMount() {}\n\t\t\t\tcomponentWillUnmount() {}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet proto = Inner.prototype;\n\t\t\tlet spies = [\n\t\t\t\t'componentWillMount',\n\t\t\t\t'componentDidMount',\n\t\t\t\t'componentWillUnmount'\n\t\t\t];\n\t\t\tspies.forEach(s => vi.spyOn(proto, s));\n\n\t\t\tlet reset = () => spies.forEach(s => proto[s].mockClear());\n\n\t\t\tbeforeEach(() => reset());\n\n\t\t\tit('should be invoke normally on initial mount', () => {\n\t\t\t\trender(<Outer />, scratch);\n\t\t\t\texpect(proto.componentWillMount).toHaveBeenCalled();\n\t\t\t\texpect(proto.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\t\tproto.componentDidMount\n\t\t\t\t);\n\t\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t\t});\n\n\t\t\tit('should be invoked normally on unmount', () => {\n\t\t\t\tsetState({ show: false });\n\t\t\t\trerender();\n\n\t\t\t\texpect(proto.componentWillUnmount).toHaveBeenCalled();\n\t\t\t});\n\n\t\t\tit('should still invoke mount for shouldComponentUpdate():false', () => {\n\t\t\t\tsetState({ show: true });\n\t\t\t\trerender();\n\n\t\t\t\texpect(proto.componentWillMount).toHaveBeenCalled();\n\t\t\t\texpect(proto.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\t\tproto.componentDidMount\n\t\t\t\t);\n\t\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t\t});\n\n\t\t\tit('should still invoke unmount for shouldComponentUpdate():false', () => {\n\t\t\t\tsetState({ show: false });\n\t\t\t\trerender();\n\n\t\t\t\texpect(proto.componentWillUnmount).toHaveBeenCalled();\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('#setState', () => {\n\t\t// From preactjs/preact#1170\n\t\tit('should NOT mutate state, only create new versions', () => {\n\t\t\tconst stateConstant = {};\n\t\t\tlet didMount = false;\n\t\t\tlet componentState;\n\n\t\t\tclass Stateful extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper(...arguments);\n\t\t\t\t\tthis.state = stateConstant;\n\t\t\t\t}\n\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tdidMount = true;\n\n\t\t\t\t\t// eslint-disable-next-line react/no-did-mount-set-state\n\t\t\t\t\tthis.setState({ key: 'value' }, () => {\n\t\t\t\t\t\tcomponentState = this.state;\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Stateful />, scratch);\n\t\t\trerender();\n\n\t\t\texpect(didMount).to.equal(true);\n\t\t\texpect(componentState).to.deep.equal({ key: 'value' });\n\t\t\texpect(stateConstant).to.deep.equal({});\n\t\t});\n\n\t\t// This feature is not mentioned in the docs, but is part of the release\n\t\t// notes for react v16.0.0: https://reactjs.org/blog/2017/09/26/react-v16.0.html#breaking-changes\n\t\tit('should abort if updater function returns null', () => {\n\t\t\tlet updateState;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { value: 0 };\n\t\t\t\t\tupdateState = () =>\n\t\t\t\t\t\tthis.setState(prev => {\n\t\t\t\t\t\t\tprev.value++;\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn 'value: ' + this.state.value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet renderSpy = vi.spyOn(Foo.prototype, 'render');\n\t\t\trender(<Foo />, scratch);\n\t\t\trenderSpy.mockClear();\n\n\t\t\tupdateState();\n\t\t\trerender();\n\t\t\texpect(renderSpy).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should call callback with correct this binding', () => {\n\t\t\tlet inst;\n\t\t\tlet updateState;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tupdateState = () => this.setState({}, this.onUpdate);\n\t\t\t\t}\n\n\t\t\t\tonUpdate() {\n\t\t\t\t\tinst = this;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(inst).to.be.instanceOf(Foo);\n\t\t});\n\t});\n\n\tdescribe('Lifecycle DOM Timing', () => {\n\t\tit('should be invoked when dom does (DidMount, WillUnmount) or does not (WillMount, DidUnmount) exist', () => {\n\t\t\tlet setState;\n\t\t\tclass Outer extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { show: true };\n\t\t\t\t\tsetState = s => {\n\t\t\t\t\t\tthis.setState(s);\n\t\t\t\t\t\tthis.forceUpdate();\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\texpect(\n\t\t\t\t\t\tdocument.getElementById('OuterDiv'),\n\t\t\t\t\t\t'Outer componentWillMount'\n\t\t\t\t\t).to.not.exist;\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\texpect(document.getElementById('OuterDiv'), 'Outer componentDidMount')\n\t\t\t\t\t\t.to.exist;\n\t\t\t\t}\n\t\t\t\tcomponentWillUnmount() {\n\t\t\t\t\texpect(\n\t\t\t\t\t\tdocument.getElementById('OuterDiv'),\n\t\t\t\t\t\t'Outer componentWillUnmount'\n\t\t\t\t\t).to.exist;\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\texpect(\n\t\t\t\t\t\t\tdocument.getElementById('OuterDiv'),\n\t\t\t\t\t\t\t'Outer after componentWillUnmount'\n\t\t\t\t\t\t).to.not.exist;\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t\trender(props, { show }) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div id=\"OuterDiv\">\n\t\t\t\t\t\t\t{show && (\n\t\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t\t<Inner {...props} />\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Inner extends Component {\n\t\t\t\tcomponentWillMount() {\n\t\t\t\t\texpect(\n\t\t\t\t\t\tdocument.getElementById('InnerDiv'),\n\t\t\t\t\t\t'Inner componentWillMount'\n\t\t\t\t\t).to.not.exist;\n\t\t\t\t}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\texpect(document.getElementById('InnerDiv'), 'Inner componentDidMount')\n\t\t\t\t\t\t.to.exist;\n\t\t\t\t}\n\t\t\t\tcomponentWillUnmount() {\n\t\t\t\t\t// @TODO Component mounted into elements (non-components)\n\t\t\t\t\t// are currently unmounted after those elements, so their\n\t\t\t\t\t// DOM is unmounted prior to the method being called.\n\t\t\t\t\t//expect(document.getElementById('InnerDiv'), 'Inner componentWillUnmount').to.exist;\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\texpect(\n\t\t\t\t\t\t\tdocument.getElementById('InnerDiv'),\n\t\t\t\t\t\t\t'Inner after componentWillUnmount'\n\t\t\t\t\t\t).to.not.exist;\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <div id=\"InnerDiv\" />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet proto = Inner.prototype;\n\t\t\tlet spies = [\n\t\t\t\t'componentWillMount',\n\t\t\t\t'componentDidMount',\n\t\t\t\t'componentWillUnmount'\n\t\t\t];\n\t\t\tspies.forEach(s => vi.spyOn(proto, s));\n\n\t\t\tlet reset = () => spies.forEach(s => proto[s].mockClear());\n\n\t\t\trender(<Outer />, scratch);\n\t\t\texpect(proto.componentWillMount).toHaveBeenCalled();\n\t\t\texpect(proto.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\tproto.componentDidMount\n\t\t\t);\n\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\n\t\t\treset();\n\t\t\tsetState({ show: false });\n\t\t\trerender();\n\n\t\t\texpect(proto.componentWillUnmount).toHaveBeenCalled();\n\n\t\t\treset();\n\t\t\tsetState({ show: true });\n\t\t\trerender();\n\n\t\t\texpect(proto.componentWillMount).toHaveBeenCalled();\n\t\t\texpect(proto.componentWillMount).toHaveBeenCalledBefore(\n\t\t\t\tproto.componentDidMount\n\t\t\t);\n\t\t\texpect(proto.componentDidMount).toHaveBeenCalled();\n\t\t});\n\n\t\tit('should be able to use getDerivedStateFromError and componentDidCatch together', () => {\n\t\t\tlet didCatch = vi.fn(),\n\t\t\t\tgetDerived = vi.fn();\n\t\t\tconst error = new Error('hi');\n\n\t\t\tclass Boundary extends Component {\n\t\t\t\tstatic getDerivedStateFromError(err) {\n\t\t\t\t\tgetDerived(err);\n\t\t\t\t\treturn { err };\n\t\t\t\t}\n\n\t\t\t\tcomponentDidCatch(err) {\n\t\t\t\t\tdidCatch(err);\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.err ? <div /> : this.props.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst ThrowErr = () => {\n\t\t\t\tthrow error;\n\t\t\t};\n\n\t\t\trender(\n\t\t\t\t<Boundary>\n\t\t\t\t\t<ThrowErr />\n\t\t\t\t</Boundary>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\trerender();\n\n\t\t\texpect(didCatch).toHaveBeenCalledWith(error);\n\n\t\t\texpect(getDerived).toHaveBeenCalledWith(error);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/lifecycles/shouldComponentUpdate.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component, Fragment } from 'preact';\nimport { vi } from 'vitest';\nimport { setupScratch, teardown } from '../../_util/helpers';\nimport { logCall, getLog, clearLog } from '../../_util/logCall';\n\ndescribe('Lifecycle methods', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t// function expectDomLogToBe(expectedOperations, message) {\n\t// \texpect(getLog()).to.deep.equal(expectedOperations, message);\n\t// }\n\tlet resetInsertBefore;\n\tlet resetRemoveChild;\n\tlet resetRemove;\n\n\tbeforeAll(() => {\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetRemoveChild = logCall(Element.prototype, 'appendChild');\n\t\tresetRemove = logCall(Element.prototype, 'removeChild');\n\t});\n\n\tafterAll(() => {\n\t\tresetInsertBefore();\n\t\tresetRemoveChild();\n\t\tresetRemove();\n\t});\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\n\t\tclearLog();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('#shouldComponentUpdate', () => {\n\t\tlet setState;\n\n\t\tclass Should extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { show: true };\n\t\t\t\tsetState = s => this.setState(s);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.state.show ? <div /> : null;\n\t\t\t}\n\t\t}\n\n\t\tclass ShouldNot extends Should {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tbeforeEach(() => {\n\t\t\tvi.spyOn(Should.prototype, 'render');\n\t\t\tvi.spyOn(ShouldNot.prototype, 'render');\n\t\t\tvi.spyOn(ShouldNot.prototype, 'shouldComponentUpdate');\n\t\t});\n\n\t\tit('should rerender component on change by default', () => {\n\t\t\trender(<Should />, scratch);\n\t\t\tsetState({ show: false });\n\t\t\trerender();\n\n\t\t\texpect(Should.prototype.render).toHaveBeenCalledTimes(2);\n\t\t});\n\n\t\tit('should not rerender component if shouldComponentUpdate returns false', () => {\n\t\t\trender(<ShouldNot />, scratch);\n\t\t\tsetState({ show: false });\n\t\t\trerender();\n\n\t\t\texpect(ShouldNot.prototype.shouldComponentUpdate).toHaveBeenCalledOnce();\n\t\t\texpect(ShouldNot.prototype.render).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should reorder non-updating text children', () => {\n\t\t\tconst rows = [\n\t\t\t\t{ id: '1', a: 5, b: 100 },\n\t\t\t\t{ id: '2', a: 50, b: 10 },\n\t\t\t\t{ id: '3', a: 25, b: 1000 }\n\t\t\t];\n\n\t\t\tclass Row extends Component {\n\t\t\t\tshouldComponentUpdate(nextProps) {\n\t\t\t\t\treturn nextProps.id !== this.props.id;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn this.props.id;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst App = ({ sortBy }) => (\n\t\t\t\t<div>\n\t\t\t\t\t<table>\n\t\t\t\t\t\t{rows\n\t\t\t\t\t\t\t.sort((a, b) => (a[sortBy] > b[sortBy] ? -1 : 1))\n\t\t\t\t\t\t\t.map(row => (\n\t\t\t\t\t\t\t\t<Row id={row.id} key={row.id} />\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t</table>\n\t\t\t\t</div>\n\t\t\t);\n\n\t\t\trender(<App sortBy=\"a\" />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div><table>231</table></div>');\n\n\t\t\trender(<App sortBy=\"b\" />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div><table>312</table></div>');\n\t\t});\n\n\t\tit('should rerender when sCU returned false before', () => {\n\t\t\tlet c;\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tc = this;\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate(_, nextState) {\n\t\t\t\t\treturn !!nextState.update;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tspy();\n\t\t\t\t\treturn <div>foo</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\n\t\t\tc.setState({});\n\t\t\trerender();\n\t\t\tspy.mockClear();\n\n\t\t\tc.setState({ update: true });\n\t\t\trerender();\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should be called with nextState', () => {\n\t\t\tlet c;\n\t\t\tlet spy = vi.fn();\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tc = this;\n\t\t\t\t\tthis.state = { a: false };\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate(_, nextState) {\n\t\t\t\t\treturn this.state !== nextState;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\tspy();\n\t\t\t\t\treturn <div>foo</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\n\t\t\tc.setState({});\n\t\t\trerender();\n\t\t\tspy.mockClear();\n\n\t\t\tc.setState({ a: true });\n\t\t\trerender();\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should clear renderCallbacks', () => {\n\t\t\tconst spy = vi.fn();\n\t\t\tlet c,\n\t\t\t\trenders = 0;\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tc = this;\n\t\t\t\t\tthis.state = { a: false };\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate(_, nextState) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\trenders += 1;\n\t\t\t\t\treturn <div>foo</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(renders).to.equal(1);\n\n\t\t\tc.setState({}, spy);\n\t\t\trerender();\n\t\t\texpect(renders).to.equal(1);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should not be called on forceUpdate', () => {\n\t\t\tlet Comp;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tComp = this;\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <ShouldNot />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo.prototype, 'shouldComponentUpdate');\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\tComp.forceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(Foo.prototype.shouldComponentUpdate).not.toHaveBeenCalled();\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(2);\n\t\t});\n\n\t\tit('should not be called on forceUpdate followed by setState', () => {\n\t\t\tlet Comp;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tComp = this;\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn <ShouldNot />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvi.spyOn(Foo.prototype, 'shouldComponentUpdate');\n\t\t\tvi.spyOn(Foo.prototype, 'render');\n\n\t\t\trender(<Foo />, scratch);\n\t\t\tComp.forceUpdate();\n\t\t\tComp.setState({});\n\t\t\trerender();\n\n\t\t\texpect(Foo.prototype.render).toHaveBeenCalledTimes(2);\n\t\t\texpect(Foo.prototype.shouldComponentUpdate).not.toHaveBeenCalled();\n\t\t});\n\n\t\tit('should not block queued child forceUpdate', () => {\n\t\t\tlet i = 0;\n\t\t\tlet updateInner;\n\t\t\tclass Inner extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn i === 0;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tupdateInner = () => this.forceUpdate();\n\t\t\t\t\treturn <div>{++i}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet updateOuter;\n\t\t\tclass Outer extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn i === 0;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\tupdateOuter = () => this.forceUpdate();\n\t\t\t\t\treturn <Inner />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass App extends Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <Outer />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\n\t\t\tupdateOuter();\n\t\t\tupdateInner();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('2');\n\n\t\t\t// The inner sCU should return false on second render because\n\t\t\t// it was not enqueued via forceUpdate\n\t\t\tupdateOuter();\n\t\t\trerender();\n\t\t\texpect(scratch.textContent).to.equal('2');\n\t\t});\n\n\t\tit('should be passed next props and state', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet updateState;\n\n\t\t\tlet curProps;\n\t\t\tlet curState;\n\t\t\tlet nextPropsArg;\n\t\t\tlet nextStateArg;\n\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = {\n\t\t\t\t\t\tvalue: 0\n\t\t\t\t\t};\n\t\t\t\t\tupdateState = () =>\n\t\t\t\t\t\tthis.setState({\n\t\t\t\t\t\t\tvalue: this.state.value + 1\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tstatic getDerivedStateFromProps(props, state) {\n\t\t\t\t\t// NOTE: Don't do this in real production code!\n\t\t\t\t\t// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html\n\t\t\t\t\treturn {\n\t\t\t\t\t\tvalue: state.value + 1\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tshouldComponentUpdate(nextProps, nextState) {\n\t\t\t\t\tnextPropsArg = { ...nextProps };\n\t\t\t\t\tnextStateArg = { ...nextState };\n\n\t\t\t\t\tcurProps = { ...this.props };\n\t\t\t\t\tcurState = { ...this.state };\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div>{this.state.value}</div>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Expectation:\n\t\t\t// `this.state` in shouldComponentUpdate should be\n\t\t\t// the state before setState or getDerivedStateFromProps was called\n\t\t\t// `nextState` in shouldComponentUpdate should be\n\t\t\t// the updated state after getDerivedStateFromProps was called\n\n\t\t\t// Initial render\n\t\t\t// state.value: initialized to 0 in constructor, 0 -> 1 in gDSFP\n\t\t\trender(<Foo foo=\"foo\" />, scratch);\n\t\t\texpect(scratch.firstChild.textContent).to.be.equal('1');\n\t\t\texpect(curProps).to.be.undefined;\n\t\t\texpect(curState).to.be.undefined;\n\t\t\texpect(nextPropsArg).to.be.undefined;\n\t\t\texpect(nextStateArg).to.be.undefined;\n\n\t\t\t// New props\n\t\t\t// state.value: 1 -> 2 in gDSFP\n\t\t\trender(<Foo foo=\"bar\" />, scratch);\n\t\t\texpect(scratch.firstChild.textContent).to.be.equal('2');\n\t\t\texpect(curProps).to.deep.equal({ foo: 'foo' });\n\t\t\texpect(curState).to.deep.equal({ value: 1 });\n\t\t\texpect(nextPropsArg).to.deep.equal({ foo: 'bar' });\n\t\t\texpect(nextStateArg).to.deep.equal({ value: 2 });\n\n\t\t\t// New state\n\t\t\t// state.value: 2 -> 3 in updateState, 3 -> 4 in gDSFP\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(scratch.firstChild.textContent).to.be.equal('4');\n\t\t\texpect(curProps).to.deep.equal({ foo: 'bar' });\n\t\t\texpect(curState).to.deep.equal({ value: 2 });\n\t\t\texpect(nextPropsArg).to.deep.equal({ foo: 'bar' });\n\t\t\texpect(nextStateArg).to.deep.equal({ value: 4 });\n\t\t});\n\n\t\tit('should update props reference when sCU returns false', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tlet updateState;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tupdateState = () => this.setState({});\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate(nextProps) {\n\t\t\t\t\tif (nextProps !== this.props) {\n\t\t\t\t\t\tspy();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo foo=\"foo\" />, scratch);\n\t\t\trender(<Foo foo=\"bar\" />, scratch);\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t});\n\n\t\tit('should update state reference when sCU returns false', () => {\n\t\t\tlet spy = vi.fn();\n\n\t\t\tlet updateState;\n\t\t\tclass Foo extends Component {\n\t\t\t\tconstructor() {\n\t\t\t\t\tsuper();\n\t\t\t\t\tthis.state = { foo: 1 };\n\t\t\t\t\tupdateState = () => this.setState({ foo: 2 });\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate(_, nextState) {\n\t\t\t\t\tif (nextState !== this.state) {\n\t\t\t\t\t\tspy(this.state, nextState);\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Foo />, scratch);\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(spy).toHaveBeenCalledWith({ foo: 1 }, { foo: 2 });\n\n\t\t\tupdateState();\n\t\t\trerender();\n\n\t\t\texpect(spy).toHaveBeenCalledWith({ foo: 2 }, { foo: 2 });\n\t\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\t});\n\n\t\t// issue #1864\n\t\tit('should update dom pointers correctly when returning an empty string', () => {\n\t\t\tfunction Child({ showMe, counter }) {\n\t\t\t\treturn showMe ? <div>Counter: {counter}</div> : '';\n\t\t\t}\n\n\t\t\tclass Parent extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Inner />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet updateChild = () => null;\n\t\t\tclass Inner extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { showMe: false };\n\t\t\t\t\tupdateChild = () => {\n\t\t\t\t\t\tthis.setState({ showMe: (display = !display) });\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Child showMe={this.state.showMe} counter={0} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet display = false;\n\t\t\tlet updateApp = () => null;\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tupdateApp = () => this.setState({});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t<Parent />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.textContent).to.equal('');\n\n\t\t\tupdateChild();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('Counter: 0');\n\n\t\t\tupdateApp();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('Counter: 0');\n\n\t\t\tupdateChild();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('');\n\n\t\t\tupdateApp();\n\t\t\trerender();\n\t\t\texpect(scratch.textContent).to.equal('');\n\t\t});\n\n\t\t// issue #1864 second case\n\t\tit('should update dom pointers correctly when returning a string', () => {\n\t\t\tfunction Child({ showMe, counter }) {\n\t\t\t\treturn showMe ? <div>Counter: {counter}</div> : 'foo';\n\t\t\t}\n\n\t\t\tclass Parent extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Inner />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet updateChild = () => null;\n\t\t\tclass Inner extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { showMe: false };\n\t\t\t\t\tupdateChild = () => {\n\t\t\t\t\t\tthis.setState({ showMe: (display = !display) });\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Child showMe={this.state.showMe} counter={0} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet display = false;\n\t\t\tlet updateApp = () => null;\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tupdateApp = () => this.setState({});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t\t<Parent />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.textContent).to.equal('foo');\n\n\t\t\tupdateChild();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('Counter: 0');\n\n\t\t\tupdateApp();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('Counter: 0');\n\n\t\t\tupdateChild();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('foo');\n\n\t\t\tupdateApp();\n\t\t\trerender();\n\t\t\texpect(scratch.textContent).to.equal('foo');\n\t\t});\n\n\t\tit('should correctly update nested children', () => {\n\t\t\tlet hideThree, incrementThree;\n\n\t\t\tclass One extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\trender(p) {\n\t\t\t\t\treturn p.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Two extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { hideMe: false };\n\t\t\t\t\thideThree = () => this.setState(s => ({ hideMe: !s.hideMe }));\n\t\t\t\t}\n\n\t\t\t\tshouldComponentUpdate(nextProps, nextState) {\n\t\t\t\t\treturn this.state.hideMe !== nextState.hideMe;\n\t\t\t\t}\n\n\t\t\t\trender(p, { hideMe }) {\n\t\t\t\t\treturn hideMe ? <Fragment /> : p.children;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclass Three extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { counter: 1 };\n\t\t\t\t\tincrementThree = () =>\n\t\t\t\t\t\tthis.setState(s => ({ counter: s.counter + 1 }));\n\t\t\t\t}\n\n\t\t\t\trender(p, { counter }) {\n\t\t\t\t\treturn <span>{counter}</span>;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(\n\t\t\t\t<One>\n\t\t\t\t\t<Two>\n\t\t\t\t\t\t<Three />\n\t\t\t\t\t</Two>\n\t\t\t\t</One>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(scratch.innerHTML).to.equal('<span>1</span>');\n\n\t\t\thideThree();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\t\thideThree();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<span>1</span>');\n\n\t\t\tincrementThree();\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<span>2</span>');\n\t\t});\n\n\t\t// issue #1864 third case\n\t\tit('should update dom pointers correctly without siblings', () => {\n\t\t\tfunction Child({ showMe, counter }) {\n\t\t\t\treturn showMe ? <div>Counter: {counter}</div> : 'foo';\n\t\t\t}\n\n\t\t\tclass Parent extends Component {\n\t\t\t\tshouldComponentUpdate() {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Inner />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet updateChild = () => null;\n\t\t\tclass Inner extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthis.state = { showMe: false };\n\t\t\t\t\tupdateChild = () => {\n\t\t\t\t\t\tthis.setState({ showMe: (display = !display) });\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <Child showMe={this.state.showMe} counter={0} />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet display = false;\n\t\t\tlet updateApp = () => null;\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tupdateApp = () => this.setState({});\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<Parent />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.textContent).to.equal('foo');\n\n\t\t\tupdateChild();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('Counter: 0');\n\n\t\t\tupdateApp();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('Counter: 0');\n\n\t\t\tupdateChild();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('foo');\n\n\t\t\tupdateApp();\n\t\t\trerender();\n\n\t\t\texpect(scratch.textContent).to.equal('foo');\n\t\t});\n\t});\n\n\tit('should correctly render when sCU component has null children', () => {\n\t\tclass App extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn [null, <div>Hello World!</div>, null];\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello World!</div>');\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello World!</div>');\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>Hello World!</div>');\n\t});\n\n\tit('should support nested update with strict-equal vnodes', () => {\n\t\tlet wrapperSetState, childSetState;\n\n\t\tclass Child extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { foo: 'baz' };\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tchildSetState = this.setState.bind(this);\n\t\t\t\treturn <p>{this.state.foo}</p>;\n\t\t\t}\n\t\t}\n\n\t\tclass Wrapper extends Component {\n\t\t\trender() {\n\t\t\t\twrapperSetState = this.setState.bind(this);\n\t\t\t\treturn this.props.children;\n\t\t\t}\n\t\t}\n\n\t\tconst App = () => (\n\t\t\t<Wrapper>\n\t\t\t\t<Child />\n\t\t\t</Wrapper>\n\t\t);\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<p>baz</p>');\n\n\t\twrapperSetState({ hi: 'world' });\n\t\tchildSetState({ foo: 'bar' });\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<p>bar</p>');\n\t});\n\n\tit('should reorder non-updating nested Fragment children', () => {\n\t\tconst rows = [\n\t\t\t{ id: '1', a: 5, b: 100 },\n\t\t\t{ id: '2', a: 50, b: 10 },\n\t\t\t{ id: '3', a: 25, b: 1000 }\n\t\t];\n\n\t\tfunction Cell({ id, a, b }) {\n\t\t\t// Return an array to really test out the reordering algorithm :)\n\t\t\treturn (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<div>id: {id}</div>\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>a: {a}</div>\n\t\t\t\t\t\t<div>b: {b}</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t</Fragment>\n\t\t\t);\n\t\t}\n\n\t\tclass Row extends Component {\n\t\t\tshouldComponentUpdate(nextProps) {\n\t\t\t\treturn nextProps.id !== this.props.id;\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn <Cell id={props.id} a={props.a} b={props.b} />;\n\t\t\t}\n\t\t}\n\n\t\tconst App = ({ sortBy }) => (\n\t\t\t<div>\n\t\t\t\t<table>\n\t\t\t\t\t{rows\n\t\t\t\t\t\t.sort((a, b) => (a[sortBy] > b[sortBy] ? -1 : 1))\n\t\t\t\t\t\t.map(row => (\n\t\t\t\t\t\t\t<Row key={row.id} id={row.id} a={row.a} b={row.b} />\n\t\t\t\t\t\t))}\n\t\t\t\t</table>\n\t\t\t</div>\n\t\t);\n\n\t\trender(<App sortBy=\"a\" />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div><table>${[\n\t\t\t\t'<div>id: 2</div><div>a: 50</div><div>b: 10</div>',\n\t\t\t\t'<div>id: 3</div><div>a: 25</div><div>b: 1000</div>',\n\t\t\t\t'<div>id: 1</div><div>a: 5</div><div>b: 100</div>'\n\t\t\t].join('')}</table></div>`\n\t\t);\n\n\t\tclearLog();\n\t\trender(<App sortBy=\"b\" />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div><table>${[\n\t\t\t\t'<div>id: 3</div><div>a: 25</div><div>b: 1000</div>',\n\t\t\t\t'<div>id: 1</div><div>a: 5</div><div>b: 100</div>',\n\t\t\t\t'<div>id: 2</div><div>a: 50</div><div>b: 10</div>'\n\t\t\t].join('')}</table></div>`\n\t\t);\n\t\t// TODO: these tests pass in isolation but not when all tests are running, figure out why logCall stops appending to log.\n\t\t// expectDomLogToBe([\n\t\t// \t'<table>id: 2a: 50b: 10id: 3a: 25b: 1000id: 1a: 5b: 100.insertBefore(<div>id: 3, <div>id: 2)',\n\t\t// \t'<table>id: 3id: 2a: 50b: 10a: 25b: 1000id: 1a: 5b: 100.insertBefore(<div>a: 25, <div>id: 2)',\n\t\t// \t'<table>id: 3a: 25id: 2a: 50b: 10b: 1000id: 1a: 5b: 100.insertBefore(<div>b: 1000, <div>id: 2)',\n\t\t// \t'<table>id: 3a: 25b: 1000id: 2a: 50b: 10id: 1a: 5b: 100.insertBefore(<div>id: 1, <div>id: 2)',\n\t\t// \t'<table>id: 3a: 25b: 1000id: 1id: 2a: 50b: 10a: 5b: 100.insertBefore(<div>a: 5, <div>id: 2)',\n\t\t// \t'<table>id: 3a: 25b: 1000id: 1a: 5id: 2a: 50b: 10b: 100.insertBefore(<div>b: 100, <div>id: 2)'\n\t\t// ]);\n\t});\n\n\tit('should correctly handle double state updates', () => {\n\t\tlet updateParent, updateChild;\n\t\tclass Parent extends Component {\n\t\t\tstate = { text: 'parent-old' };\n\n\t\t\tcomponentDidMount() {\n\t\t\t\tupdateParent = () => this.setState({ text: 'Parent-NEW' });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t{this.props.children} and {this.state.text}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass Child extends Component {\n\t\t\tstate = { text: 'child-old' };\n\n\t\t\tshouldComponentUpdate(nextProps, nextState) {\n\t\t\t\treturn this.state.text !== nextState.text;\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\tupdateChild = () => this.setState({ text: 'Child-NEW' });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <h1>{this.state.text}</h1>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Parent>\n\t\t\t\t<Child />\n\t\t\t</Parent>,\n\t\t\tscratch\n\t\t);\n\n\t\tupdateParent();\n\t\tupdateChild();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<h1>Child-NEW</h1> and Parent-NEW');\n\t});\n\n\tit('should maintain the order if memoised component initially rendered empty content', () => {\n\t\tlet showText, updateParent;\n\t\tclass Child extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = {\n\t\t\t\t\tshow: false\n\t\t\t\t};\n\t\t\t\tshowText = () => this.setState({ show: true });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tif (!this.state.show) return null;\n\n\t\t\t\treturn <div>Component</div>;\n\t\t\t}\n\t\t}\n\n\t\tclass Memoized extends Component {\n\t\t\tshouldComponentUpdate() {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <Child />;\n\t\t\t}\n\t\t}\n\t\tclass Parent extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tupdateParent = () => this.setState({});\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t<div>Before</div>\n\t\t\t\t\t\t<Memoized />\n\t\t\t\t\t\t<div>After</div>\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Parent />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(`<div>Before</div><div>After</div>`);\n\n\t\tupdateParent();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(`<div>Before</div><div>After</div>`);\n\n\t\tshowText();\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>Before</div><div>Component</div><div>After</div>`\n\t\t);\n\t});\n\n\tit('should not re-insert memoized items that keep their relative order after swap', () => {\n\t\tclass MemoizedItem extends Component {\n\t\t\tshouldComponentUpdate(nextProps) {\n\t\t\t\treturn nextProps.value !== this.props.value;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>{this.props.value}</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = ({ items }) => (\n\t\t\t<div>\n\t\t\t\t{items.map(value => (\n\t\t\t\t\t<MemoizedItem key={value} value={value} />\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\n\t\trender(<App items={[1, 2, 3, 4, 5, 6, 7]} />, scratch);\n\n\t\tfunction renderItemsAndAssert({ items, expectedLog }) {\n\t\t\tclearLog();\n\t\t\trender(<App items={items} />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t`<div>${items.map(value => `<div>${value}</div>`).join('')}</div>`\n\t\t\t);\n\t\t\texpect(getLog()).to.deep.equal(expectedLog);\n\t\t}\n\n\t\t// Swap 1 and 7\n\t\trenderItemsAndAssert({\n\t\t\titems: [7, 2, 3, 4, 5, 6, 1],\n\t\t\texpectedLog: [\n\t\t\t\t'<div>1234567.insertBefore(<div>7, <div>1)',\n\t\t\t\t'<div>7123456.appendChild(<div>1)'\n\t\t\t]\n\t\t});\n\n\t\t// Swap 2 and 6\n\t\trenderItemsAndAssert({\n\t\t\titems: [7, 6, 3, 4, 5, 2, 1],\n\t\t\texpectedLog: [\n\t\t\t\t'<div>7234561.insertBefore(<div>6, <div>2)',\n\t\t\t\t'<div>7623451.insertBefore(<div>2, <div>1)'\n\t\t\t]\n\t\t});\n\n\t\t// Swap 3 and 5\n\t\trenderItemsAndAssert({\n\t\t\titems: [7, 6, 5, 4, 3, 2, 1],\n\t\t\texpectedLog: [\n\t\t\t\t'<div>7634521.insertBefore(<div>5, <div>3)',\n\t\t\t\t'<div>7653421.insertBefore(<div>3, <div>2)'\n\t\t\t]\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/mathml.test.jsx",
    "content": "import { createElement, Component, render } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../_util/helpers';\n\nconst XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\nconst MATH_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n\ndescribe('mathml', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should render with the correct namespace URI', () => {\n\t\trender(<math />, scratch);\n\n\t\tlet namespace = scratch.querySelector('math').namespaceURI;\n\n\t\texpect(namespace).to.equal(MATH_NAMESPACE);\n\t});\n\n\tit('should render children with the correct namespace URI', () => {\n\t\trender(\n\t\t\t<math>\n\t\t\t\t<mrow />\n\t\t\t</math>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet namespace = scratch.querySelector('mrow').namespaceURI;\n\n\t\texpect(namespace).to.equal(MATH_NAMESPACE);\n\t});\n\n\tit('should inherit correct namespace URI from parent', () => {\n\t\tconst math = document.createElementNS(\n\t\t\tMATH_NAMESPACE,\n\t\t\t'math'\n\t\t);\n\t\tscratch.appendChild(math);\n\n\t\trender(<mrow />, scratch.firstChild);\n\n\t\tlet namespace = scratch.querySelector('mrow').namespaceURI;\n\t\texpect(namespace).to.equal(MATH_NAMESPACE);\n\t});\n\n\tit('should inherit correct namespace URI from parent upon updating', () => {\n\t\tsetupRerender();\n\n\t\tconst math = document.createElementNS(\n\t\t\tMATH_NAMESPACE,\n\t\t\t'math'\n\t\t);\n\t\tscratch.appendChild(math);\n\n\t\tclass App extends Component {\n\t\t\tstate = { show: true };\n\t\t\tcomponentDidMount() {\n\t\t\t\t// eslint-disable-next-line\n\t\t\t\tthis.setState({ show: false }, () => {\n\t\t\t\t\texpect(scratch.querySelector('mo').namespaceURI).to.equal(\n\t\t\t\t\t\tMATH_NAMESPACE\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.state.show ? <mi>1</mi> : <mo>2</mo>;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch.firstChild);\n\t});\n\n\tit('should transition from DOM to MathML and back', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<math>\n\t\t\t\t\t<msup>\n\t\t\t\t\t\t<mi>c</mi>\n\t\t\t\t\t\t<mn>2</mn>\n\t\t\t\t\t</msup>\n\t\t\t\t</math>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.firstChild).to.be.an('HTMLDivElement');\n\t\texpect(scratch.firstChild.firstChild).to.be.an('MathMLElement');\n\t});\n\n\tit('should support XHTML phrasing content within MathML token elements', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<math>\n\t\t\t\t\t<mrow>\n\t\t\t\t\t\t<mi><ins>123</ins></mi>\n\t\t\t\t\t</mrow>\n\t\t\t\t</math>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.querySelector('mi').namespaceURI).to.equal(\n\t\t\tMATH_NAMESPACE\n\t\t);\n\t\texpect(scratch.querySelector('ins').namespaceURI).to.equal(\n\t\t\tXHTML_NAMESPACE\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/browser/placeholders.test.jsx",
    "content": "import { createElement, Component, render, createRef, Fragment } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { logCall, clearLog, getLog } from '../_util/logCall';\nimport { div } from '../_util/dom';\nimport { vi } from 'vitest';\n\ndescribe('null placeholders', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\t/** @type {() => void} */\n\tlet rerender;\n\n\t/** @type {string[]} */\n\tlet ops;\n\n\tfunction createNullable(name) {\n\t\treturn function Nullable(props) {\n\t\t\treturn props.show ? name : null;\n\t\t};\n\t}\n\n\t/**\n\t * @param {string} name\n\t * @returns {[import('preact').ComponentClass, import('preact').RefObject<{ toggle(): void }>]}\n\t */\n\tfunction createStatefulNullable(name) {\n\t\tlet ref = createRef();\n\t\tclass Nullable extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: props.initialShow || true };\n\t\t\t\tref.current = this;\n\t\t\t}\n\t\t\ttoggle() {\n\t\t\t\tthis.setState({ show: !this.state.show });\n\t\t\t}\n\t\t\tcomponentDidUpdate() {\n\t\t\t\tops.push(`Update ${name}`);\n\t\t\t}\n\t\t\tcomponentDidMount() {\n\t\t\t\tops.push(`Mount ${name}`);\n\t\t\t}\n\t\t\tcomponentWillUnmount() {\n\t\t\t\tops.push(`Unmount ${name}`);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.state.show ? <div>{name}</div> : null;\n\t\t\t}\n\t\t}\n\n\t\treturn [Nullable, ref];\n\t}\n\n\tlet resetAppendChild;\n\tlet resetInsertBefore;\n\tlet resetRemoveText;\n\tlet resetRemove;\n\n\tbeforeAll(() => {\n\t\tresetAppendChild = logCall(Element.prototype, 'appendChild');\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetRemove = logCall(Element.prototype, 'remove');\n\t\tresetRemoveText = logCall(Text.prototype, 'remove');\n\t});\n\n\tafterAll(() => {\n\t\tresetAppendChild();\n\t\tresetInsertBefore();\n\t\tresetRemoveText();\n\t\tresetRemove();\n\t});\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t\tops = [];\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\tclearLog();\n\t});\n\n\tit('should treat undefined as a hole', () => {\n\t\tlet Bar = () => <div>bar</div>;\n\n\t\tfunction Foo(props) {\n\t\t\tlet sibling;\n\t\t\tif (props.condition) {\n\t\t\t\tsibling = <Bar />;\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<div>Hello</div>\n\t\t\t\t\t{sibling}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo condition />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Hello</div><div>bar</div></div>'\n\t\t);\n\t\tclearLog();\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>Hello</div></div>');\n\t\texpect(getLog()).to.deep.equal(['<div>bar.remove()']);\n\t});\n\n\tit('should preserve state of Components when using null or booleans as placeholders', () => {\n\t\t// Must be the same class for all children in <App /> for this test to be valid\n\t\tclass Stateful extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tif (typeof props.ref === 'function') {\n\t\t\t\t\tprops.ref(this);\n\t\t\t\t} else if (props.ref) {\n\t\t\t\t\tprops.ref.current = this;\n\t\t\t\t}\n\t\t\t\tthis.state = { count: 0 };\n\t\t\t}\n\t\t\tincrement() {\n\t\t\t\tthis.setState({ count: this.state.count + 1 });\n\t\t\t}\n\t\t\tcomponentDidUpdate() {\n\t\t\t\tops.push(`Update ${this.props.name}`);\n\t\t\t}\n\t\t\tcomponentDidMount() {\n\t\t\t\tops.push(`Mount ${this.props.name}`);\n\t\t\t}\n\t\t\tcomponentWillUnmount() {\n\t\t\t\tops.push(`Unmount ${this.props.name}`);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.props.name}: {this.state.count}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst s1ref = createRef();\n\t\tconst s2ref = createRef();\n\t\tconst s3ref = createRef();\n\n\t\tfunction App({ first = null, second = false }) {\n\t\t\treturn [first, second, <Stateful name=\"third\" ref={s3ref} />];\n\t\t}\n\n\t\t// Mount third stateful - Initial render\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>third: 0</div>');\n\t\texpect(ops).to.deep.equal(['Mount third'], 'mount third');\n\n\t\t// Update third stateful\n\t\tops = [];\n\t\ts3ref.current.increment();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div>third: 1</div>');\n\t\texpect(ops).to.deep.equal(['Update third'], 'update third');\n\n\t\t// Mount first stateful\n\t\tops = [];\n\t\trender(<App first={<Stateful name=\"first\" ref={s1ref} />} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>first: 0</div><div>third: 1</div>'\n\t\t);\n\t\texpect(ops).to.deep.equal(['Mount first', 'Update third'], 'mount first');\n\n\t\t// Update first stateful\n\t\tops = [];\n\t\ts1ref.current.increment();\n\t\ts3ref.current.increment();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>first: 1</div><div>third: 2</div>'\n\t\t);\n\t\texpect(ops).to.deep.equal(['Update first', 'Update third'], 'update first');\n\n\t\t// Mount second stateful\n\t\tops = [];\n\t\trender(\n\t\t\t<App\n\t\t\t\tfirst={<Stateful name=\"first\" ref={s1ref} />}\n\t\t\t\tsecond={<Stateful name=\"second\" ref={s2ref} />}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>first: 1</div><div>second: 0</div><div>third: 2</div>'\n\t\t);\n\t\texpect(ops).to.deep.equal(\n\t\t\t['Update first', 'Mount second', 'Update third'],\n\t\t\t'mount second'\n\t\t);\n\n\t\t// Update second stateful\n\t\tops = [];\n\t\ts1ref.current.increment();\n\t\ts2ref.current.increment();\n\t\ts3ref.current.increment();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div>first: 2</div><div>second: 1</div><div>third: 3</div>'\n\t\t);\n\t\texpect(ops).to.deep.equal(\n\t\t\t['Update first', 'Update second', 'Update third'],\n\t\t\t'update second'\n\t\t);\n\t});\n\n\tit('should efficiently replace self-updating null placeholders', () => {\n\t\t// These Nullable components replace themselves with null without the parent re-rendering\n\t\tconst [Nullable, ref] = createStatefulNullable('Nullable');\n\t\tconst [Nullable2, ref2] = createStatefulNullable('Nullable2');\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<div>1</div>\n\t\t\t\t\t<Nullable />\n\t\t\t\t\t<div>3</div>\n\t\t\t\t\t<Nullable2 />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(1), div('Nullable'), div(3), div('Nullable2')])\n\t\t);\n\n\t\tclearLog();\n\t\tref2.current.toggle();\n\t\tref.current.toggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(div([div(1), div(3)]));\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>Nullable2.remove()',\n\t\t\t'<div>Nullable.remove()'\n\t\t]);\n\n\t\tclearLog();\n\t\tref2.current.toggle();\n\t\tref.current.toggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div(1), div('Nullable'), div(3), div('Nullable2')])\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>13.appendChild(<div>Nullable2)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>13Nullable2.insertBefore(<div>Nullable, <div>3)'\n\t\t]);\n\t});\n\n\t// See preactjs/preact#2350\n\tit('should efficiently replace null placeholders in parent rerenders (#2350)', () => {\n\t\t// This Nullable only changes when it's parent rerenders\n\t\tconst Nullable1 = createNullable('Nullable 1');\n\t\tconst Nullable2 = createNullable('Nullable 2');\n\n\t\t/** @type {() => void} */\n\t\tlet toggle;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: false };\n\t\t\t\ttoggle = () => this.setState({ show: !this.state.show });\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div>{this.state.show.toString()}</div>\n\t\t\t\t\t\t<Nullable1 show={this.state.show} />\n\t\t\t\t\t\t<div>the middle</div>\n\t\t\t\t\t\t<Nullable2 show={this.state.show} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(div([div('false'), div('the middle')]));\n\n\t\tclearLog();\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\tdiv([div('true'), 'Nullable 1', div('the middle'), 'Nullable 2'])\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>truethe middle.insertBefore(#text, <div>the middle)',\n\t\t\t'<div>trueNullable 1the middle.appendChild(#text)'\n\t\t]);\n\n\t\tclearLog();\n\t\ttoggle();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(div([div('false'), div('the middle')]));\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'#text.remove()',\n\t\t\t// '<div>falsethe middleNullable 2.appendChild(<div>the middle)',\n\t\t\t'#text.remove()'\n\t\t]);\n\t});\n\n\tit('when set through the children prop (#4074)', () => {\n\t\t/** @type {(state: { value: boolean }) => void} */\n\t\tlet setState;\n\t\tconst Iframe = () => {\n\t\t\t// Using a div here to make debugging tests in devtools a little less\n\t\t\t// noisy. The dom ops still assert that the iframe isn't moved.\n\t\t\t//\n\t\t\t// return <iframe src=\"https://codesandbox.io/s/runtime-silence-no4zx\" />;\n\t\t\treturn <div>Iframe</div>;\n\t\t};\n\n\t\tconst Test2 = () => <div>Test2</div>;\n\t\tconst Test3 = () => <div>Test3</div>;\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: true };\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Test2 />\n\t\t\t\t\t\t{state.value && <Test3 />}\n\t\t\t\t\t\t{props.children}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<App>\n\t\t\t\t<Iframe />\n\t\t\t</App>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test2</div><div>Test3</div><div>Iframe</div></div>'\n\t\t);\n\t\tclearLog();\n\t\tsetState({ value: false });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test2</div><div>Iframe</div></div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal(['<div>Test3.remove()']);\n\t});\n\n\tit('when set through the children prop when removing a Fragment with multiple DOM children (#4074)', () => {\n\t\t/** @type {(state: { value: boolean }) => void} */\n\t\tlet setState;\n\t\tconst Iframe = () => {\n\t\t\t// Using a div here to make debugging tests in devtools a little less\n\t\t\t// noisy. The dom ops still assert that the iframe isn't moved.\n\t\t\t//\n\t\t\t// return <iframe src=\"https://codesandbox.io/s/runtime-silence-no4zx\" />;\n\t\t\treturn <div>Iframe</div>;\n\t\t};\n\n\t\tconst Test2 = () => <div>Test2</div>;\n\t\tconst Test34 = () => (\n\t\t\t<Fragment>\n\t\t\t\t<div>Test3</div>\n\t\t\t\t<div>Test4</div>\n\t\t\t</Fragment>\n\t\t);\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: true };\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Test2 />\n\t\t\t\t\t\t{state.value && <Test34 />}\n\t\t\t\t\t\t{props.children}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<App>\n\t\t\t\t<Iframe />\n\t\t\t</App>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test2</div><div>Test3</div><div>Test4</div><div>Iframe</div></div>'\n\t\t);\n\t\tclearLog();\n\t\tsetState({ value: false });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test2</div><div>Iframe</div></div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>Test3.remove()',\n\t\t\t'<div>Test4.remove()'\n\t\t]);\n\t});\n\n\tit('should only call unmount once when removing placeholders (#4104)', () => {\n\t\t/** @type {(state: { value: boolean }) => void} */\n\t\tlet setState;\n\t\tconst Iframe = () => {\n\t\t\t// Using a div here to make debugging tests in devtools a little less\n\t\t\t// noisy. The dom ops still assert that the iframe isn't moved.\n\t\t\t//\n\t\t\t// return <iframe src=\"https://codesandbox.io/s/runtime-silence-no4zx\" />;\n\t\t\treturn <div>Iframe</div>;\n\t\t};\n\n\t\tconst Test2 = () => <div>Test2</div>;\n\n\t\tconst ref = vi.fn();\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: true };\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Test2 />\n\t\t\t\t\t\t{state.value && <div ref={ref}>Test3</div>}\n\t\t\t\t\t\t{props.children}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<App>\n\t\t\t\t<Iframe />\n\t\t\t</App>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test2</div><div>Test3</div><div>Iframe</div></div>'\n\t\t);\n\t\texpect(ref).toHaveBeenCalledTimes(1);\n\n\t\tref.mockClear();\n\t\tclearLog();\n\t\tsetState({ value: false });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test2</div><div>Iframe</div></div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal(['<div>Test3.remove()']);\n\t\texpect(ref).toHaveBeenCalledTimes(1);\n\t});\n});\n"
  },
  {
    "path": "test/browser/refs.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component, createRef, Fragment } from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { vi } from 'vitest';\n\n// gives call count and argument errors names (otherwise vitest just uses \"spy\"):\nlet spy = (name, ...args) => {\n\tlet spy = vi.fn(...args);\n\tspy.displayName = `spy('${name}')`;\n\treturn spy;\n};\n\ndescribe('refs', () => {\n\tlet scratch;\n\tlet rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should invoke refs in render()', () => {\n\t\tlet ref = spy('ref');\n\t\trender(<div ref={ref} />, scratch);\n\t\texpect(ref).toHaveBeenCalledOnce();\n\t\texpect(ref).toHaveBeenCalledWith(scratch.firstChild);\n\t});\n\n\tit('should not call stale refs', () => {\n\t\tlet ref = spy('ref');\n\t\tlet ref2 = spy('ref2');\n\t\tlet bool = true;\n\t\tconst App = () => <div ref={bool ? ref : ref2} />;\n\n\t\trender(<App />, scratch);\n\t\texpect(ref).toHaveBeenCalledOnce();\n\t\texpect(ref).toHaveBeenCalledWith(scratch.firstChild);\n\n\t\tbool = false;\n\t\trender(<App />, scratch);\n\t\texpect(ref).toHaveBeenCalledTimes(2);\n\t\texpect(ref).toHaveBeenCalledWith(null);\n\t\texpect(ref2).toHaveBeenCalledOnce();\n\t\texpect(ref2).toHaveBeenCalledWith(scratch.firstChild);\n\t});\n\n\tit('should support createRef', () => {\n\t\tconst r = createRef();\n\t\texpect(r.current).to.equal(null);\n\n\t\trender(<div ref={r} />, scratch);\n\t\texpect(r.current).to.equalNode(scratch.firstChild);\n\t});\n\n\tit('should invoke refs in Component.render()', () => {\n\t\tlet outer = spy('outer'),\n\t\t\tinner = spy('inner');\n\t\tclass Foo extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div ref={outer}>\n\t\t\t\t\t\t<span ref={inner} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\trender(<Foo />, scratch);\n\n\t\texpect(outer).toHaveBeenCalledWith(scratch.firstChild);\n\t\texpect(inner).toHaveBeenCalledWith(scratch.firstChild.firstChild);\n\t});\n\n\tit('should pass component refs in props', () => {\n\t\tlet ref = spy('ref'),\n\t\t\tinstance;\n\t\tclass Foo extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t}\n\t\t\trender(props) {\n\t\t\t\tinstance = props.ref;\n\t\t\t\treturn <div />;\n\t\t\t}\n\t\t}\n\t\trender(<Foo ref={ref} />, scratch);\n\n\t\texpect(ref).to.equal(instance);\n\t});\n\n\tit('should have a consistent order', () => {\n\t\tconst events = [];\n\t\tconst App = () => (\n\t\t\t<div ref={r => events.push('called with ' + (r && r.tagName))}>\n\t\t\t\t<h1 ref={r => events.push('called with ' + (r && r.tagName))}>hi</h1>\n\t\t\t</div>\n\t\t);\n\n\t\trender(<App />, scratch);\n\t\trender(<App />, scratch);\n\t\texpect(events.length).to.equal(6);\n\t\texpect(events).to.deep.equal([\n\t\t\t'called with H1',\n\t\t\t'called with DIV',\n\t\t\t'called with null',\n\t\t\t'called with null',\n\t\t\t'called with H1',\n\t\t\t'called with DIV'\n\t\t]);\n\t});\n\n\t// Test for #232\n\tit('should only null refs after unmount', () => {\n\t\tlet outer, inner;\n\n\t\tclass TestUnmount extends Component {\n\t\t\tcomponentWillUnmount() {\n\t\t\t\texpect(this).to.have.property('outer', outer);\n\t\t\t\texpect(this).to.have.property('inner', inner);\n\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\texpect(this).to.have.property('outer', null);\n\t\t\t\t\texpect(this).to.have.property('inner', null);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div id=\"outer\" ref={c => (this.outer = c)}>\n\t\t\t\t\t\t<div id=\"inner\" ref={c => (this.inner = c)} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(TestUnmount.prototype, 'componentWillUnmount');\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<TestUnmount />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\touter = scratch.querySelector('#outer');\n\t\tinner = scratch.querySelector('#inner');\n\n\t\texpect(TestUnmount.prototype.componentWillUnmount).not.toHaveBeenCalled();\n\n\t\trender(<div />, scratch);\n\t\texpect(TestUnmount.prototype.componentWillUnmount).toHaveBeenCalledOnce();\n\t});\n\n\tit('should null and re-invoke refs when swapping component root element type', () => {\n\t\t/** @type {Child} */\n\t\tlet inst;\n\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Child />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tclass Child extends Component {\n\t\t\tconstructor(props, context) {\n\t\t\t\tsuper(props, context);\n\t\t\t\tthis.state = { show: false };\n\t\t\t\tinst = this;\n\t\t\t}\n\t\t\thandleMount() {}\n\t\t\trender(_, { show }) {\n\t\t\t\tif (!show) return <div id=\"div\" ref={this.handleMount} />;\n\t\t\t\treturn (\n\t\t\t\t\t<span id=\"span\" ref={this.handleMount}>\n\t\t\t\t\t\tsome test content\n\t\t\t\t\t</span>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tvi.spyOn(Child.prototype, 'handleMount');\n\n\t\trender(<App />, scratch);\n\t\texpect(inst.handleMount).toHaveBeenCalledOnce();\n\t\texpect(inst.handleMount).toHaveBeenCalledWith(\n\t\t\tscratch.querySelector('#div')\n\t\t);\n\t\tinst.handleMount.mockClear();\n\n\t\tinst.setState({ show: true });\n\t\trerender();\n\t\texpect(inst.handleMount).toHaveBeenCalledTimes(2);\n\t\texpect(inst.handleMount).toHaveBeenNthCalledWith(1, null);\n\t\texpect(inst.handleMount).toHaveBeenNthCalledWith(\n\t\t\t2,\n\t\t\tscratch.querySelector('#span')\n\t\t);\n\t\tinst.handleMount.mockClear();\n\n\t\tinst.setState({ show: false });\n\t\trerender();\n\t\texpect(inst.handleMount).toHaveBeenCalledTimes(2);\n\t\texpect(inst.handleMount).toHaveBeenNthCalledWith(1, null);\n\t\texpect(inst.handleMount).toHaveBeenNthCalledWith(\n\t\t\t2,\n\t\t\tscratch.querySelector('#div')\n\t\t);\n\t});\n\n\t// Test for #1177\n\tit('should call ref after children are rendered', async () => {\n\t\t/** @type {HTMLInputElement} */\n\t\tlet input;\n\t\tlet res;\n\t\tfunction autoFocus(el) {\n\t\t\tif (el) {\n\t\t\t\tinput = el;\n\n\t\t\t\t// Chrome bug: It will somehow drop the focus event if it fires too soon.\n\t\t\t\t// See https://stackoverflow.com/questions/17384464/\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tel.focus();\n\t\t\t\t\tres();\n\t\t\t\t}, 1);\n\t\t\t}\n\t\t}\n\n\t\trender(<input type=\"text\" ref={autoFocus} value=\"foo\" />, scratch);\n\t\texpect(input.value).to.equal('foo');\n\n\t\treturn new Promise(resolve => {\n\t\t\tres = resolve;\n\t\t});\n\t});\n\n\tit('should correctly set nested child refs', () => {\n\t\tconst ref = createRef();\n\t\tconst App = ({ open }) =>\n\t\t\topen ? (\n\t\t\t\t<div class=\"open\" key=\"open\">\n\t\t\t\t\t<div ref={ref} />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div class=\"closes\" key=\"closed\">\n\t\t\t\t\t<div ref={ref} />\n\t\t\t\t</div>\n\t\t\t);\n\n\t\trender(<App />, scratch);\n\t\texpect(ref.current).to.not.be.null;\n\n\t\trender(<App open />, scratch);\n\t\texpect(ref.current).to.not.be.null;\n\t});\n\n\tit('should correctly call child refs for un-keyed children on re-render', () => {\n\t\tlet el = null;\n\t\tlet ref = e => {\n\t\t\tel = e;\n\t\t};\n\n\t\tclass App extends Component {\n\t\t\trender({ headerVisible }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{headerVisible && <div>foo</div>}\n\t\t\t\t\t\t<div ref={ref}>bar</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App headerVisible />, scratch);\n\t\texpect(el).to.not.be.equal(null);\n\n\t\trender(<App />, scratch);\n\t\texpect(el).to.not.be.equal(null);\n\t});\n\n\tit('should not remove refs for memoized components keyed', () => {\n\t\tconst ref = createRef();\n\t\tconst element = <div ref={ref}>hey</div>;\n\t\tfunction App(props) {\n\t\t\treturn <div key={props.count}>{element}</div>;\n\t\t}\n\n\t\trender(<App count={0} />, scratch);\n\t\texpect(ref.current).to.equal(scratch.firstChild.firstChild);\n\t\trender(<App count={1} />, scratch);\n\t\texpect(ref.current).to.equal(scratch.firstChild.firstChild);\n\t\trender(<App count={2} />, scratch);\n\t\texpect(ref.current).to.equal(scratch.firstChild.firstChild);\n\t});\n\n\tit('should not remove refs for memoized components unkeyed', () => {\n\t\tconst ref = createRef();\n\t\tconst element = <div ref={ref}>hey</div>;\n\t\tfunction App(props) {\n\t\t\treturn <div>{element}</div>;\n\t\t}\n\n\t\trender(<App count={0} />, scratch);\n\t\texpect(ref.current).to.equal(scratch.firstChild.firstChild);\n\t\trender(<App count={1} />, scratch);\n\t\texpect(ref.current).to.equal(scratch.firstChild.firstChild);\n\t\trender(<App count={2} />, scratch);\n\t\texpect(ref.current).to.equal(scratch.firstChild.firstChild);\n\t});\n\n\tit('should properly call null for memoized components keyed', () => {\n\t\tlet calls = [];\n\t\tconst element = <div ref={x => calls.push(x)}>hey</div>;\n\t\tfunction App(props) {\n\t\t\treturn <div key={props.count}>{element}</div>;\n\t\t}\n\n\t\trender(<App count={0} />, scratch);\n\t\texpect(calls).to.deep.equal([scratch.firstChild.firstChild]);\n\t\tcalls = [];\n\n\t\trender(<App count={1} />, scratch);\n\t\texpect(calls).to.deep.equal([null, scratch.firstChild.firstChild]);\n\t\tcalls = [];\n\n\t\trender(<App count={2} />, scratch);\n\t\texpect(calls).to.deep.equal([null, scratch.firstChild.firstChild]);\n\t});\n\n\tit('should properly call null for memoized components unkeyed', () => {\n\t\tconst calls = [];\n\t\tconst element = <div ref={x => calls.push(x)}>hey</div>;\n\t\tfunction App(props) {\n\t\t\treturn <div>{element}</div>;\n\t\t}\n\n\t\trender(<App count={0} />, scratch);\n\t\trender(<App count={1} />, scratch);\n\t\trender(<App count={2} />, scratch);\n\t\texpect(calls.length).to.equal(1);\n\t\texpect(calls[0]).to.equal(scratch.firstChild.firstChild);\n\t});\n\n\t// Test for #4049\n\tit('should first clean-up refs and after apply them', () => {\n\t\tlet calls = [];\n\t\t/** @type {() => void} */\n\t\tlet set;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = {\n\t\t\t\t\tphase: 1\n\t\t\t\t};\n\t\t\t\tset = () => this.setState({ phase: 2 });\n\t\t\t}\n\n\t\t\trender(props, { phase }) {\n\t\t\t\treturn (\n\t\t\t\t\t<Fragment>\n\t\t\t\t\t\t{phase === 1 ? (\n\t\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tref={r =>\n\t\t\t\t\t\t\t\t\t\tr\n\t\t\t\t\t\t\t\t\t\t\t? calls.push('adding ref to two')\n\t\t\t\t\t\t\t\t\t\t\t: calls.push('removing ref from two')\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tElement two\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tref={r =>\n\t\t\t\t\t\t\t\t\t\tr\n\t\t\t\t\t\t\t\t\t\t\t? calls.push('adding ref to three')\n\t\t\t\t\t\t\t\t\t\t\t: calls.push('removing ref from three')\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tElement three\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : phase === 2 ? (\n\t\t\t\t\t\t\t<div class=\"outer\">\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tref={r =>\n\t\t\t\t\t\t\t\t\t\tr\n\t\t\t\t\t\t\t\t\t\t\t? calls.push('adding ref to one')\n\t\t\t\t\t\t\t\t\t\t\t: calls.push('removing ref from one')\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tElement one\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t<div class=\"wrapper\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tref={r =>\n\t\t\t\t\t\t\t\t\t\t\tr\n\t\t\t\t\t\t\t\t\t\t\t\t? calls.push('adding ref to two')\n\t\t\t\t\t\t\t\t\t\t\t\t: calls.push('removing ref from two')\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tElement two\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tref={r =>\n\t\t\t\t\t\t\t\t\t\t\tr\n\t\t\t\t\t\t\t\t\t\t\t\t? calls.push('adding ref to three')\n\t\t\t\t\t\t\t\t\t\t\t\t: calls.push('removing ref from three')\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tElement three\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</Fragment>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(calls).to.deep.equal(['adding ref to two', 'adding ref to three']);\n\t\tcalls = [];\n\n\t\tset();\n\t\trerender();\n\t\texpect(calls).to.deep.equal([\n\t\t\t'removing ref from two',\n\t\t\t'adding ref to one',\n\t\t\t'adding ref to two',\n\t\t\t'adding ref to three'\n\t\t]);\n\t});\n\n\tit('should bind refs before componentDidMount', () => {\n\t\t/** @type {import('preact').RefObject<HTMLSpanElement>[]} */\n\t\tconst refs = [];\n\n\t\tclass Parent extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\t// Child refs should be set\n\t\t\t\texpect(refs.length).to.equal(2);\n\t\t\t\texpect(refs[0].current.tagName).to.equal('SPAN');\n\t\t\t\texpect(refs[1].current.tagName).to.equal('SPAN');\n\t\t\t}\n\n\t\t\trender(props) {\n\t\t\t\treturn props.children;\n\t\t\t}\n\t\t}\n\n\t\tclass Child extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\n\t\t\t\tthis.ref = createRef();\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\t// SPAN refs should be set\n\t\t\t\texpect(this.ref.current.tagName).to.equal('SPAN');\n\t\t\t\texpect(document.body.contains(this.ref.current)).to.equal(true);\n\t\t\t\trefs.push(this.ref);\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <span ref={this.ref}>Hello</span>;\n\t\t\t}\n\t\t}\n\n\t\trender(\n\t\t\t<Parent>\n\t\t\t\t<Child />\n\t\t\t\t<Child />\n\t\t\t</Parent>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.equal('<span>Hello</span><span>Hello</span>');\n\t\texpect(refs[0].current).to.equalNode(scratch.firstChild);\n\t\texpect(refs[1].current).to.equalNode(scratch.lastChild);\n\t});\n\n\tit('should call refs after element is added to document on initial mount', () => {\n\t\tconst verifyRef = name => el =>\n\t\t\texpect(document.body.contains(el), name).to.equal(true);\n\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<div ref={verifyRef('div tag')}>\n\t\t\t\t\t<p ref={verifyRef('p tag')}>Hello</p>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t});\n\n\tit('should call refs after element is added to document on update', () => {\n\t\tconst verifyRef = name => el =>\n\t\t\texpect(document.body.contains(el), name).to.equal(true);\n\n\t\tfunction App({ show = false }) {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t{show && (\n\t\t\t\t\t\t<p ref={verifyRef('p tag')}>\n\t\t\t\t\t\t\t<span ref={verifyRef('inner span')}>Hello</span>\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\trender(<App show />, scratch);\n\t});\n\n\tit('should call ref cleanup on unmount', () => {\n\t\tconst cleanup = vi.fn();\n\t\tconst ref = vi.fn(() => cleanup);\n\n\t\tfunction App({ show = false }) {\n\t\t\treturn <div>{show && <p ref={ref}>hello</p>}</div>;\n\t\t}\n\n\t\trender(<App show />, scratch);\n\t\trender(<App />, scratch);\n\n\t\texpect(cleanup).toHaveBeenCalledOnce();\n\n\t\t// Ref should not be called with `null` when cleanup is present\n\t\texpect(ref).toHaveBeenCalledOnce();\n\t\texpect(ref).not.toHaveBeenCalledWith(null);\n\t});\n\n\tit('should call ref cleanup when ref changes', () => {\n\t\tconst cleanup = vi.fn();\n\n\t\tfunction App({ show = false, count = 0 }) {\n\t\t\treturn <div>{show && <p ref={() => cleanup}>hello {count}</p>}</div>;\n\t\t}\n\n\t\trender(<App show />, scratch);\n\t\trender(<App show count={1} />, scratch);\n\n\t\t// Cleanup should be invoked whenever ref function changes\n\t\texpect(cleanup).toHaveBeenCalledOnce();\n\t});\n});\n"
  },
  {
    "path": "test/browser/render.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component, options, Fragment } from 'preact';\nimport {\n\tsetupScratch,\n\tteardown,\n\tgetMixedArray,\n\tmixedArrayHTML,\n\tserializeHtml,\n\tsupportsDataList,\n\tsortAttributes,\n\tspyOnElementAttributes,\n\tcreateEvent\n} from '../_util/helpers';\nimport { clearLog, getLog, logCall } from '../_util/logCall';\nimport { useState } from 'preact/hooks';\nimport { expect, vi } from 'vitest';\n\nfunction getAttributes(node) {\n\tlet attrs = {};\n\tfor (let i = node.attributes.length; i--; ) {\n\t\tattrs[node.attributes[i].name] = node.attributes[i].value;\n\t}\n\treturn attrs;\n}\n\ndescribe('render()', () => {\n\tlet scratch, rerender;\n\n\tlet resetAppendChild;\n\tlet resetInsertBefore;\n\tlet resetRemoveText;\n\tlet resetRemove;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tbeforeAll(() => {\n\t\tresetAppendChild = logCall(Element.prototype, 'appendChild');\n\t\tresetInsertBefore = logCall(Element.prototype, 'insertBefore');\n\t\tresetRemoveText = logCall(Text.prototype, 'remove');\n\t\tresetRemove = logCall(Element.prototype, 'remove');\n\t});\n\n\tafterAll(() => {\n\t\tresetAppendChild();\n\t\tresetInsertBefore();\n\t\tresetRemoveText();\n\t\tresetRemove();\n\t});\n\n\tit('should rerender when value from \"\" to 0', () => {\n\t\trender('', scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\n\t\trender(0, scratch);\n\t\texpect(scratch.innerHTML).to.equal('0');\n\t});\n\n\tit('should render an empty text node given an empty string', () => {\n\t\trender('', scratch);\n\t\tlet c = scratch.childNodes;\n\t\texpect(c).to.have.length(1);\n\t\texpect(c[0].data).to.equal('');\n\t\texpect(c[0].nodeName).to.equal('#text');\n\t});\n\n\tit('should allow node type change with content', () => {\n\t\trender(<span>Bad</span>, scratch);\n\t\trender(<div>Good</div>, scratch);\n\t\texpect(scratch.innerHTML).to.eql(`<div>Good</div>`);\n\t});\n\n\tit('should render % width and height on img correctly', () => {\n\t\trender(<img width=\"100%\" height=\"100%\" />, scratch);\n\t\texpect(scratch.innerHTML).to.eql(`<img width=\"100%\" height=\"100%\">`);\n\t});\n\n\tit('should render px width and height on img correctly', () => {\n\t\trender(<img width=\"100px\" height=\"100px\" />, scratch);\n\t\texpect(scratch.innerHTML).to.eql(`<img width=\"100px\" height=\"100px\">`);\n\t});\n\n\tit('should support the <template> tag', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<template>\n\t\t\t\t\t<h1>it works</h1>\n\t\t\t\t</template>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tconst clone = scratch.firstChild.content.cloneNode(true);\n\t\texpect(clone.firstChild.outerHTML).to.eql('<h1>it works</h1>');\n\t});\n\n\tit('should render function components with an undefined prototype', () => {\n\t\tconst Foo = () => <div>foo</div>;\n\t\tFoo.prototype = undefined;\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>foo</div>');\n\t});\n\n\tit('should not render when detecting JSON-injection', () => {\n\t\tconst vnode = JSON.parse(\n\t\t\t'{\"type\":\"span\",\"props\":{ \"children\": \"Malicious\"}, \"__v\": 1, \"constructor\": null}'\n\t\t);\n\t\trender(vnode, scratch);\n\t\texpect(scratch.firstChild).to.be.null;\n\t});\n\n\tit('should create empty nodes (<* />)', () => {\n\t\trender(<div />, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.childNodes[0].nodeName).to.equal('DIV');\n\n\t\tscratch.parentNode.removeChild(scratch);\n\t\tscratch = document.createElement('div');\n\t\t(document.body || document.documentElement).appendChild(scratch);\n\n\t\trender(<span />, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.childNodes[0].nodeName).to.equal('SPAN');\n\t});\n\n\tit('should support custom tag names', () => {\n\t\trender(<foo />, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.firstChild).to.have.property('nodeName', 'FOO');\n\n\t\tscratch.parentNode.removeChild(scratch);\n\t\tscratch = document.createElement('div');\n\t\t(document.body || document.documentElement).appendChild(scratch);\n\n\t\trender(<x-bar />, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.firstChild).to.have.property('nodeName', 'X-BAR');\n\t});\n\n\tit('should support the translate attribute w/ false as a boolean', () => {\n\t\trender(<b translate={false}>Bold</b>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<b translate=\"no\">Bold</b>');\n\t});\n\n\tit('should support the translate attribute w/ true as a boolean', () => {\n\t\trender(<b translate>Bold</b>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<b translate=\"yes\">Bold</b>');\n\t});\n\n\tit('should support the form attribute', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<form id=\"myform\" />\n\t\t\t\t<button form=\"myform\">test</button>\n\t\t\t\t<input form=\"myform\" />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tconst div = scratch.childNodes[0];\n\t\tconst form = div.childNodes[0];\n\t\tconst button = div.childNodes[1];\n\t\tconst input = div.childNodes[2];\n\n\t\texpect(button).to.have.property('form', form);\n\t\texpect(input).to.have.property('form', form);\n\t});\n\n\tit('should allow VNode reuse', () => {\n\t\tlet reused = <div class=\"reuse\">Hello World!</div>;\n\t\trender(\n\t\t\t<div>\n\t\t\t\t{reused}\n\t\t\t\t<hr />\n\t\t\t\t{reused}\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\texpect(serializeHtml(scratch)).to.eql(\n\t\t\t`<div><div class=\"reuse\">Hello World!</div><hr><div class=\"reuse\">Hello World!</div></div>`\n\t\t);\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<hr />\n\t\t\t\t{reused}\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\texpect(serializeHtml(scratch)).to.eql(\n\t\t\t`<div><hr><div class=\"reuse\">Hello World!</div></div>`\n\t\t);\n\t});\n\n\tit('should merge new elements when called multiple times', () => {\n\t\trender(<div />, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.firstChild).to.have.property('nodeName', 'DIV');\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\n\t\trender(<span />, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.firstChild).to.have.property('nodeName', 'SPAN');\n\t\texpect(scratch.innerHTML).to.equal('<span></span>');\n\n\t\trender(<span class=\"hello\">Hello!</span>, scratch);\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.firstChild).to.have.property('nodeName', 'SPAN');\n\t\texpect(scratch.innerHTML).to.equal('<span class=\"hello\">Hello!</span>');\n\t});\n\n\tit('should nest empty nodes', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<span />\n\t\t\t\t<foo />\n\t\t\t\t<x-bar />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.childNodes).to.have.length(1);\n\t\texpect(scratch.childNodes[0].nodeName).to.equal('DIV');\n\n\t\tlet c = scratch.childNodes[0].childNodes;\n\t\texpect(c).to.have.length(3);\n\t\texpect(c[0].nodeName).to.equal('SPAN');\n\t\texpect(c[1].nodeName).to.equal('FOO');\n\t\texpect(c[2].nodeName).to.equal('X-BAR');\n\t});\n\n\tit('should not render falsy values', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t{null},{undefined},{false},{0},{NaN}\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.firstChild).to.have.property('innerHTML', ',,,0,NaN');\n\t});\n\n\tit('should not render null', () => {\n\t\trender(null, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t\texpect(scratch.childNodes).to.have.length(0);\n\t});\n\n\tit('should not render undefined', () => {\n\t\trender(undefined, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t\texpect(scratch.childNodes).to.have.length(0);\n\t});\n\n\tit('should not render boolean true', () => {\n\t\trender(true, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t\texpect(scratch.childNodes).to.have.length(0);\n\t});\n\n\tit('should not render boolean false', () => {\n\t\trender(false, scratch);\n\t\texpect(scratch.innerHTML).to.equal('');\n\t\texpect(scratch.childNodes).to.have.length(0);\n\t});\n\n\tit('should not render children when using function children', () => {\n\t\trender(<div>{() => {}}</div>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('should not render children when rerendering a function child', () => {\n\t\tconst icon = () => {};\n\n\t\trender(<div>{icon}</div>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\n\t\trender(<div>{icon}</div>, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('should render NaN as text content', () => {\n\t\trender(NaN, scratch);\n\t\texpect(scratch.innerHTML).to.equal('NaN');\n\t});\n\n\tit('should render numbers (0) as text content', () => {\n\t\trender(0, scratch);\n\t\texpect(scratch.innerHTML).to.equal('0');\n\t});\n\n\tit('should render numbers (42) as text content', () => {\n\t\trender(42, scratch);\n\t\texpect(scratch.innerHTML).to.equal('42');\n\t});\n\n\tit('should render bigint as text content', () => {\n\t\t// Skip in browsers not supporting big integers\n\t\tif (typeof BigInt === 'undefined') {\n\t\t\treturn;\n\t\t}\n\n\t\t// eslint-disable-next-line no-undef, new-cap\n\t\trender(BigInt(4), scratch);\n\t\texpect(scratch.innerHTML).to.equal('4');\n\t});\n\n\tit('should render strings as text content', () => {\n\t\trender('Testing, huh! How is it going?', scratch);\n\t\texpect(scratch.innerHTML).to.equal('Testing, huh! How is it going?');\n\t});\n\n\tit('should render arrays of mixed elements', () => {\n\t\trender(getMixedArray(), scratch);\n\t\texpect(scratch.innerHTML).to.equal(mixedArrayHTML);\n\t});\n\n\tit('should clear falsy attributes', () => {\n\t\trender(\n\t\t\t<div\n\t\t\t\tanull=\"anull\"\n\t\t\t\taundefined=\"aundefined\"\n\t\t\t\tafalse=\"afalse\"\n\t\t\t\tanan=\"aNaN\"\n\t\t\t\ta0=\"a0\"\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\trender(\n\t\t\t<div\n\t\t\t\tanull={null}\n\t\t\t\taundefined={undefined}\n\t\t\t\tafalse={false}\n\t\t\t\tanan={NaN}\n\t\t\t\ta0={0}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(\n\t\t\tgetAttributes(scratch.firstChild),\n\t\t\t'from previous truthy values'\n\t\t).to.eql({\n\t\t\ta0: '0',\n\t\t\tanan: 'NaN'\n\t\t});\n\t});\n\n\tit('should not render falsy attributes on hydrate', () => {\n\t\trender(\n\t\t\t<div\n\t\t\t\tanull={null}\n\t\t\t\taundefined={undefined}\n\t\t\t\tafalse={false}\n\t\t\t\tanan={NaN}\n\t\t\t\ta0={0}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(getAttributes(scratch.firstChild), 'initial render').to.eql({\n\t\t\ta0: '0',\n\t\t\tanan: 'NaN'\n\t\t});\n\t});\n\n\tit('should clear falsy input values', () => {\n\t\t// Note: this test just demonstrates the default browser behavior\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<input value={0} />\n\t\t\t\t<input value={false} />\n\t\t\t\t<input value={null} />\n\t\t\t\t<input value={undefined} />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet root = scratch.firstChild;\n\t\texpect(root.children[0]).to.have.property('value', '0');\n\t\texpect(root.children[1]).to.have.property('value', 'false');\n\t\texpect(root.children[2]).to.have.property('value', '');\n\t\texpect(root.children[3]).to.have.property('value', '');\n\t});\n\n\tit('should set value inside the specified range', () => {\n\t\trender(\n\t\t\t<input type=\"range\" value={0.5} min=\"0\" max=\"1\" step=\"0.05\" />,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.firstChild.value).to.equal('0.5');\n\t});\n\n\tit('should not clear falsy DOM properties', () => {\n\t\tfunction test(val) {\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\t<input value={val} />\n\t\t\t\t\t<table border={val} />\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t}\n\n\t\ttest('2');\n\t\ttest(false);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><input><table border=\"false\"></table></div>',\n\t\t\t'for false'\n\t\t);\n\n\t\ttest('3');\n\t\ttest(null);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><input><table border=\"\"></table></div>',\n\t\t\t'for null'\n\t\t);\n\n\t\ttest('4');\n\t\ttest(undefined);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><input><table border=\"\"></table></div>',\n\t\t\t'for undefined'\n\t\t);\n\t});\n\n\t// Test for #3969\n\tit('should clear rowspan and colspan', () => {\n\t\t/** @type {(v) => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { active: true };\n\t\t\t\tupdate = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.active ? (\n\t\t\t\t\t\t\t<table>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td rowSpan={2} colSpan={2}>\n\t\t\t\t\t\t\t\t\t\tFoo\n\t\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<table>\n\t\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t\t<td>Foo</td>\n\t\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tupdate({ active: false });\n\t\trerender();\n\n\t\texpect(scratch.querySelector('td[rowspan]')).to.equal(null);\n\t\texpect(scratch.querySelector('td[colspan]')).to.equal(null);\n\t});\n\n\t// Test for preactjs/preact#651\n\tit('should set enumerable boolean attribute', () => {\n\t\trender(<input spellcheck={false} />, scratch);\n\t\texpect(scratch.firstChild.spellcheck).to.equal(false);\n\t});\n\n\tit('should support popover auto', () => {\n\t\trender(<div popover=\"auto\" />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div popover=\"auto\"></div>');\n\t});\n\n\tit('should support popover true boolean', () => {\n\t\trender(<div popover />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div popover=\"\"></div>');\n\t});\n\n\tit('should support popover false boolean', () => {\n\t\trender(<div popover={false} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\t// Test for preactjs/preact#4340\n\tit('should respect defaultValue in render', () => {\n\t\tscratch.innerHTML = '<input value=\"foo\">';\n\t\trender(<input defaultValue=\"foo\" />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('foo');\n\t});\n\n\tit('should support subsequent renders w/ defaultValue', () => {\n\t\tscratch.innerHTML = '<input value=\"foo\">';\n\t\trender(<input defaultValue=\"foo\" value=\"bar\" />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('bar');\n\t\trender(<input defaultValue=\"foo\" value=\"baz\" />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('baz');\n\t});\n\n\tit('should respect defaultChecked in render', () => {\n\t\tscratch.innerHTML = '<input checked=\"true\">';\n\t\trender(<input defaultChecked />, scratch);\n\t\texpect(scratch.firstChild.checked).to.equal(true);\n\t});\n\n\tit('should support subsequent renders w/ defaultChecked', () => {\n\t\tscratch.innerHTML = '<input checked=\"true\">';\n\t\trender(<input defaultChecked checked />, scratch);\n\t\texpect(scratch.firstChild.checked).to.equal(true);\n\t\trender(<input defaultChecked checked={false} />, scratch);\n\t\texpect(scratch.firstChild.checked).to.equal(false);\n\t});\n\n\tit('should not try to set element.children', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<span />\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\tconst spy = vi.fn();\n\t\tObject.defineProperty(scratch.firstChild, 'children', {\n\t\t\tset: spy\n\t\t});\n\t\trender(<div />, scratch);\n\t\texpect(spy).not.toHaveBeenCalled();\n\t});\n\n\tit('should render download attribute', () => {\n\t\trender(<a download=\"\" />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('download')).to.equal('');\n\n\t\trender(<a download={null} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('download')).to.equal(null);\n\t});\n\n\tit('should not set tagName', () => {\n\t\texpect(() => render(<input tagName=\"div\" />, scratch)).not.to.throw();\n\t});\n\n\tit('should apply string attributes', () => {\n\t\trender(<div foo=\"bar\" data-foo=\"databar\" />, scratch);\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\t'<div data-foo=\"databar\" foo=\"bar\"></div>'\n\t\t);\n\t});\n\n\tit('should not serialize function props as attributes', () => {\n\t\trender(<div click={function a() {}} ONCLICK={function b() {}} />, scratch);\n\n\t\tlet div = scratch.childNodes[0];\n\t\texpect(div.attributes.length).to.equal(0);\n\t});\n\n\tit('should serialize object props as attributes', () => {\n\t\trender(\n\t\t\t<div\n\t\t\t\tfoo={{ a: 'b' }}\n\t\t\t\tbar={{\n\t\t\t\t\ttoString() {\n\t\t\t\t\t\treturn 'abc';\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t/>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet div = scratch.childNodes[0];\n\t\texpect(div.attributes.length).to.equal(2);\n\n\t\t// Normalize attribute order because it's different in various browsers\n\t\tlet normalized = {};\n\t\tfor (let i = 0; i < div.attributes.length; i++) {\n\t\t\tlet attr = div.attributes[i];\n\t\t\tnormalized[attr.name] = attr.value;\n\t\t}\n\n\t\texpect(normalized).to.deep.equal({\n\t\t\tbar: 'abc',\n\t\t\tfoo: '[object Object]'\n\t\t});\n\t});\n\n\tit('should apply class as String', () => {\n\t\trender(<div class=\"foo\" />, scratch);\n\t\texpect(scratch.childNodes[0]).to.have.property('className', 'foo');\n\t});\n\n\tit('should alias className to class', () => {\n\t\trender(<div className=\"bar\" />, scratch);\n\t\texpect(scratch.childNodes[0]).to.have.property('className', 'bar');\n\t});\n\n\tit('should support false string aria-* attributes', () => {\n\t\trender(<div aria-checked=\"false\" />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('aria-checked')).to.equal('false');\n\t});\n\n\tit('should support false aria-* attributes', () => {\n\t\trender(<div aria-checked={false} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('aria-checked')).to.equal('false');\n\t});\n\n\tit('should support false data-* attributes', () => {\n\t\trender(<div data-checked={false} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('data-checked')).to.equal('false');\n\t});\n\n\tit('should set checked attribute on custom elements without checked property', () => {\n\t\trender(<o-checkbox checked />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<o-checkbox checked=\"true\"></o-checkbox>'\n\t\t);\n\t});\n\n\tit('should set value attribute on custom elements without value property', () => {\n\t\trender(<o-input value=\"test\" />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<o-input value=\"test\"></o-input>');\n\t});\n\n\tit('should mask value on password input elements', () => {\n\t\trender(<input value=\"xyz\" type=\"password\" />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<input type=\"password\">');\n\t});\n\n\tit('should unset href if null || undefined', () => {\n\t\trender(\n\t\t\t<pre>\n\t\t\t\t<a href=\"#\">href=\"#\"</a>\n\t\t\t\t<a href={undefined}>href=\"undefined\"</a>\n\t\t\t\t<a href={null}>href=\"null\"</a>\n\t\t\t\t<a href={''}>href=\"''\"</a>\n\t\t\t</pre>,\n\t\t\tscratch\n\t\t);\n\n\t\tconst links = scratch.querySelectorAll('a');\n\t\texpect(links[0].hasAttribute('href')).to.equal(true);\n\t\texpect(links[1].hasAttribute('href')).to.equal(false);\n\t\texpect(links[2].hasAttribute('href')).to.equal(false);\n\t\texpect(links[3].hasAttribute('href')).to.equal(true);\n\t});\n\n\tdescribe('dangerouslySetInnerHTML', () => {\n\t\tit('should support dangerouslySetInnerHTML', () => {\n\t\t\tlet html = '<b>foo &amp; bar</b>';\n\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\trender(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch);\n\n\t\t\texpect(scratch.firstChild, 'set').to.have.property('innerHTML', html);\n\t\t\texpect(scratch.innerHTML).to.equal('<div>' + html + '</div>');\n\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\ta<strong>b</strong>\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\texpect(scratch, 'unset').to.have.property(\n\t\t\t\t'innerHTML',\n\t\t\t\t`<div>a<strong>b</strong></div>`\n\t\t\t);\n\n\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\trender(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch);\n\t\t\texpect(scratch.innerHTML, 're-set').to.equal('<div>' + html + '</div>');\n\t\t});\n\n\t\tit('should apply proper mutation for VNodes with dangerouslySetInnerHTML attr', () => {\n\t\t\t/** @type {Component} */\n\t\t\tlet thing;\n\t\t\tclass Thing extends Component {\n\t\t\t\tconstructor(props, context) {\n\t\t\t\t\tsuper(props, context);\n\t\t\t\t\tthis.state = { html: this.props.html };\n\t\t\t\t\tthing = this;\n\t\t\t\t}\n\t\t\t\trender(props, { html }) {\n\t\t\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\t\t\treturn html ? (\n\t\t\t\t\t\t<div dangerouslySetInnerHTML={{ __html: html }} />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div />\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Thing html=\"<b><i>test</i></b>\" />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div><b><i>test</i></b></div>');\n\n\t\t\tthing.setState({ html: false });\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\n\t\t\tthing.setState({ html: '<foo><bar>test</bar></foo>' });\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t'<div><foo><bar>test</bar></foo></div>'\n\t\t\t);\n\t\t});\n\n\t\tit('should not hydrate with dangerouslySetInnerHTML', () => {\n\t\t\tlet html = '<b>foo &amp; bar</b>';\n\t\t\tscratch.innerHTML = `<div>${html}</div>`;\n\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\trender(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch);\n\n\t\t\texpect(scratch.firstChild).to.have.property('innerHTML', html);\n\t\t\texpect(scratch.innerHTML).to.equal(`<div>${html}</div>`);\n\t\t});\n\n\t\tit('should avoid reapplying innerHTML when __html property of dangerouslySetInnerHTML attr remains unchanged', () => {\n\t\t\t/** @type {Component} */\n\t\t\tlet thing;\n\t\t\tclass Thing extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tthing = this;\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\t// eslint-disable-next-line react/no-danger\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div dangerouslySetInnerHTML={{ __html: '<span>same</span>' }} />\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<Thing />, scratch);\n\n\t\t\tlet firstInnerHTMLChild = scratch.firstChild.firstChild;\n\n\t\t\t// Re-render\n\t\t\tthing.forceUpdate();\n\n\t\t\texpect(firstInnerHTMLChild).to.equalNode(scratch.firstChild.firstChild);\n\t\t});\n\n\t\tit('should unmount dangerouslySetInnerHTML', () => {\n\t\t\t/** @type {(v) => void} */\n\t\t\tlet set;\n\n\t\t\tconst TextDiv = () => (\n\t\t\t\t<div dangerouslySetInnerHTML={{ __html: '' }}>some text</div>\n\t\t\t);\n\n\t\t\tclass App extends Component {\n\t\t\t\tconstructor(props) {\n\t\t\t\t\tsuper(props);\n\t\t\t\t\tset = this.setState.bind(this);\n\t\t\t\t\tthis.state = { show: true };\n\t\t\t\t}\n\n\t\t\t\trender() {\n\t\t\t\t\treturn this.state.show && <TextDiv />;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender(<App />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\n\t\t\tset({ show: false });\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('');\n\t\t});\n\t});\n\n\tit('should reconcile mutated DOM attributes', () => {\n\t\tlet check = p => render(<input type=\"checkbox\" checked={p} />, scratch),\n\t\t\tvalue = () => scratch.lastChild.checked,\n\t\t\tsetValue = p => (scratch.lastChild.checked = p);\n\t\tcheck(true);\n\t\texpect(value()).to.equal(true);\n\t\tcheck(false);\n\t\texpect(value()).to.equal(false);\n\t\tcheck(true);\n\t\texpect(value()).to.equal(true);\n\t\tsetValue(true);\n\t\tcheck(false);\n\t\texpect(value()).to.equal(false);\n\t\tsetValue(false);\n\t\tcheck(true);\n\t\texpect(value()).to.equal(true);\n\t});\n\n\tit('should reorder child pairs', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<a>a</a>\n\t\t\t\t<b>b</b>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet a = scratch.firstChild.firstChild;\n\t\tlet b = scratch.firstChild.lastChild;\n\n\t\texpect(a).to.have.property('nodeName', 'A');\n\t\texpect(b).to.have.property('nodeName', 'B');\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<b>b</b>\n\t\t\t\t<a>a</a>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.firstChild.firstChild).to.equalNode(b);\n\t\texpect(scratch.firstChild.lastChild).to.equalNode(a);\n\t});\n\n\t// Discussion: https://github.com/preactjs/preact/issues/287\n\t// <datalist> is not supported in Safari, even though the element\n\t// constructor is present\n\tif (supportsDataList()) {\n\t\tit('should allow <input list /> to pass through as an attribute', () => {\n\t\t\trender(\n\t\t\t\t<div>\n\t\t\t\t\t<input type=\"range\" min=\"0\" max=\"100\" list=\"steplist\" />\n\t\t\t\t\t<datalist id=\"steplist\">\n\t\t\t\t\t\t<option>0</option>\n\t\t\t\t\t\t<option>50</option>\n\t\t\t\t\t\t<option>100</option>\n\t\t\t\t\t</datalist>\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\n\t\t\tlet html = scratch.firstElementChild.firstElementChild.outerHTML;\n\t\t\texpect(sortAttributes(html)).to.equal(\n\t\t\t\tsortAttributes('<input type=\"range\" min=\"0\" max=\"100\" list=\"steplist\">')\n\t\t\t);\n\t\t});\n\t}\n\n\t// Issue #2284\n\tit('should not throw when setting size to an invalid value', () => {\n\t\t// These values are usually used to reset the `size` attribute to its\n\t\t// initial state.\n\t\texpect(() => render(<input size={undefined} />, scratch)).to.not.throw();\n\t\texpect(() => render(<input size={null} />, scratch)).to.not.throw();\n\t\texpect(() => render(<input size={0} />, scratch)).to.not.throw();\n\t});\n\n\tit('should not execute append operation when child is at last', () => {\n\t\t// See preactjs/preact#717 for discussion about the issue this addresses\n\n\t\tlet todoText = 'new todo that I should complete';\n\t\tlet input;\n\t\t/** @type {(v) => void} */\n\t\tlet setText;\n\t\t/** @type {(v) => void} */\n\t\tlet addTodo;\n\n\t\tconst ENTER = 13;\n\n\t\tclass TodoList extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { todos: [], text: '' };\n\t\t\t\tsetText = this.setText = this.setText.bind(this);\n\t\t\t\taddTodo = this.addTodo = this.addTodo.bind(this);\n\t\t\t}\n\t\t\tsetText(e) {\n\t\t\t\tthis.setState({ text: e.target.value });\n\t\t\t}\n\t\t\taddTodo(e) {\n\t\t\t\tif (e.keyCode === ENTER) {\n\t\t\t\t\tlet { todos, text } = this.state;\n\t\t\t\t\ttodos = todos.concat({ text });\n\t\t\t\t\tthis.setState({ todos, text: '' });\n\t\t\t\t}\n\t\t\t}\n\t\t\trender() {\n\t\t\t\tconst { todos, text } = this.state;\n\t\t\t\treturn (\n\t\t\t\t\t<div onKeyDown={this.addTodo}>\n\t\t\t\t\t\t{todos.map(todo => [\n\t\t\t\t\t\t\t<span>{todo.text}</span>,\n\t\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t[ <a href=\"javascript:;\">Delete</a> ]\n\t\t\t\t\t\t\t</span>,\n\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t])}\n\t\t\t\t\t\t<input value={text} onInput={this.setText} ref={i => (input = i)} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<TodoList />, scratch);\n\n\t\t// Simulate user typing\n\t\tinput.focus();\n\t\tinput.value = todoText;\n\t\tsetText({\n\t\t\ttarget: input\n\t\t});\n\n\t\t// Commit the user typing setState call\n\t\trerender();\n\n\t\t// Simulate user pressing enter\n\t\taddTodo({\n\t\t\tkeyCode: ENTER\n\t\t});\n\n\t\t// Before Preact rerenders, focus should be on the input\n\t\texpect(document.activeElement).to.equalNode(input);\n\n\t\trerender();\n\n\t\t// After Preact rerenders, focus should remain on the input\n\t\texpect(document.activeElement).to.equalNode(input);\n\t\texpect(scratch.innerHTML).to.contain(`<span>${todoText}</span>`);\n\t});\n\n\tit('should keep value of uncontrolled inputs', () => {\n\t\trender(<input value={undefined} />, scratch);\n\t\tscratch.firstChild.value = 'foo';\n\t\trender(<input value={undefined} />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('foo');\n\t});\n\n\tit('should keep value of uncontrolled checkboxes', () => {\n\t\trender(<input type=\"checkbox\" checked={undefined} />, scratch);\n\t\tscratch.firstChild.checked = true;\n\t\trender(<input type=\"checkbox\" checked={undefined} />, scratch);\n\t\texpect(scratch.firstChild.checked).to.equal(true);\n\t});\n\n\t// #2756\n\tit('should set progress value to 0', () => {\n\t\trender(<progress value={0} max=\"100\" />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal(0);\n\t\texpect(scratch.firstChild.getAttribute('value')).to.equal('0');\n\t});\n\n\t// #4487\n\tit('should not set value for undefined/null on a progress element', () => {\n\t\trender(<progress value={undefined} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('value')).to.equal(null);\n\t\trender(<progress value={null} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('value')).to.equal(null);\n\t\trender(<progress value={0} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('value')).to.equal('0');\n\t\trender(<progress value={50} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('value')).to.equal('50');\n\t\trender(<progress value={null} />, scratch);\n\t\texpect(scratch.firstChild.getAttribute('value')).to.equal(null);\n\t});\n\n\tit('should always diff `checked` and `value` properties against the DOM', () => {\n\t\t// See https://github.com/preactjs/preact/issues/1324\n\n\t\tlet inputs;\n\t\tlet text;\n\t\tlet checkbox;\n\n\t\tclass Inputs extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tinputs = this;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<input value={'Hello'} ref={el => (text = el)} />\n\t\t\t\t\t\t<input type=\"checkbox\" checked ref={el => (checkbox = el)} />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<Inputs />, scratch);\n\n\t\texpect(text.value).to.equal('Hello');\n\t\texpect(checkbox.checked).to.equal(true);\n\n\t\ttext.value = 'World';\n\t\tcheckbox.checked = false;\n\n\t\tinputs.forceUpdate();\n\t\trerender();\n\n\t\texpect(text.value).to.equal('Hello');\n\t\texpect(checkbox.checked).to.equal(true);\n\t});\n\n\tit('should always diff `contenteditable` `innerHTML` against the DOM', () => {\n\t\t// This tests that we do not cause any cursor jumps in contenteditable fields\n\t\t// See https://github.com/preactjs/preact/issues/2691\n\n\t\tfunction Editable() {\n\t\t\tconst [value, setValue] = useState('Hello');\n\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tcontentEditable\n\t\t\t\t\tdangerouslySetInnerHTML={{ __html: value }}\n\t\t\t\t\tonInput={e => setValue(e.currentTarget.innerHTML)}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\n\t\trender(<Editable />, scratch);\n\n\t\tlet editable = scratch.querySelector('[contenteditable]');\n\n\t\t// modify the innerHTML and set the caret to character 2 to simulate a user typing\n\t\teditable.innerHTML = 'World';\n\n\t\tconst range = document.createRange();\n\t\trange.selectNodeContents(editable);\n\t\trange.setStart(editable.childNodes[0], 2);\n\t\trange.collapse(true);\n\t\tconst sel = window.getSelection();\n\t\tsel.removeAllRanges();\n\t\tsel.addRange(range);\n\n\t\t// ensure we didn't mess up setting the cursor to position 2\n\t\texpect(window.getSelection().getRangeAt(0).startOffset).to.equal(2);\n\n\t\t// dispatch the input event to tell preact to re-render\n\t\teditable.dispatchEvent(createEvent('input'));\n\t\trerender();\n\n\t\t// ensure innerHTML is still correct (was not an issue before) and\n\t\t// more importantly the caret is still at character 2\n\t\teditable = scratch.querySelector('[contenteditable]');\n\t\texpect(editable.innerHTML).to.equal('World');\n\t\texpect(window.getSelection().getRangeAt(0).startOffset).to.equal(2);\n\t});\n\n\tit('should not re-render when a component returns undefined', () => {\n\t\tlet Dialog = () => undefined;\n\t\t/** @type {() => void} */\n\t\tlet updateState;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { name: '' };\n\t\t\t\tupdateState = () => this.setState({ name: ', friend' });\n\t\t\t}\n\n\t\t\trender(props, { name }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<Dialog />\n\t\t\t\t\t\t<h1 class=\"fade-down\">Hi{name}</h1>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tclearLog();\n\n\t\tupdateState();\n\t\trerender();\n\n\t\t// We don't log text updates\n\t\texpect(getLog()).to.deep.equal([]);\n\t});\n\n\tit('should not lead to stale DOM nodes', () => {\n\t\tlet i = 0;\n\t\t/** @type {() => void} */\n\t\tlet updateApp;\n\t\tclass App extends Component {\n\t\t\trender() {\n\t\t\t\tupdateApp = () => this.forceUpdate();\n\t\t\t\treturn <Parent />;\n\t\t\t}\n\t\t}\n\n\t\t/** @type {() => void} */\n\t\tlet updateParent;\n\t\tfunction Parent() {\n\t\t\tupdateParent = () => this.forceUpdate();\n\t\t\ti++;\n\t\t\treturn <Child i={i} />;\n\t\t}\n\n\t\tfunction Child({ i }) {\n\t\t\treturn i < 3 ? null : <div>foo</div>;\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\tupdateApp();\n\t\trerender();\n\t\tupdateParent();\n\t\trerender();\n\t\tupdateApp();\n\t\trerender();\n\n\t\t// Without a fix it would render: `<div>foo</div><div></div>`\n\t\texpect(scratch.innerHTML).to.equal('<div>foo</div>');\n\t});\n\n\t// see preact/#1327\n\tit('should not reuse unkeyed components', () => {\n\t\tlet ref;\n\t\tclass X extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tref = this;\n\t\t\t\tthis.id = null;\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t}\n\n\t\t\tupdate() {\n\t\t\t\tthis.setState(prev => ({ i: prev.i + 1 }));\n\t\t\t}\n\n\t\t\tcomponentWillUnmount() {\n\t\t\t\tclearTimeout(this.id);\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <div>{this.state.i}</div>;\n\t\t\t}\n\t\t}\n\n\t\t/** @type {() => void} */\n\t\tlet updateApp;\n\t\tclass App extends Component {\n\t\t\tconstructor() {\n\t\t\t\tsuper();\n\t\t\t\tthis.state = { i: 0 };\n\t\t\t\tupdateApp = () => this.setState(prev => ({ i: prev.i ^ 1 }));\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{this.state.i === 0 && <X />}\n\t\t\t\t\t\t<X />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.textContent).to.equal('00');\n\n\t\tref.update();\n\t\tupdateApp();\n\t\trerender();\n\t\texpect(scratch.textContent).to.equal('1');\n\n\t\tupdateApp();\n\t\trerender();\n\n\t\texpect(scratch.textContent).to.equal('01');\n\t});\n\n\tit('should not remove iframe', () => {\n\t\t/** @type {(v) => void} */\n\t\tlet setState;\n\t\tconst Iframe = () => {\n\t\t\t// oxlint-disable-next-line iframe-missing-sandbox\n\t\t\treturn <iframe src=\"https://codesandbox.io/s/runtime-silence-no4zx\" />;\n\t\t};\n\n\t\tconst Test2 = () => <div>Test2</div>;\n\t\tconst Test3 = () => <div>Test3</div>;\n\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { value: true };\n\t\t\t\tsetState = this.setState.bind(this);\n\t\t\t}\n\n\t\t\trender(props, state) {\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{state.value ? <Test3 /> : null}\n\t\t\t\t\t\t{state.value ? <Test2 /> : null}\n\t\t\t\t\t\t<Iframe key=\"iframe\" />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>Test3</div><div>Test2</div><iframe src=\"https://codesandbox.io/s/runtime-silence-no4zx\"></iframe></div>'\n\t\t);\n\t\tclearLog();\n\t\tsetState({ value: false });\n\t\trerender();\n\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><iframe src=\"https://codesandbox.io/s/runtime-silence-no4zx\"></iframe></div>'\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>Test3.remove()',\n\t\t\t'<div>Test2.remove()'\n\t\t]);\n\t});\n\n\tit('should not cause infinite loop with referentially equal props', () => {\n\t\tlet i = 0;\n\t\tlet prevDiff = options._diff;\n\t\toptions._diff = () => {\n\t\t\tif (++i > 10) {\n\t\t\t\toptions._diff = prevDiff;\n\t\t\t\tthrow new Error('Infinite loop');\n\t\t\t}\n\t\t};\n\n\t\tfunction App({ children, ...rest }) {\n\t\t\treturn (\n\t\t\t\t<div {...rest}>\n\t\t\t\t\t<div {...rest}>{children}</div>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<App>10</App>, scratch);\n\t\texpect(scratch.textContent).to.equal('10');\n\t\toptions._diff = prevDiff;\n\t});\n\n\tit('should not call options.debounceRendering unnecessarily', () => {\n\t\t/** @type {A} */\n\t\tlet comp;\n\n\t\tclass A extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { updates: 0 };\n\t\t\t\tcomp = this;\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <div>{this.state.updates}</div>;\n\t\t\t}\n\t\t}\n\n\t\trender(<A />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div>0</div>');\n\n\t\tconst debounceSpy = vi.spyOn(options, 'debounceRendering');\n\t\ttry {\n\t\t\tcomp.setState({ updates: 1 }, () => {\n\t\t\t\tcomp.setState({ updates: 2 });\n\t\t\t});\n\t\t\trerender();\n\t\t\texpect(scratch.innerHTML).to.equal('<div>2</div>');\n\n\t\t\texpect(debounceSpy).toHaveBeenCalledTimes(1);\n\t\t} finally {\n\t\t\tdebounceSpy.mockRestore();\n\t\t}\n\t});\n\n\tit('should remove attributes on pre-existing DOM', () => {\n\t\tconst div = document.createElement('div');\n\t\tdiv.setAttribute('class', 'red');\n\t\tconst span = document.createElement('span');\n\t\tconst text = document.createTextNode('Hi');\n\n\t\tspan.appendChild(text);\n\t\tdiv.appendChild(span);\n\t\tscratch.appendChild(div);\n\n\t\tconst App = () => (\n\t\t\t<div>\n\t\t\t\t<span>Bye</span>\n\t\t\t</div>\n\t\t);\n\n\t\trender(<App />, scratch);\n\t\texpect(serializeHtml(scratch)).to.equal('<div><span>Bye</span></div>');\n\t});\n\n\tit('should remove class attributes', () => {\n\t\tconst App = props => (\n\t\t\t<div className={props.class}>\n\t\t\t\t<span>Bye</span>\n\t\t\t</div>\n\t\t);\n\n\t\trender(<App class=\"hi\" />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div class=\"hi\"><span>Bye</span></div>'\n\t\t);\n\n\t\trender(<App />, scratch);\n\t\texpect(serializeHtml(scratch)).to.equal('<div><span>Bye</span></div>');\n\t});\n\n\tit('should not read DOM attributes on render without existing DOM', () => {\n\t\tconst attributesSpy = spyOnElementAttributes();\n\t\trender(\n\t\t\t<div id=\"wrapper\">\n\t\t\t\t<div id=\"page1\">Page 1</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"wrapper\"><div id=\"page1\">Page 1</div></div>'\n\t\t);\n\n\t\texpect(attributesSpy).not.toHaveBeenCalled();\n\n\t\trender(\n\t\t\t<div id=\"wrapper\">\n\t\t\t\t<div id=\"page2\">Page 2</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div id=\"wrapper\"><div id=\"page2\">Page 2</div></div>'\n\t\t);\n\n\t\texpect(attributesSpy).not.toHaveBeenCalled();\n\t});\n\n\t// #2926\n\tit('should not throw when changing contentEditable to undefined or null', () => {\n\t\trender(<p contentEditable>foo</p>, scratch);\n\n\t\texpect(() =>\n\t\t\trender(<p contentEditable={undefined}>foo</p>, scratch)\n\t\t).to.not.throw();\n\t\texpect(scratch.firstChild.contentEditable).to.equal('inherit');\n\n\t\texpect(() =>\n\t\t\trender(<p contentEditable={null}>foo</p>, scratch)\n\t\t).to.not.throw();\n\t\texpect(scratch.firstChild.contentEditable).to.equal('inherit');\n\t});\n\n\t// #2926 Part 2\n\tit('should allow setting contentEditable to false', () => {\n\t\trender(\n\t\t\t<div contentEditable>\n\t\t\t\t<span>editable</span>\n\t\t\t\t<p contentEditable={false}>not editable</p>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.firstChild.contentEditable).to.equal('true');\n\t\texpect(scratch.querySelector('p').contentEditable).to.equal('false');\n\t});\n\n\t// #3060\n\tit('should reset tabindex on undefined/null', () => {\n\t\tconst defaultValue = -1;\n\n\t\trender(<div tabIndex={0} />, scratch);\n\t\texpect(scratch.firstChild.tabIndex).to.equal(0);\n\t\trender(<div tabIndex={undefined} />, scratch);\n\t\texpect(scratch.firstChild.tabIndex).to.equal(defaultValue);\n\t\trender(<div tabIndex={null} />, scratch);\n\t\texpect(scratch.firstChild.tabIndex).to.equal(defaultValue);\n\n\t\trender(<div tabindex={0} />, scratch);\n\t\texpect(scratch.firstChild.tabIndex).to.equal(0);\n\t\trender(<div tabindex={undefined} />, scratch);\n\t\texpect(scratch.firstChild.tabIndex).to.equal(defaultValue);\n\t\trender(<div tabindex={null} />, scratch);\n\t\texpect(scratch.firstChild.tabIndex).to.equal(defaultValue);\n\t});\n\n\t// #4137\n\tit('should unset role if null || undefined', () => {\n\t\trender(\n\t\t\t<section>\n\t\t\t\t<div role=\"status\">role=\"status\"</div>\n\t\t\t\t<div role={undefined}>role=\"undefined\"</div>\n\t\t\t\t<div role={null}>role=\"null\"</div>\n\t\t\t</section>,\n\t\t\tscratch\n\t\t);\n\n\t\tconst divs = scratch.querySelectorAll('div');\n\t\texpect(divs[0].hasAttribute('role')).to.equal(true);\n\t\texpect(divs[1].hasAttribute('role')).to.equal(false);\n\t\texpect(divs[2].hasAttribute('role')).to.equal(false);\n\t});\n\n\tit('should not crash or repeatedly add the same child when replacing a matched vnode with null', () => {\n\t\tconst B = () => <div>B</div>;\n\n\t\t/** @type {() => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true };\n\t\t\t\tupdate = () => {\n\t\t\t\t\tthis.setState(state => ({ show: !state.show }));\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tif (this.state.show) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<B />\n\t\t\t\t\t\t\t<div />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<div />\n\t\t\t\t\t\t{null}\n\t\t\t\t\t\t<B />\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>B</div><div></div></div>');\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><div></div><div>B</div></div>');\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><div>B</div><div></div></div>');\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><div></div><div>B</div></div>');\n\t});\n\n\tit('should reconcile children in right order', () => {\n\t\tlet data = ['A', 'B', 'C', 'D', 'E'];\n\t\trender(\n\t\t\t<ul>\n\t\t\t\t{data.map(d => (\n\t\t\t\t\t<li key={d}>{d}</li>\n\t\t\t\t))}\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.textContent).to.equal('ABCDE');\n\n\t\tdata = ['B', 'E', 'C', 'D'];\n\t\trender(\n\t\t\t<ul>\n\t\t\t\t{data.map(d => (\n\t\t\t\t\t<li key={d}>{d}</li>\n\t\t\t\t))}\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.textContent).to.equal('BECD');\n\t});\n\n\tit('should reconcile children in right order #2', () => {\n\t\tlet data = ['A', 'B', 'C', 'D', 'E'];\n\t\trender(\n\t\t\t<ul>\n\t\t\t\t{data.map(d => (\n\t\t\t\t\t<li key={d}>{d}</li>\n\t\t\t\t))}\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.textContent).to.equal('ABCDE');\n\n\t\tdata = ['B', 'E', 'D', 'C'];\n\t\trender(\n\t\t\t<ul>\n\t\t\t\t{data.map(d => (\n\t\t\t\t\t<li key={d}>{d}</li>\n\t\t\t\t))}\n\t\t\t</ul>,\n\t\t\tscratch\n\t\t);\n\t\texpect(scratch.textContent).to.equal('BEDC');\n\t});\n\n\tit('should reconcile children in right order #3', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<p>_A1</p>\n\t\t\t\t<p>_A2</p>\n\t\t\t\t<h2>_A3</h2>\n\t\t\t\t<p>_A4</p>\n\t\t\t\t<h2>_A5</h2>\n\t\t\t\t<p>_A6</p>\n\t\t\t\t<h2>_A7</h2>\n\t\t\t\t<p>_A8</p>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<p>_B1</p>\n\t\t\t\t<p>_B2</p>\n\t\t\t\t<p>_B3</p>\n\t\t\t\t<h2>_B4</h2>\n\t\t\t\t<p>_B5</p>\n\t\t\t\t<p>_B6</p>\n\t\t\t\t<h2>_B7</h2>\n\t\t\t\t<p>_B8</p>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\t'<div><p>_B1</p><p>_B2</p><p>_B3</p><h2>_B4</h2><p>_B5</p><p>_B6</p><h2>_B7</h2><p>_B8</p></div>'\n\t\t);\n\t});\n\n\tit('should reconcile children in right order #4', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<p>_A1</p>\n\t\t\t\t<p>_A2</p>\n\t\t\t\t<div>_A3</div>\n\t\t\t\t<h2>_A4</h2>\n\t\t\t\t<p>_A5</p>\n\t\t\t\t<div>_A6</div>\n\t\t\t\t<h2>_A7</h2>\n\t\t\t\t<p>_A8</p>\n\t\t\t\t<div>_A9</div>\n\t\t\t\t<h2>_A10</h2>\n\t\t\t\t<p>_A11</p>\n\t\t\t\t<div>_A12</div>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<p>_B1</p>\n\t\t\t\t<p>_B2</p>\n\t\t\t\t<p>_B3</p>\n\t\t\t\t<h2>_B4</h2>\n\t\t\t\t<p>_B5</p>\n\t\t\t\t<p>_B6</p>\n\t\t\t\t<p>_B7</p>\n\t\t\t\t<h2>_B8</h2>\n\t\t\t\t<p>_B9</p>\n\t\t\t\t<p>_B10</p>\n\t\t\t\t<p>_B11</p>\n\t\t\t\t<p>_B12</p>\n\t\t\t\t<h2>_B13</h2>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(serializeHtml(scratch)).to.equal(\n\t\t\t'<div><p>_B1</p><p>_B2</p><p>_B3</p><h2>_B4</h2><p>_B5</p><p>_B6</p><p>_B7</p><h2>_B8</h2><p>_B9</p><p>_B10</p><p>_B11</p><p>_B12</p><h2>_B13</h2></div>'\n\t\t);\n\t});\n\n\tit('should not crash or repeatedly add the same child when replacing a matched vnode with null (mixed dom-types)', () => {\n\t\tconst B = () => <div>B</div>;\n\n\t\t/** @type {() => void} */\n\t\tlet update;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { show: true };\n\t\t\t\tupdate = () => {\n\t\t\t\t\tthis.setState(state => ({ show: !state.show }));\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tif (this.state.show) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<B />\n\t\t\t\t\t\t\t<div>C</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<span>A</span>\n\t\t\t\t\t\t{null}\n\t\t\t\t\t\t<B />\n\t\t\t\t\t\t<div>C</div>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('<div><div>B</div><div>C</div></div>');\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><span>A</span><div>B</div><div>C</div></div>'\n\t\t);\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal('<div><div>B</div><div>C</div></div>');\n\n\t\tupdate();\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><span>A</span><div>B</div><div>C</div></div>'\n\t\t);\n\t});\n\n\tit('should shrink lists', () => {\n\t\tfunction RenderedItem({ item }) {\n\t\t\tif (item.renderAsNullInComponent) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn <div>{item.id}</div>;\n\t\t}\n\n\t\tfunction App({ list }) {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t{list.map(item => (\n\t\t\t\t\t\t<RenderedItem key={item.id} item={item} />\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tconst firstList = [\n\t\t\t{ id: 'One' },\n\t\t\t{ id: 'Two' },\n\t\t\t{ id: 'Three' },\n\t\t\t{ id: 'Four' }\n\t\t];\n\n\t\tconst secondList = [\n\t\t\t{ id: 'One' },\n\t\t\t{ id: 'Four', renderAsNullInComponent: true },\n\t\t\t{ id: 'Six' },\n\t\t\t{ id: 'Seven' }\n\t\t];\n\n\t\trender(<App list={firstList} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>One</div><div>Two</div><div>Three</div><div>Four</div></div>'\n\t\t);\n\n\t\trender(<App list={secondList} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<div><div>One</div><div>Six</div><div>Seven</div></div>'\n\t\t);\n\t});\n\n\tit('handles shuffled child-ordering', function () {\n\t\tconst App = ({ items }) => (\n\t\t\t<div>\n\t\t\t\t{items.map(key => (\n\t\t\t\t\t<div key={key}>{key}</div>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\t\tconst a = ['0', '1', '2', '3', '4', '5', '6'];\n\t\tconst b = ['1', '3', '5', '2', '6', '4', '0'];\n\t\tconst c = ['11', '3', '1', '4', '6', '2', '5', '0', '9', '10'];\n\t\trender(<App items={a} />, scratch);\n\t\tclearLog();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${a.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\n\t\trender(<App items={b} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${b.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>0123456.insertBefore(<div>2, <div>6)',\n\t\t\t'<div>0134526.appendChild(<div>4)',\n\t\t\t'<div>0135264.appendChild(<div>0)'\n\t\t]);\n\t\tclearLog();\n\n\t\trender(<App items={c} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${c.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>1352640.insertBefore(<div>11, <div>1)',\n\t\t\t'<div>111352640.insertBefore(<div>1, <div>5)',\n\t\t\t'<div>113152640.insertBefore(<div>6, <div>0)',\n\t\t\t'<div>113152460.insertBefore(<div>2, <div>0)',\n\t\t\t'<div>113154620.insertBefore(<div>5, <div>0)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>113146250.appendChild(<div>9)',\n\t\t\t'<div>.appendChild(#text)',\n\t\t\t'<div>1131462509.appendChild(<div>10)'\n\t\t]);\n\t\tclearLog();\n\n\t\trender(<App items={a} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${a.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\t\texpect(getLog()).to.deep.equal([\n\t\t\t'<div>11.remove()',\n\t\t\t'<div>9.remove()',\n\t\t\t'<div>10.remove()',\n\t\t\t'<div>3146250.insertBefore(<div>0, <div>3)',\n\t\t\t'<div>0314625.insertBefore(<div>1, <div>3)',\n\t\t\t'<div>0134625.insertBefore(<div>2, <div>3)',\n\t\t\t'<div>0123465.insertBefore(<div>5, <div>6)'\n\t\t]);\n\t\tclearLog();\n\t});\n\n\tit('should shift keyed lists with wrapping fragment-like children', () => {\n\t\tconst ItemA = ({ text }) => <div>A: {text}</div>;\n\t\tconst ItemB = ({ text }) => <div>B: {text}</div>;\n\n\t\tconst Item = ({ text, type }) => {\n\t\t\treturn type === 'B' ? <ItemB text={text} /> : <ItemA text={text} />;\n\t\t};\n\n\t\tlet set;\n\t\tclass App extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.state = { items: a, mapping: mappingA };\n\t\t\t\tset = (items, mapping) => {\n\t\t\t\t\tthis.setState({ items, mapping });\n\t\t\t\t};\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn (\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t{this.state.items.map((key, i) => (\n\t\t\t\t\t\t\t<Item key={key} type={this.state.mapping[i]} text={key} />\n\t\t\t\t\t\t))}\n\t\t\t\t\t</ul>\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst a = ['4', '1', '2', '3'];\n\t\tconst mappingA = ['A', 'A', 'B', 'B'];\n\t\tconst b = ['1', '2', '4', '3'];\n\t\tconst mappingB = ['B', 'A', 'A', 'A'];\n\t\tconst c = ['4', '2', '1', '3'];\n\t\tconst mappingC = ['A', 'B', 'B', 'A'];\n\n\t\trender(<App items={a} mapping={mappingA} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><div>A: 4</div><div>A: 1</div><div>B: 2</div><div>B: 3</div></ul>'\n\t\t);\n\n\t\tset(b, mappingB);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><div>B: 1</div><div>A: 2</div><div>A: 4</div><div>A: 3</div></ul>'\n\t\t);\n\n\t\tset(c, mappingC);\n\t\trerender();\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t'<ul><div>A: 4</div><div>B: 2</div><div>B: 1</div><div>A: 3</div></ul>'\n\t\t);\n\t});\n\n\tit('handle shuffled array children (moving to the front)', () => {\n\t\tconst App = ({ items }) => (\n\t\t\t<div>\n\t\t\t\t{items.map(key => (\n\t\t\t\t\t<div key={key}>{key}</div>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\n\t\tconst a = ['0', '2', '7', '6', '1', '3', '5', '4'];\n\t\tconst b = ['1', '0', '6', '7', '5', '2', '4', '3'];\n\t\tconst c = ['0', '7', '2', '1', '3', '5', '6', '4'];\n\n\t\trender(<App items={a} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${a.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\n\t\trender(<App items={b} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${b.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\n\t\trender(<App items={c} />, scratch);\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>${c.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t);\n\t});\n\n\t// #2949\n\tit.skip('should not swap unkeyed chlildren', () => {\n\t\tclass X extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.name = props.name;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <p>{this.name}</p>;\n\t\t\t}\n\t\t}\n\n\t\tfunction Foo({ condition }) {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t{condition ? '' : <X name=\"A\" />}\n\t\t\t\t\t{condition ? <X name=\"B\" /> : ''}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.textContent).to.equal('A');\n\n\t\trender(<Foo condition />, scratch);\n\t\texpect(scratch.textContent).to.equal('B');\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.textContent).to.equal('A');\n\t});\n\n\t// #2949\n\tit.skip('should not swap unkeyed chlildren', () => {\n\t\tconst calls = [];\n\t\tclass X extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tcalls.push(props.name);\n\t\t\t\tthis.name = props.name;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <p>{this.name}</p>;\n\t\t\t}\n\t\t}\n\n\t\tfunction Foo({ condition }) {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<X name=\"1\" />\n\t\t\t\t\t{condition ? '' : <X name=\"A\" />}\n\t\t\t\t\t{condition ? <X name=\"B\" /> : ''}\n\t\t\t\t\t<X name=\"C\" />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.textContent).to.equal('1AC');\n\t\texpect(calls).to.deep.equal(['1', 'A', 'C']);\n\n\t\trender(<Foo condition />, scratch);\n\t\texpect(scratch.textContent).to.equal('1BC');\n\t\texpect(calls).to.deep.equal(['1', 'A', 'C', 'B']);\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.textContent).to.equal('1AC');\n\t\texpect(calls).to.deep.equal(['1', 'A', 'C', 'B', 'A']);\n\t});\n\n\tit('should retain state for inserted children', () => {\n\t\tclass X extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\t\t\t\tthis.name = props.name;\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <p>{this.name}</p>;\n\t\t\t}\n\t\t}\n\n\t\tfunction Foo({ condition }) {\n\t\t\t// We swap the prop from A to B but we don't expect this to\n\t\t\t// reflect in text-content as we are testing whether the\n\t\t\t// state is retained for a skew that matches the original children.\n\t\t\t//\n\t\t\t// We insert <span /> which should amount to a skew of -1 which should\n\t\t\t// make us correctly match the X component.\n\t\t\treturn condition ? (\n\t\t\t\t<div>\n\t\t\t\t\t<span />\n\t\t\t\t\t<X name=\"B\" />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<X name=\"A\" />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.textContent).to.equal('A');\n\n\t\trender(<Foo condition />, scratch);\n\t\texpect(scratch.textContent).to.equal('A');\n\n\t\trender(<Foo />, scratch);\n\t\texpect(scratch.textContent).to.equal('A');\n\t});\n\n\tit('handle shuffled (stress test)', () => {\n\t\tfunction randomize(arr) {\n\t\t\tfor (let i = arr.length - 1; i > 0; i--) {\n\t\t\t\tlet j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t[arr[i], arr[j]] = [arr[j], arr[i]];\n\t\t\t}\n\t\t\treturn arr;\n\t\t}\n\n\t\tconst App = ({ items }) => (\n\t\t\t<div>\n\t\t\t\t{items.map(key => (\n\t\t\t\t\t<div key={key}>{key}</div>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t);\n\n\t\tconst a = Array.from({ length: 8 }).map((_, i) => `${i}`);\n\n\t\tfor (let i = 0; i < 10000; i++) {\n\t\t\tconst aa = randomize(a);\n\t\t\trender(<App items={aa} />, scratch);\n\t\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t\t`<div>${aa.map(n => `<div>${n}</div>`).join('')}</div>`\n\t\t\t);\n\t\t}\n\t});\n\n\tit('should work with document', () => {\n\t\tdocument.textContent = '';\n\t\tconst App = () => (\n\t\t\t<Fragment>\n\t\t\t\t<head>\n\t\t\t\t\t<title>Test</title>\n\t\t\t\t</head>\n\t\t\t\t<body>\n\t\t\t\t\t<p>Test</p>\n\t\t\t\t</body>\n\t\t\t</Fragment>\n\t\t);\n\t\trender(<App />, document);\n\t\texpect(document.documentElement.innerHTML.trim()).to.equal(\n\t\t\t'<head><title>Test</title></head><body><p>Test</p></body>'\n\t\t);\n\t});\n\n\tit('should not remount components when replacing a component with a falsy value in-between', () => {\n\t\tconst actions = [];\n\t\tclass Comp extends Component {\n\t\t\tcomponentDidMount() {\n\t\t\t\tactions.push('mounted ' + this.props.i);\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn <div>Hello</div>;\n\t\t\t}\n\t\t}\n\n\t\tconst App = props => {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t{props.y === '1' ? <Comp i={1} /> : <div />}\n\t\t\t\t\t{false}\n\t\t\t\t\t<Comp i={2} />\n\t\t\t\t\t<Comp i={3} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t};\n\n\t\trender(<App y=\"1\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\n\t\trender(<App y=\"2\" />, scratch);\n\t\texpect(actions).to.deep.equal(['mounted 1', 'mounted 2', 'mounted 3']);\n\t});\n\n\tit('Should render intercepted component', () => {\n\t\tclass Test {\n\t\t\tconstructor(text) {\n\t\t\t\tthis.text = text;\n\t\t\t}\n\t\t}\n\n\t\tconst TestValue = props => {\n\t\t\treturn props.text;\n\t\t};\n\n\t\tObject.defineProperties(Test.prototype, {\n\t\t\tconstructor: { configurable: true, value: undefined },\n\t\t\ttype: { configurable: true, value: TestValue },\n\t\t\tprops: {\n\t\t\t\tconfigurable: true,\n\t\t\t\tget() {\n\t\t\t\t\treturn { text: this.text };\n\t\t\t\t}\n\t\t\t},\n\t\t\t_depth: { configurable: true, value: 1 }\n\t\t});\n\n\t\tconst test = new Test('hello world');\n\n\t\tconst App = () => <Fragment>{test}</Fragment>;\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.innerHTML).to.equal('hello world');\n\t});\n\n\tdescribe('Alternative document', () => {\n\t\tit('Renders in an iframe', () => {\n\t\t\tconst iframe = document.createElement('iframe');\n\t\t\tscratch.appendChild(iframe);\n\n\t\t\tconst rootCreateElementSpy = vi.spyOn(document, 'createElementNS');\n\t\t\tconst iframeCreateElementSpy = vi.spyOn(\n\t\t\t\tiframe.contentDocument,\n\t\t\t\t'createElementNS'\n\t\t\t);\n\n\t\t\tconst iframeBody = iframe.contentDocument.getElementsByTagName('body')[0];\n\n\t\t\trender(<div>Hello world</div>, iframeBody);\n\n\t\t\texpect(iframe.contentDocument.body.innerHTML).to.equal(\n\t\t\t\t'<div>Hello world</div>'\n\t\t\t);\n\t\t\texpect(rootCreateElementSpy).not.toBeCalled();\n\t\t\texpect(iframeCreateElementSpy).toBeCalled();\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/select.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\n\ndescribe('Select', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should set <select> value', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<select value=\"B\">\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option value=\"B\">B</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('B');\n\t});\n\n\tit('should set value with selected', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<select>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option selected value=\"B\">\n\t\t\t\t\t\tB\n\t\t\t\t\t</option>\n\t\t\t\t\t<option value=\"C\">C</option>\n\t\t\t\t</select>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\texpect(scratch.firstChild.value).to.equal('B');\n\t});\n\n\tit('should work with multiple selected', () => {\n\t\tfunction App() {\n\t\t\treturn (\n\t\t\t\t<select multiple>\n\t\t\t\t\t<option value=\"A\">A</option>\n\t\t\t\t\t<option selected value=\"B\">\n\t\t\t\t\t\tB\n\t\t\t\t\t</option>\n\t\t\t\t\t<option selected value=\"C\">\n\t\t\t\t\t\tC\n\t\t\t\t\t</option>\n\t\t\t\t</select>\n\t\t\t);\n\t\t}\n\n\t\trender(<App />, scratch);\n\t\tArray.prototype.slice.call(scratch.firstChild.childNodes).forEach(node => {\n\t\t\tif (node.value === 'B' || node.value === 'C') {\n\t\t\t\texpect(node.selected).to.equal(true);\n\t\t\t}\n\t\t});\n\t\texpect(scratch.firstChild.value).to.equal('B');\n\t});\n});\n"
  },
  {
    "path": "test/browser/spec.test.jsx",
    "content": "import { setupRerender } from 'preact/test-utils';\nimport { createElement, render, Component } from 'preact';\nimport { setupScratch, teardown } from '../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('Component spec', () => {\n\tlet scratch, rerender;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\trerender = setupRerender();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tdescribe('forceUpdate', () => {\n\t\tit('should force a rerender', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet forceUpdate;\n\t\t\tclass ForceUpdateComponent extends Component {\n\t\t\t\tcomponentWillUpdate() {}\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tforceUpdate = () => this.forceUpdate();\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(ForceUpdateComponent.prototype, 'componentWillUpdate');\n\t\t\tvi.spyOn(ForceUpdateComponent.prototype, 'forceUpdate');\n\t\t\trender(<ForceUpdateComponent />, scratch);\n\t\t\texpect(\n\t\t\t\tForceUpdateComponent.prototype.componentWillUpdate\n\t\t\t).not.toHaveBeenCalled();\n\n\t\t\tforceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(\n\t\t\t\tForceUpdateComponent.prototype.componentWillUpdate\n\t\t\t).toHaveBeenCalled();\n\t\t\texpect(ForceUpdateComponent.prototype.forceUpdate).toHaveBeenCalled();\n\t\t});\n\n\t\tit('should add callback to renderCallbacks', () => {\n\t\t\t/** @type {() => void} */\n\t\t\tlet forceUpdate;\n\t\t\tlet callback = vi.fn();\n\t\t\tclass ForceUpdateComponent extends Component {\n\t\t\t\tcomponentDidMount() {\n\t\t\t\t\tforceUpdate = () => this.forceUpdate(callback);\n\t\t\t\t}\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\tvi.spyOn(ForceUpdateComponent.prototype, 'forceUpdate');\n\t\t\trender(<ForceUpdateComponent />, scratch);\n\n\t\t\tforceUpdate();\n\t\t\trerender();\n\n\t\t\texpect(ForceUpdateComponent.prototype.forceUpdate).toHaveBeenCalled();\n\t\t\texpect(ForceUpdateComponent.prototype.forceUpdate).toHaveBeenCalledWith(\n\t\t\t\tcallback\n\t\t\t);\n\t\t\texpect(callback).toHaveBeenCalled();\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/browser/style.test.jsx",
    "content": "import { createElement, render } from 'preact';\nimport { setupScratch, teardown, sortCss } from '../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('style attribute', () => {\n\t/** @type {HTMLElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should apply style as String', () => {\n\t\trender(<div style=\"top: 5px; position: relative;\" />, scratch);\n\t\texpect(scratch.childNodes[0].style.cssText).to.equal(\n\t\t\t'top: 5px; position: relative;'\n\t\t);\n\t});\n\n\tit('should not call CSSStyleDeclaration.setProperty for style strings', () => {\n\t\trender(<div style=\"top: 5px; position: relative;\" />, scratch);\n\t\tvi.spyOn(scratch.firstChild.style, 'setProperty').mockImplementation(\n\t\t\t() => {}\n\t\t);\n\t\trender(<div style=\"top: 10px; position: absolute;\" />, scratch);\n\t\texpect(scratch.firstChild.style.setProperty).not.toHaveBeenCalled();\n\t});\n\n\tit('should properly switch from string styles to object styles and back', () => {\n\t\trender(<div style=\"display: inline;\">test</div>, scratch);\n\n\t\tlet style = scratch.firstChild.style;\n\t\texpect(style.cssText).to.equal('display: inline;');\n\n\t\trender(<div style={{ color: 'red' }} />, scratch);\n\t\texpect(style.cssText).to.equal('color: red;');\n\n\t\trender(<div style=\"color: blue\" />, scratch);\n\t\texpect(style.cssText).to.equal('color: blue;');\n\n\t\trender(<div style={{ color: 'yellow' }} />, scratch);\n\t\texpect(style.cssText).to.equal('color: yellow;');\n\n\t\trender(<div style=\"display: block\" />, scratch);\n\t\texpect(style.cssText).to.equal('display: block;');\n\t});\n\n\tit('should serialize style objects', () => {\n\t\tconst styleObj = {\n\t\t\tcolor: 'rgb(255, 255, 255)',\n\t\t\tbackground: 'rgb(255, 100, 0)',\n\t\t\tbackgroundPosition: '10px 10px',\n\t\t\t'background-size': 'cover',\n\t\t\tgridRowStart: 1,\n\t\t\tpadding: '5px',\n\t\t\ttop: '100px',\n\t\t\tleft: '100%'\n\t\t};\n\n\t\trender(<div style={styleObj}>test</div>, scratch);\n\n\t\tlet style = scratch.firstChild.style;\n\t\texpect(style.color).to.equal('rgb(255, 255, 255)');\n\t\texpect(style.background).to.contain('rgb(255, 100, 0)');\n\t\texpect(style.backgroundPosition).to.equal('10px 10px');\n\t\texpect(style.backgroundSize).to.equal('cover');\n\t\texpect(style.padding).to.equal('5px');\n\t\texpect(style.top).to.equal('100px');\n\t\texpect(style.left).to.equal('100%');\n\n\t\t// Only check for this in browsers that support css grids\n\t\tif (typeof scratch.style.grid == 'string') {\n\t\t\texpect(style.gridRowStart).to.equal('1');\n\t\t}\n\t});\n\n\tit('should support opacity 0', () => {\n\t\trender(<div style={{ opacity: 1 }}>Test</div>, scratch);\n\t\tlet style = scratch.firstChild.style;\n\t\texpect(style).to.have.property('opacity').that.equals('1');\n\n\t\trender(<div style={{ opacity: 0 }}>Test</div>, scratch);\n\t\tstyle = scratch.firstChild.style;\n\t\texpect(style).to.have.property('opacity').that.equals('0');\n\t});\n\n\tit('should support animation-iteration-count as number', () => {\n\t\trender(<div style={{ animationIterationCount: 1 }}>Test</div>, scratch);\n\t\tlet style = scratch.firstChild.style;\n\t\texpect(style).to.have.property('animationIterationCount').that.equals('1');\n\n\t\trender(<div style={{ animationIterationCount: 2.5 }}>Test</div>, scratch);\n\t\tstyle = scratch.firstChild.style;\n\t\texpect(style)\n\t\t\t.to.have.property('animationIterationCount')\n\t\t\t.that.equals('2.5');\n\t});\n\n\tit('should replace previous style objects', () => {\n\t\trender(<div style={{ display: 'inline' }}>test</div>, scratch);\n\n\t\tlet style = scratch.firstChild.style;\n\t\texpect(style.cssText).to.equal('display: inline;');\n\t\texpect(style).to.have.property('display').that.equals('inline');\n\t\texpect(style).to.have.property('color').that.equals('');\n\t\texpect(style.zIndex.toString()).to.equal('');\n\n\t\trender(\n\t\t\t<div style={{ color: 'rgb(0, 255, 255)', zIndex: '3' }}>test</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tstyle = scratch.firstChild.style;\n\t\texpect(style.cssText).to.equal('color: rgb(0, 255, 255); z-index: 3;');\n\t\texpect(style).to.have.property('display').that.equals('');\n\t\texpect(style).to.have.property('color').that.equals('rgb(0, 255, 255)');\n\n\t\t// IE stores numeric z-index values as a number\n\t\texpect(style.zIndex.toString()).to.equal('3');\n\n\t\trender(\n\t\t\t<div style={{ color: 'rgb(0, 255, 255)', display: 'inline' }}>test</div>,\n\t\t\tscratch\n\t\t);\n\n\t\tstyle = scratch.firstChild.style;\n\t\texpect(style.cssText).to.equal('color: rgb(0, 255, 255); display: inline;');\n\t\texpect(style).to.have.property('display').that.equals('inline');\n\t\texpect(style).to.have.property('color').that.equals('rgb(0, 255, 255)');\n\t\texpect(style.zIndex.toString()).to.equal('');\n\t});\n\n\tit('should remove old styles', () => {\n\t\trender(<div style={{ color: 'red' }} />, scratch);\n\t\trender(<div style={{ backgroundColor: 'blue' }} />, scratch);\n\t\texpect(scratch.firstChild.style.color).to.equal('');\n\t\texpect(scratch.firstChild.style.backgroundColor).to.equal('blue');\n\t});\n\n\t// Issue #1850\n\tit('should remove empty styles', () => {\n\t\trender(<div style={{ visibility: 'hidden' }} />, scratch);\n\t\texpect(scratch.firstChild.style.visibility).to.equal('hidden');\n\t\trender(<div style={{ visibility: undefined }} />, scratch);\n\t\texpect(scratch.firstChild.style.visibility).to.equal('');\n\t});\n\n\t// Skip test if the currently running browser doesn't support CSS Custom Properties\n\tif (window.CSS && CSS.supports('color', 'var(--fake-var)')) {\n\t\tit('should support css custom properties', () => {\n\t\t\trender(\n\t\t\t\t<div style={{ '--foo': 'red', color: 'var(--foo)' }}>test</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(sortCss(scratch.firstChild.style.cssText)).to.equal(\n\t\t\t\t'--foo: red; color: var(--foo);'\n\t\t\t);\n\t\t\texpect(window.getComputedStyle(scratch.firstChild).color).to.equal(\n\t\t\t\t'rgb(255, 0, 0)'\n\t\t\t);\n\t\t});\n\n\t\tit('should not add \"px\" suffix for custom properties', () => {\n\t\t\trender(\n\t\t\t\t<div style={{ '--foo': '100px', width: 'var(--foo)' }}>test</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(sortCss(scratch.firstChild.style.cssText)).to.equal(\n\t\t\t\t'--foo: 100px; width: var(--foo);'\n\t\t\t);\n\t\t});\n\n\t\tit('css vars should not be transformed into dash-separated', () => {\n\t\t\trender(\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t'--fooBar': 1,\n\t\t\t\t\t\t'--foo-baz': 2,\n\t\t\t\t\t\topacity: 'var(--fooBar)',\n\t\t\t\t\t\tzIndex: 'var(--foo-baz)'\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\ttest\n\t\t\t\t</div>,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(sortCss(scratch.firstChild.style.cssText)).to.equal(\n\t\t\t\t'--foo-baz: 2; --fooBar: 1; opacity: var(--fooBar); z-index: var(--foo-baz);'\n\t\t\t);\n\t\t});\n\n\t\tit('should call CSSStyleDeclaration.setProperty for css vars', () => {\n\t\t\trender(<div style={{ padding: '10px' }} />, scratch);\n\t\t\tvi.spyOn(scratch.firstChild.style, 'setProperty').mockImplementation(\n\t\t\t\t() => {}\n\t\t\t);\n\t\t\trender(\n\t\t\t\t<div style={{ '--foo': '10px', padding: 'var(--foo)' }} />,\n\t\t\t\tscratch\n\t\t\t);\n\t\t\texpect(scratch.firstChild.style.setProperty).toHaveBeenCalledWith(\n\t\t\t\t'--foo',\n\t\t\t\t'10px'\n\t\t\t);\n\t\t});\n\n\t\tit('should clear css properties when passed an empty string, null, or undefined', () => {\n\t\t\tconst red = 'rgb(255, 0, 0)';\n\t\t\tconst blue = 'rgb(0, 0, 255)';\n\t\t\tconst green = 'rgb(0, 128, 0)';\n\t\t\tconst yellow = 'rgb(255, 255, 0)';\n\t\t\tconst violet = 'rgb(238, 130, 238)';\n\n\t\t\tfunction App({ color }) {\n\t\t\t\treturn (\n\t\t\t\t\t<div style={{ '--color': color }}>\n\t\t\t\t\t\t<span style={{ color: 'var(--color, red)' }}>Hello World!</span>\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst getDiv = () => /** @type {HTMLDivElement} */ (scratch.firstChild);\n\t\t\tconst getSpan = () =>\n\t\t\t\t/** @type {HTMLSpanElement} */ (scratch.firstChild.firstChild);\n\t\t\tconst getCSSVariableValue = () =>\n\t\t\t\tgetDiv().style.getPropertyValue('--color');\n\t\t\tconst getTextColor = () => window.getComputedStyle(getSpan()).color;\n\n\t\t\trender(<App color=\"blue\" />, scratch);\n\t\t\texpect(getCSSVariableValue()).to.equal('blue');\n\t\t\texpect(getTextColor()).to.equal(blue);\n\n\t\t\trender(<App color=\"\" />, scratch);\n\t\t\texpect(getCSSVariableValue(), 'empty string').to.equal('');\n\t\t\texpect(getTextColor(), 'empty string').to.equal(red);\n\n\t\t\trender(<App color=\"green\" />, scratch);\n\t\t\texpect(getCSSVariableValue()).to.equal('green');\n\t\t\texpect(getTextColor()).to.equal(green);\n\n\t\t\trender(<App color={undefined} />, scratch);\n\t\t\texpect(getCSSVariableValue(), 'undefined').to.equal('');\n\t\t\texpect(getTextColor(), 'undefined').to.equal(red);\n\n\t\t\trender(<App color=\"yellow\" />, scratch);\n\t\t\texpect(getCSSVariableValue()).to.equal('yellow');\n\t\t\texpect(getTextColor()).to.equal(yellow);\n\n\t\t\trender(<App color={null} />, scratch);\n\t\t\texpect(getCSSVariableValue(), 'null').to.equal('');\n\t\t\texpect(getTextColor(), 'null').to.equal(red);\n\n\t\t\trender(<App color=\"violet\" />, scratch);\n\t\t\texpect(getCSSVariableValue()).to.equal('violet');\n\t\t\texpect(getTextColor()).to.equal(violet);\n\t\t});\n\t}\n});\n"
  },
  {
    "path": "test/browser/svg.test.jsx",
    "content": "import { createElement, Component, render } from 'preact';\nimport { setupRerender } from 'preact/test-utils';\nimport { setupScratch, teardown, sortAttributes } from '../_util/helpers';\nimport { vi } from 'vitest';\n\ndescribe('svg', () => {\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('should render SVG to string', () => {\n\t\trender(\n\t\t\t<svg viewBox=\"0 0 360 360\">\n\t\t\t\t<path\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t\td=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\"\n\t\t\t\t/>\n\t\t\t</svg>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet html = sortAttributes(\n\t\t\tString(scratch.innerHTML).replace(\n\t\t\t\t' xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t\t''\n\t\t\t)\n\t\t);\n\t\texpect(html).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t`\n\t\t\t<svg viewBox=\"0 0 360 360\">\n\t\t\t\t<path d=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\" fill=\"black\" stroke=\"white\"></path>\n\t\t\t</svg>\n\t\t`.replace(/[\\n\\t]+/g, '')\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should support svg xlink:href attribute', () => {\n\t\trender(\n\t\t\tcreateElement('svg', {}, createElement('use', { 'xlink:href': '#foo' })),\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.innerHTML).to.contain(` href=\"#foo\"`);\n\t});\n\n\tit('should support svg attributes', () => {\n\t\tconst Demo = ({ url }) => (\n\t\t\t<svg viewBox=\"0 0 360 360\" xlinkHref={url}>\n\t\t\t\t<path\n\t\t\t\t\td=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t);\n\t\trender(<Demo url=\"www.preact.com\" />, scratch);\n\n\t\tlet html = String(scratch.innerHTML).replace(\n\t\t\t' xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t''\n\t\t);\n\t\thtml = sortAttributes(\n\t\t\thtml.replace(' xmlns:xlink=\"http://www.w3.org/1999/xlink\"', '')\n\t\t);\n\t\texpect(html).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t`\n\t\t\t<svg viewBox=\"0 0 360 360\" href=\"www.preact.com\">\n\t\t\t\t<path d=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\" fill=\"black\" stroke=\"white\"></path>\n\t\t\t</svg>\n\t\t`.replace(/[\\n\\t]+/g, '')\n\t\t\t)\n\t\t);\n\t\trender(<Demo />, scratch);\n\n\t\thtml = String(scratch.innerHTML).replace(\n\t\t\t' xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t''\n\t\t);\n\t\thtml = sortAttributes(\n\t\t\thtml.replace(' xmlns:xlink=\"http://www.w3.org/1999/xlink\"', '')\n\t\t);\n\t\texpect(html).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t`\n\t\t\t<svg viewBox=\"0 0 360 360\">\n\t\t\t\t<path d=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\" fill=\"black\" stroke=\"white\"></path>\n\t\t\t</svg>\n\t\t`.replace(/[\\n\\t]+/g, '')\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should render SVG to DOM', () => {\n\t\tconst Demo = () => (\n\t\t\t<svg viewBox=\"0 0 360 360\">\n\t\t\t\t<path\n\t\t\t\t\td=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t);\n\t\trender(<Demo />, scratch);\n\n\t\tlet html = sortAttributes(\n\t\t\tString(scratch.innerHTML).replace(\n\t\t\t\t' xmlns=\"http://www.w3.org/2000/svg\"',\n\t\t\t\t''\n\t\t\t)\n\t\t);\n\t\texpect(html).to.equal(\n\t\t\tsortAttributes(\n\t\t\t\t'<svg viewBox=\"0 0 360 360\"><path stroke=\"white\" fill=\"black\" d=\"M 347.1 357.9 L 183.3 256.5 L 13 357.9 V 1.7 h 334.1 v 356.2 Z M 58.5 47.2 v 231.4 l 124.8 -74.1 l 118.3 72.8 V 47.2 H 58.5 Z\"></path></svg>'\n\t\t\t)\n\t\t);\n\t});\n\n\tit('should render with the correct namespace URI', () => {\n\t\trender(<svg />, scratch);\n\n\t\tlet namespace = scratch.querySelector('svg').namespaceURI;\n\n\t\texpect(namespace).to.equal('http://www.w3.org/2000/svg');\n\t});\n\n\tit('should render children with the correct namespace URI', () => {\n\t\trender(\n\t\t\t<svg>\n\t\t\t\t<text />\n\t\t\t</svg>,\n\t\t\tscratch\n\t\t);\n\n\t\tlet namespace = scratch.querySelector('text').namespaceURI;\n\n\t\texpect(namespace).to.equal('http://www.w3.org/2000/svg');\n\t});\n\n\tit('should inherit correct namespace URI from parent', () => {\n\t\tconst svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n\t\tscratch.appendChild(svg);\n\n\t\trender(<text />, scratch.firstChild);\n\n\t\tlet namespace = scratch.querySelector('text').namespaceURI;\n\n\t\texpect(namespace).to.equal('http://www.w3.org/2000/svg');\n\t});\n\n\tit('should inherit correct namespace URI from parent upon updating', () => {\n\t\tsetupRerender();\n\n\t\tconst svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n\t\tscratch.appendChild(svg);\n\n\t\tclass App extends Component {\n\t\t\tstate = { show: true };\n\t\t\tcomponentDidMount() {\n\t\t\t\t// eslint-disable-next-line\n\t\t\t\tthis.setState({ show: false }, () => {\n\t\t\t\t\texpect(scratch.querySelector('circle').namespaceURI).to.equal(\n\t\t\t\t\t\t'http://www.w3.org/2000/svg'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}\n\t\t\trender() {\n\t\t\t\treturn this.state.show ? <text /> : <circle />;\n\t\t\t}\n\t\t}\n\n\t\trender(<App />, scratch.firstChild);\n\t});\n\n\tit('should use attributes for className', () => {\n\t\tconst Demo = ({ c }) => (\n\t\t\t<svg viewBox=\"0 0 360 360\" {...(c ? { class: 'foo_' + c } : {})}>\n\t\t\t\t<path\n\t\t\t\t\tclass={c && 'bar_' + c}\n\t\t\t\t\tstroke=\"white\"\n\t\t\t\t\tfill=\"black\"\n\t\t\t\t\td=\"M347.1 357.9L183.3 256.5 13 357.9V1.7h334.1v356.2zM58.5 47.2v231.4l124.8-74.1 118.3 72.8V47.2H58.5z\"\n\t\t\t\t/>\n\t\t\t</svg>\n\t\t);\n\t\trender(<Demo c=\"1\" />, scratch);\n\t\tlet root = scratch.firstChild;\n\t\tvi.spyOn(root, 'removeAttribute');\n\t\trender(<Demo />, scratch);\n\t\texpect(root.removeAttribute).toHaveBeenCalledTimes(1);\n\t\texpect(root.removeAttribute).toHaveBeenCalledWith('class');\n\n\t\troot.removeAttribute.mockRestore();\n\n\t\trender(<div />, scratch);\n\t\trender(<Demo />, scratch);\n\t\troot = scratch.firstChild;\n\t\tvi.spyOn(root, 'setAttribute');\n\t\trender(<Demo c=\"2\" />, scratch);\n\t\texpect(root.setAttribute).toHaveBeenCalledTimes(1);\n\t\texpect(root.setAttribute).toHaveBeenCalledWith('class', 'foo_2');\n\n\t\troot.setAttribute.mockRestore();\n\t});\n\n\tit('should still support class attribute', () => {\n\t\trender(<svg viewBox=\"0 0 1 1\" class=\"foo bar\" />, scratch);\n\n\t\texpect(scratch.innerHTML).to.contain(` class=\"foo bar\"`);\n\t});\n\n\tit('should still support className attribute', () => {\n\t\trender(<svg viewBox=\"0 0 1 1\" className=\"foo bar\" />, scratch);\n\n\t\texpect(scratch.innerHTML).to.contain(` class=\"foo bar\"`);\n\t});\n\n\tit('should switch back to HTML for <foreignObject>', () => {\n\t\trender(\n\t\t\t<svg>\n\t\t\t\t<g>\n\t\t\t\t\t<foreignObject>\n\t\t\t\t\t\t<a href=\"#foo\">test</a>\n\t\t\t\t\t</foreignObject>\n\t\t\t\t</g>\n\t\t\t</svg>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.getElementsByTagName('a'))\n\t\t\t.to.have.property('0')\n\t\t\t.that.is.a('HTMLAnchorElement');\n\t});\n\n\tit('should render foreignObject as an svg element', () => {\n\t\trender(\n\t\t\t<svg>\n\t\t\t\t<g>\n\t\t\t\t\t<foreignObject>\n\t\t\t\t\t\t<a href=\"#foo\">test</a>\n\t\t\t\t\t</foreignObject>\n\t\t\t\t</g>\n\t\t\t</svg>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.querySelector('foreignObject').localName).to.equal(\n\t\t\t'foreignObject'\n\t\t);\n\t});\n\n\tit('should transition from DOM to SVG and back', () => {\n\t\trender(\n\t\t\t<div>\n\t\t\t\t<svg\n\t\t\t\t\tid=\"svg1923\"\n\t\t\t\t\twidth=\"700\"\n\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\theight=\"700\"\n\t\t\t\t>\n\t\t\t\t\t<circle cy=\"333\" cx=\"333\" r=\"333\" />\n\t\t\t\t\t<circle cy=\"333\" cx=\"333\" r=\"333\" fill=\"#fede58\" />\n\t\t\t\t</svg>\n\t\t\t</div>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(scratch.firstChild).to.be.an('HTMLDivElement');\n\t\texpect(scratch.firstChild.firstChild).to.be.an('SVGSVGElement');\n\t});\n});\n"
  },
  {
    "path": "test/browser/toChildArray.test.jsx",
    "content": "import { createElement, render, toChildArray } from 'preact';\nimport {\n\tsetupScratch,\n\tteardown,\n\tgetMixedArray,\n\tmixedArrayHTML\n} from '../_util/helpers';\n\ndescribe('toChildArray', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tlet children;\n\n\tlet Foo = props => {\n\t\tchildren = toChildArray(props.children);\n\t\treturn <div>{children}</div>;\n\t};\n\n\tlet Bar = () => <span>Bar</span>;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t\tchildren = undefined;\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t});\n\n\tit('returns an empty array with no child', () => {\n\t\trender(<Foo />, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(0);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('returns an empty array with null as a child', () => {\n\t\trender(<Foo>{null}</Foo>, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(0);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('returns an empty array with false as a child', () => {\n\t\trender(<Foo>{false}</Foo>, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(0);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('returns an empty array with true as a child', () => {\n\t\trender(<Foo>{true}</Foo>, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(0);\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('should skip a function child', () => {\n\t\tconst child = num => num.toFixed(2);\n\t\trender(<Foo>{child}</Foo>, scratch);\n\t\texpect(children).to.be.an('array');\n\t\texpect(scratch.innerHTML).to.equal('<div></div>');\n\t});\n\n\tit('returns an array containing a VNode with a text child', () => {\n\t\trender(<Foo>text</Foo>, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(1);\n\t\texpect(children[0]).to.equal('text');\n\t\texpect(scratch.innerHTML).to.equal('<div>text</div>');\n\t});\n\n\tit('returns an array containing a VNode with a number child', () => {\n\t\trender(<Foo>{1}</Foo>, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(1);\n\t\texpect(children[0]).to.equal(1);\n\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\t});\n\n\tit('returns an array containing a VNode with a DOM node child', () => {\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<span />\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(1);\n\t\texpect(children[0].type).to.equal('span');\n\t\texpect(scratch.innerHTML).to.equal('<div><span></span></div>');\n\t});\n\n\tit('returns an array containing a VNode with a Component child', () => {\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t<Bar />\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(1);\n\t\texpect(children[0].type).to.equal(Bar);\n\t\texpect(scratch.innerHTML).to.equal('<div><span>Bar</span></div>');\n\t});\n\n\tit('returns an array with multiple children', () => {\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t0<span />\n\t\t\t\t<input />\n\t\t\t\t<div />1\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children[0]).to.equal('0');\n\t\texpect(children[1].type).to.equal('span');\n\t\texpect(children[2].type).to.equal('input');\n\t\texpect(children[3].type).to.equal('div');\n\t\texpect(children[4]).to.equal('1');\n\t\texpect(scratch.innerHTML).to.equal(\n\t\t\t`<div>0<span></span><input><div></div>1</div>`\n\t\t);\n\t});\n\n\tit('returns an array with non-renderables removed with a mixed array as children', () => {\n\t\tconst mixedArray = getMixedArray();\n\t\trender(<Foo>{mixedArray}</Foo>, scratch);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(children).to.have.lengthOf(8); // Length of flattened mixedArray with non-renderables removed\n\t\texpect(scratch.innerHTML).to.equal(`<div>${mixedArrayHTML}</div>`);\n\n\t\tfunction filterAndReduceChildren(acc, child) {\n\t\t\tif (Array.isArray(child)) {\n\t\t\t\treturn child.reduce(filterAndReduceChildren, acc);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tchild != null &&\n\t\t\t\ttypeof child != 'boolean' &&\n\t\t\t\ttypeof child != 'function'\n\t\t\t) {\n\t\t\t\tacc.push(child);\n\t\t\t}\n\n\t\t\treturn acc;\n\t\t}\n\n\t\tlet renderableArray = filterAndReduceChildren([], mixedArray);\n\n\t\texpect(children).to.have.lengthOf(renderableArray.length);\n\n\t\tfor (let i = 0; i < renderableArray.length; i++) {\n\t\t\tlet originalChild = renderableArray[i];\n\t\t\tlet actualChild = children[i];\n\n\t\t\tif (\n\t\t\t\ttypeof originalChild == 'string' ||\n\t\t\t\ttypeof originalChild == 'number'\n\t\t\t) {\n\t\t\t\texpect(actualChild).to.equal(originalChild);\n\t\t\t} else {\n\t\t\t\texpect(actualChild.type).to.equal(originalChild.type);\n\t\t\t}\n\t\t}\n\t});\n\n\tit('flattens sibling and nested arrays', () => {\n\t\tconst list1 = [0, 1];\n\t\tconst list2 = [2, 3];\n\t\tconst list3 = [4, 5];\n\t\tconst list4 = [6, 7];\n\t\tconst list5 = [8, 9];\n\n\t\tconst flatList = [...list1, ...list2, ...list3, ...list4, ...list5];\n\n\t\trender(\n\t\t\t<Foo>\n\t\t\t\t{[list1, list2]}\n\t\t\t\t{[list3, list4]}\n\t\t\t\t{list5}\n\t\t\t</Foo>,\n\t\t\tscratch\n\t\t);\n\n\t\texpect(children).to.be.an('array');\n\t\texpect(scratch.innerHTML).to.equal('<div>0123456789</div>');\n\n\t\tfor (let i = 0; i < flatList.length; i++) {\n\t\t\texpect(children[i]).to.equal(flatList[i]);\n\t\t}\n\t});\n});\n"
  },
  {
    "path": "test/fixtures/preact.js",
    "content": "!(function () {\n\t'use strict';\n\tfunction h(nodeName, attributes) {\n\t\tvar lastSimple,\n\t\t\tchild,\n\t\t\tsimple,\n\t\t\ti,\n\t\t\tchildren = EMPTY_CHILDREN;\n\t\tfor (i = arguments.length; i-- > 2; ) stack.push(arguments[i]);\n\t\tif (attributes && null != attributes.children) {\n\t\t\tif (!stack.length) stack.push(attributes.children);\n\t\t\tdelete attributes.children;\n\t\t}\n\t\twhile (stack.length)\n\t\t\tif ((child = stack.pop()) && void 0 !== child.pop)\n\t\t\t\tfor (i = child.length; i--; ) stack.push(child[i]);\n\t\t\telse {\n\t\t\t\tif ('boolean' == typeof child) child = null;\n\t\t\t\tif ((simple = 'function' != typeof nodeName))\n\t\t\t\t\tif (null == child) child = '';\n\t\t\t\t\telse if ('number' == typeof child) child = String(child);\n\t\t\t\t\telse if ('string' != typeof child) simple = !1;\n\t\t\t\tif (simple && lastSimple) children[children.length - 1] += child;\n\t\t\t\telse if (children === EMPTY_CHILDREN) children = [child];\n\t\t\t\telse children.push(child);\n\t\t\t\tlastSimple = simple;\n\t\t\t}\n\t\tvar p = new VNode();\n\t\tp.nodeName = nodeName;\n\t\tp.children = children;\n\t\tp.attributes = null == attributes ? void 0 : attributes;\n\t\tp.key = null == attributes ? void 0 : attributes.key;\n\t\tif (void 0 !== options.vnode) options.vnode(p);\n\t\treturn p;\n\t}\n\tfunction extend(obj, props) {\n\t\tfor (var i in props) obj[i] = props[i];\n\t\treturn obj;\n\t}\n\tfunction applyRef(ref, value) {\n\t\tif ('function' == typeof ref) ref(value);\n\t\telse if (null != ref) ref.current = value;\n\t}\n\tfunction cloneElement(vnode, props) {\n\t\treturn h(\n\t\t\tvnode.nodeName,\n\t\t\textend(extend({}, vnode.attributes), props),\n\t\t\targuments.length > 2 ? [].slice.call(arguments, 2) : vnode.children\n\t\t);\n\t}\n\tfunction enqueueRender(component) {\n\t\tif (!component.__d && (component.__d = !0) && 1 == items.push(component))\n\t\t\t(options.debounceRendering || defer)(rerender);\n\t}\n\tfunction rerender() {\n\t\tvar p;\n\t\twhile ((p = items.pop())) if (p.__d) renderComponent(p);\n\t}\n\tfunction isSameNodeType(node, vnode, hydrating) {\n\t\tif ('string' == typeof vnode || 'number' == typeof vnode)\n\t\t\treturn void 0 !== node.splitText;\n\t\tif ('string' == typeof vnode.nodeName)\n\t\t\treturn !node._componentConstructor && isNamedNode(node, vnode.nodeName);\n\t\telse return hydrating || node._componentConstructor === vnode.nodeName;\n\t}\n\tfunction isNamedNode(node, nodeName) {\n\t\treturn (\n\t\t\tnode.__n === nodeName ||\n\t\t\tnode.nodeName.toLowerCase() === nodeName.toLowerCase()\n\t\t);\n\t}\n\tfunction getNodeProps(vnode) {\n\t\tvar props = extend({}, vnode.attributes);\n\t\tprops.children = vnode.children;\n\t\tvar defaultProps = vnode.nodeName.defaultProps;\n\t\tif (void 0 !== defaultProps)\n\t\t\tfor (var i in defaultProps)\n\t\t\t\tif (void 0 === props[i]) props[i] = defaultProps[i];\n\t\treturn props;\n\t}\n\tfunction createNode(nodeName, isSvg) {\n\t\tvar node = isSvg\n\t\t\t? document.createElementNS('http://www.w3.org/2000/svg', nodeName)\n\t\t\t: document.createElement(nodeName);\n\t\tnode.__n = nodeName;\n\t\treturn node;\n\t}\n\tfunction removeNode(node) {\n\t\tvar parentNode = node.parentNode;\n\t\tif (parentNode) parentNode.removeChild(node);\n\t}\n\tfunction setAccessor(node, name, old, value, isSvg) {\n\t\tif ('className' === name) name = 'class';\n\t\tif ('key' === name);\n\t\telse if ('ref' === name) {\n\t\t\tapplyRef(old, null);\n\t\t\tapplyRef(value, node);\n\t\t} else if ('class' === name && !isSvg) node.className = value || '';\n\t\telse if ('style' === name) {\n\t\t\tif (!value || 'string' == typeof value || 'string' == typeof old)\n\t\t\t\tnode.style.cssText = value || '';\n\t\t\tif (value && 'object' == typeof value) {\n\t\t\t\tif ('string' != typeof old)\n\t\t\t\t\tfor (var i in old) if (!(i in value)) node.style[i] = '';\n\t\t\t\tfor (var i in value)\n\t\t\t\t\tnode.style[i] =\n\t\t\t\t\t\t'number' == typeof value[i] && !1 === IS_NON_DIMENSIONAL.test(i)\n\t\t\t\t\t\t\t? value[i] + 'px'\n\t\t\t\t\t\t\t: value[i];\n\t\t\t}\n\t\t} else if ('dangerouslySetInnerHTML' === name) {\n\t\t\tif (value) node.innerHTML = value.__html || '';\n\t\t} else if ('o' == name[0] && 'n' == name[1]) {\n\t\t\tvar useCapture = name !== (name = name.replace(/Capture$/, ''));\n\t\t\tname = name.toLowerCase().substring(2);\n\t\t\tif (value) {\n\t\t\t\tif (!old) node.addEventListener(name, eventProxy, useCapture);\n\t\t\t} else node.removeEventListener(name, eventProxy, useCapture);\n\t\t\t(node.__l || (node.__l = {}))[name] = value;\n\t\t} else if ('list' !== name && 'type' !== name && !isSvg && name in node) {\n\t\t\ttry {\n\t\t\t\tnode[name] = null == value ? '' : value;\n\t\t\t} catch (e) {}\n\t\t\tif ((null == value || !1 === value) && 'spellcheck' != name)\n\t\t\t\tnode.removeAttribute(name);\n\t\t} else {\n\t\t\tvar ns = isSvg && name !== (name = name.replace(/^xlink:?/, ''));\n\t\t\tif (null == value || !1 === value)\n\t\t\t\tif (ns)\n\t\t\t\t\tnode.removeAttributeNS(\n\t\t\t\t\t\t'http://www.w3.org/1999/xlink',\n\t\t\t\t\t\tname.toLowerCase()\n\t\t\t\t\t);\n\t\t\t\telse node.removeAttribute(name);\n\t\t\telse if ('function' != typeof value)\n\t\t\t\tif (ns)\n\t\t\t\t\tnode.setAttributeNS(\n\t\t\t\t\t\t'http://www.w3.org/1999/xlink',\n\t\t\t\t\t\tname.toLowerCase(),\n\t\t\t\t\t\tvalue\n\t\t\t\t\t);\n\t\t\t\telse node.setAttribute(name, value);\n\t\t}\n\t}\n\tfunction eventProxy(e) {\n\t\treturn this.__l[e.type]((options.event && options.event(e)) || e);\n\t}\n\tfunction flushMounts() {\n\t\tvar c;\n\t\twhile ((c = mounts.pop())) {\n\t\t\tif (options.afterMount) options.afterMount(c);\n\t\t\tif (c.componentDidMount) c.componentDidMount();\n\t\t}\n\t}\n\tfunction diff(dom, vnode, context, mountAll, parent, componentRoot) {\n\t\tif (!diffLevel++) {\n\t\t\tisSvgMode = null != parent && void 0 !== parent.ownerSVGElement;\n\t\t\thydrating = null != dom && !('__preactattr_' in dom);\n\t\t}\n\t\tvar ret = idiff(dom, vnode, context, mountAll, componentRoot);\n\t\tif (parent && ret.parentNode !== parent) parent.appendChild(ret);\n\t\tif (!--diffLevel) {\n\t\t\thydrating = !1;\n\t\t\tif (!componentRoot) flushMounts();\n\t\t}\n\t\treturn ret;\n\t}\n\tfunction idiff(dom, vnode, context, mountAll, componentRoot) {\n\t\tvar out = dom,\n\t\t\tprevSvgMode = isSvgMode;\n\t\tif (null == vnode || 'boolean' == typeof vnode) vnode = '';\n\t\tif ('string' == typeof vnode || 'number' == typeof vnode) {\n\t\t\tif (\n\t\t\t\tdom &&\n\t\t\t\tvoid 0 !== dom.splitText &&\n\t\t\t\tdom.parentNode &&\n\t\t\t\t(!dom._component || componentRoot)\n\t\t\t) {\n\t\t\t\tif (dom.nodeValue != vnode) dom.nodeValue = vnode;\n\t\t\t} else {\n\t\t\t\tout = document.createTextNode(vnode);\n\t\t\t\tif (dom) {\n\t\t\t\t\tif (dom.parentNode) dom.parentNode.replaceChild(out, dom);\n\t\t\t\t\trecollectNodeTree(dom, !0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tout.__preactattr_ = !0;\n\t\t\treturn out;\n\t\t}\n\t\tvar vnodeName = vnode.nodeName;\n\t\tif ('function' == typeof vnodeName)\n\t\t\treturn buildComponentFromVNode(dom, vnode, context, mountAll);\n\t\tisSvgMode =\n\t\t\t'svg' === vnodeName ? !0 : 'foreignObject' === vnodeName ? !1 : isSvgMode;\n\t\tvnodeName = String(vnodeName);\n\t\tif (!dom || !isNamedNode(dom, vnodeName)) {\n\t\t\tout = createNode(vnodeName, isSvgMode);\n\t\t\tif (dom) {\n\t\t\t\twhile (dom.firstChild) out.appendChild(dom.firstChild);\n\t\t\t\tif (dom.parentNode) dom.parentNode.replaceChild(out, dom);\n\t\t\t\trecollectNodeTree(dom, !0);\n\t\t\t}\n\t\t}\n\t\tvar fc = out.firstChild,\n\t\t\tprops = out.__preactattr_,\n\t\t\tvchildren = vnode.children;\n\t\tif (null == props) {\n\t\t\tprops = out.__preactattr_ = {};\n\t\t\tfor (var a = out.attributes, i = a.length; i--; )\n\t\t\t\tprops[a[i].name] = a[i].value;\n\t\t}\n\t\tif (\n\t\t\t!hydrating &&\n\t\t\tvchildren &&\n\t\t\t1 === vchildren.length &&\n\t\t\t'string' == typeof vchildren[0] &&\n\t\t\tnull != fc &&\n\t\t\tvoid 0 !== fc.splitText &&\n\t\t\tnull == fc.nextSibling\n\t\t) {\n\t\t\tif (fc.nodeValue != vchildren[0]) fc.nodeValue = vchildren[0];\n\t\t} else if ((vchildren && vchildren.length) || null != fc)\n\t\t\tinnerDiffNode(\n\t\t\t\tout,\n\t\t\t\tvchildren,\n\t\t\t\tcontext,\n\t\t\t\tmountAll,\n\t\t\t\thydrating || null != props.dangerouslySetInnerHTML\n\t\t\t);\n\t\tdiffAttributes(out, vnode.attributes, props);\n\t\tisSvgMode = prevSvgMode;\n\t\treturn out;\n\t}\n\tfunction innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {\n\t\tvar j,\n\t\t\tc,\n\t\t\tf,\n\t\t\tvchild,\n\t\t\tchild,\n\t\t\toriginalChildren = dom.childNodes,\n\t\t\tchildren = [],\n\t\t\tkeyed = {},\n\t\t\tkeyedLen = 0,\n\t\t\tmin = 0,\n\t\t\tlen = originalChildren.length,\n\t\t\tchildrenLen = 0,\n\t\t\tvlen = vchildren ? vchildren.length : 0;\n\t\tif (0 !== len)\n\t\t\tfor (var i = 0; i < len; i++) {\n\t\t\t\tvar _child = originalChildren[i],\n\t\t\t\t\tprops = _child.__preactattr_,\n\t\t\t\t\tkey =\n\t\t\t\t\t\tvlen && props\n\t\t\t\t\t\t\t? _child._component\n\t\t\t\t\t\t\t\t? _child._component.__k\n\t\t\t\t\t\t\t\t: props.key\n\t\t\t\t\t\t\t: null;\n\t\t\t\tif (null != key) {\n\t\t\t\t\tkeyedLen++;\n\t\t\t\t\tkeyed[key] = _child;\n\t\t\t\t} else if (\n\t\t\t\t\tprops ||\n\t\t\t\t\t(void 0 !== _child.splitText\n\t\t\t\t\t\t? isHydrating\n\t\t\t\t\t\t\t? _child.nodeValue.trim()\n\t\t\t\t\t\t\t: !0\n\t\t\t\t\t\t: isHydrating)\n\t\t\t\t)\n\t\t\t\t\tchildren[childrenLen++] = _child;\n\t\t\t}\n\t\tif (0 !== vlen)\n\t\t\tfor (var i = 0; i < vlen; i++) {\n\t\t\t\tvchild = vchildren[i];\n\t\t\t\tchild = null;\n\t\t\t\tvar key = vchild.key;\n\t\t\t\tif (null != key) {\n\t\t\t\t\tif (keyedLen && void 0 !== keyed[key]) {\n\t\t\t\t\t\tchild = keyed[key];\n\t\t\t\t\t\tkeyed[key] = void 0;\n\t\t\t\t\t\tkeyedLen--;\n\t\t\t\t\t}\n\t\t\t\t} else if (min < childrenLen)\n\t\t\t\t\tfor (j = min; j < childrenLen; j++)\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tvoid 0 !== children[j] &&\n\t\t\t\t\t\t\tisSameNodeType((c = children[j]), vchild, isHydrating)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tchild = c;\n\t\t\t\t\t\t\tchildren[j] = void 0;\n\t\t\t\t\t\t\tif (j === childrenLen - 1) childrenLen--;\n\t\t\t\t\t\t\tif (j === min) min++;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\tchild = idiff(child, vchild, context, mountAll);\n\t\t\t\tf = originalChildren[i];\n\t\t\t\tif (child && child !== dom && child !== f)\n\t\t\t\t\tif (null == f) dom.appendChild(child);\n\t\t\t\t\telse if (child === f.nextSibling) removeNode(f);\n\t\t\t\t\telse dom.insertBefore(child, f);\n\t\t\t}\n\t\tif (keyedLen)\n\t\t\tfor (var i in keyed)\n\t\t\t\tif (void 0 !== keyed[i]) recollectNodeTree(keyed[i], !1);\n\t\twhile (min <= childrenLen)\n\t\t\tif (void 0 !== (child = children[childrenLen--]))\n\t\t\t\trecollectNodeTree(child, !1);\n\t}\n\tfunction recollectNodeTree(node, unmountOnly) {\n\t\tvar component = node._component;\n\t\tif (component) unmountComponent(component);\n\t\telse {\n\t\t\tif (null != node.__preactattr_) applyRef(node.__preactattr_.ref, null);\n\t\t\tif (!1 === unmountOnly || null == node.__preactattr_) removeNode(node);\n\t\t\tremoveChildren(node);\n\t\t}\n\t}\n\tfunction removeChildren(node) {\n\t\tnode = node.lastChild;\n\t\twhile (node) {\n\t\t\tvar next = node.previousSibling;\n\t\t\trecollectNodeTree(node, !0);\n\t\t\tnode = next;\n\t\t}\n\t}\n\tfunction diffAttributes(dom, attrs, old) {\n\t\tvar name;\n\t\tfor (name in old)\n\t\t\tif ((!attrs || null == attrs[name]) && null != old[name])\n\t\t\t\tsetAccessor(dom, name, old[name], (old[name] = void 0), isSvgMode);\n\t\tfor (name in attrs)\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\t'children' === name ||\n\t\t\t\t\t'innerHTML' === name ||\n\t\t\t\t\t(name in old &&\n\t\t\t\t\t\tattrs[name] ===\n\t\t\t\t\t\t\t('value' === name || 'checked' === name ? dom[name] : old[name]))\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tsetAccessor(dom, name, old[name], (old[name] = attrs[name]), isSvgMode);\n\t}\n\tfunction createComponent(Ctor, props, context) {\n\t\tvar inst,\n\t\t\ti = recyclerComponents.length;\n\t\tif (Ctor.prototype && Ctor.prototype.render) {\n\t\t\tinst = new Ctor(props, context);\n\t\t\tComponent.call(inst, props, context);\n\t\t} else {\n\t\t\tinst = new Component(props, context);\n\t\t\tinst.constructor = Ctor;\n\t\t\tinst.render = doRender;\n\t\t}\n\t\twhile (i--)\n\t\t\tif (recyclerComponents[i].constructor === Ctor) {\n\t\t\t\tinst.__b = recyclerComponents[i].__b;\n\t\t\t\trecyclerComponents.splice(i, 1);\n\t\t\t\treturn inst;\n\t\t\t}\n\t\treturn inst;\n\t}\n\tfunction doRender(props, state, context) {\n\t\treturn this.constructor(props, context);\n\t}\n\tfunction setComponentProps(component, props, renderMode, context, mountAll) {\n\t\tif (!component.__x) {\n\t\t\tcomponent.__x = !0;\n\t\t\tcomponent.__r = props.ref;\n\t\t\tcomponent.__k = props.key;\n\t\t\tdelete props.ref;\n\t\t\tdelete props.key;\n\t\t\tif (void 0 === component.constructor.getDerivedStateFromProps)\n\t\t\t\tif (!component.base || mountAll) {\n\t\t\t\t\tif (component.componentWillMount) component.componentWillMount();\n\t\t\t\t} else if (component.componentWillReceiveProps)\n\t\t\t\t\tcomponent.componentWillReceiveProps(props, context);\n\t\t\tif (context && context !== component.context) {\n\t\t\t\tif (!component.__c) component.__c = component.context;\n\t\t\t\tcomponent.context = context;\n\t\t\t}\n\t\t\tif (!component.__p) component.__p = component.props;\n\t\t\tcomponent.props = props;\n\t\t\tcomponent.__x = !1;\n\t\t\tif (0 !== renderMode)\n\t\t\t\tif (\n\t\t\t\t\t1 === renderMode ||\n\t\t\t\t\t!1 !== options.syncComponentUpdates ||\n\t\t\t\t\t!component.base\n\t\t\t\t)\n\t\t\t\t\trenderComponent(component, 1, mountAll);\n\t\t\t\telse enqueueRender(component);\n\t\t\tapplyRef(component.__r, component);\n\t\t}\n\t}\n\tfunction renderComponent(component, renderMode, mountAll, isChild) {\n\t\tif (!component.__x) {\n\t\t\tvar rendered,\n\t\t\t\tinst,\n\t\t\t\tcbase,\n\t\t\t\tprops = component.props,\n\t\t\t\tstate = component.state,\n\t\t\t\tcontext = component.context,\n\t\t\t\tpreviousProps = component.__p || props,\n\t\t\t\tpreviousState = component.__s || state,\n\t\t\t\tpreviousContext = component.__c || context,\n\t\t\t\tisUpdate = component.base,\n\t\t\t\tnextBase = component.__b,\n\t\t\t\tinitialBase = isUpdate || nextBase,\n\t\t\t\tinitialChildComponent = component._component,\n\t\t\t\tskip = !1,\n\t\t\t\tsnapshot = previousContext;\n\t\t\tif (component.constructor.getDerivedStateFromProps) {\n\t\t\t\tstate = extend(\n\t\t\t\t\textend({}, state),\n\t\t\t\t\tcomponent.constructor.getDerivedStateFromProps(props, state)\n\t\t\t\t);\n\t\t\t\tcomponent.state = state;\n\t\t\t}\n\t\t\tif (isUpdate) {\n\t\t\t\tcomponent.props = previousProps;\n\t\t\t\tcomponent.state = previousState;\n\t\t\t\tcomponent.context = previousContext;\n\t\t\t\tif (\n\t\t\t\t\t2 !== renderMode &&\n\t\t\t\t\tcomponent.shouldComponentUpdate &&\n\t\t\t\t\t!1 === component.shouldComponentUpdate(props, state, context)\n\t\t\t\t)\n\t\t\t\t\tskip = !0;\n\t\t\t\telse if (component.componentWillUpdate)\n\t\t\t\t\tcomponent.componentWillUpdate(props, state, context);\n\t\t\t\tcomponent.props = props;\n\t\t\t\tcomponent.state = state;\n\t\t\t\tcomponent.context = context;\n\t\t\t}\n\t\t\tcomponent.__p = component.__s = component.__c = component.__b = null;\n\t\t\tcomponent.__d = !1;\n\t\t\tif (!skip) {\n\t\t\t\trendered = component.render(props, state, context);\n\t\t\t\tif (component.getChildContext)\n\t\t\t\t\tcontext = extend(extend({}, context), component.getChildContext());\n\t\t\t\tif (isUpdate && component.getSnapshotBeforeUpdate)\n\t\t\t\t\tsnapshot = component.getSnapshotBeforeUpdate(\n\t\t\t\t\t\tpreviousProps,\n\t\t\t\t\t\tpreviousState\n\t\t\t\t\t);\n\t\t\t\tvar toUnmount,\n\t\t\t\t\tbase,\n\t\t\t\t\tchildComponent = rendered && rendered.nodeName;\n\t\t\t\tif ('function' == typeof childComponent) {\n\t\t\t\t\tvar childProps = getNodeProps(rendered);\n\t\t\t\t\tinst = initialChildComponent;\n\t\t\t\t\tif (\n\t\t\t\t\t\tinst &&\n\t\t\t\t\t\tinst.constructor === childComponent &&\n\t\t\t\t\t\tchildProps.key == inst.__k\n\t\t\t\t\t)\n\t\t\t\t\t\tsetComponentProps(inst, childProps, 1, context, !1);\n\t\t\t\t\telse {\n\t\t\t\t\t\ttoUnmount = inst;\n\t\t\t\t\t\tcomponent._component = inst = createComponent(\n\t\t\t\t\t\t\tchildComponent,\n\t\t\t\t\t\t\tchildProps,\n\t\t\t\t\t\t\tcontext\n\t\t\t\t\t\t);\n\t\t\t\t\t\tinst.__b = inst.__b || nextBase;\n\t\t\t\t\t\tinst.__u = component;\n\t\t\t\t\t\tsetComponentProps(inst, childProps, 0, context, !1);\n\t\t\t\t\t\trenderComponent(inst, 1, mountAll, !0);\n\t\t\t\t\t}\n\t\t\t\t\tbase = inst.base;\n\t\t\t\t} else {\n\t\t\t\t\tcbase = initialBase;\n\t\t\t\t\ttoUnmount = initialChildComponent;\n\t\t\t\t\tif (toUnmount) cbase = component._component = null;\n\t\t\t\t\tif (initialBase || 1 === renderMode) {\n\t\t\t\t\t\tif (cbase) cbase._component = null;\n\t\t\t\t\t\tbase = diff(\n\t\t\t\t\t\t\tcbase,\n\t\t\t\t\t\t\trendered,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tmountAll || !isUpdate,\n\t\t\t\t\t\t\tinitialBase && initialBase.parentNode,\n\t\t\t\t\t\t\t!0\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tinitialBase &&\n\t\t\t\t\tbase !== initialBase &&\n\t\t\t\t\tinst !== initialChildComponent\n\t\t\t\t) {\n\t\t\t\t\tvar baseParent = initialBase.parentNode;\n\t\t\t\t\tif (baseParent && base !== baseParent) {\n\t\t\t\t\t\tbaseParent.replaceChild(base, initialBase);\n\t\t\t\t\t\tif (!toUnmount) {\n\t\t\t\t\t\t\tinitialBase._component = null;\n\t\t\t\t\t\t\trecollectNodeTree(initialBase, !1);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (toUnmount) unmountComponent(toUnmount);\n\t\t\t\tcomponent.base = base;\n\t\t\t\tif (base && !isChild) {\n\t\t\t\t\tvar componentRef = component,\n\t\t\t\t\t\tt = component;\n\t\t\t\t\twhile ((t = t.__u)) (componentRef = t).base = base;\n\t\t\t\t\tbase._component = componentRef;\n\t\t\t\t\tbase._componentConstructor = componentRef.constructor;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isUpdate || mountAll) mounts.unshift(component);\n\t\t\telse if (!skip) {\n\t\t\t\tif (component.componentDidUpdate)\n\t\t\t\t\tcomponent.componentDidUpdate(previousProps, previousState, snapshot);\n\t\t\t\tif (options.afterUpdate) options.afterUpdate(component);\n\t\t\t}\n\t\t\twhile (component.__h.length) component.__h.pop().call(component);\n\t\t\tif (!diffLevel && !isChild) flushMounts();\n\t\t}\n\t}\n\tfunction buildComponentFromVNode(dom, vnode, context, mountAll) {\n\t\tvar c = dom && dom._component,\n\t\t\toriginalComponent = c,\n\t\t\toldDom = dom,\n\t\t\tisDirectOwner = c && dom._componentConstructor === vnode.nodeName,\n\t\t\tisOwner = isDirectOwner,\n\t\t\tprops = getNodeProps(vnode);\n\t\twhile (c && !isOwner && (c = c.__u))\n\t\t\tisOwner = c.constructor === vnode.nodeName;\n\t\tif (c && isOwner && (!mountAll || c._component)) {\n\t\t\tsetComponentProps(c, props, 3, context, mountAll);\n\t\t\tdom = c.base;\n\t\t} else {\n\t\t\tif (originalComponent && !isDirectOwner) {\n\t\t\t\tunmountComponent(originalComponent);\n\t\t\t\tdom = oldDom = null;\n\t\t\t}\n\t\t\tc = createComponent(vnode.nodeName, props, context);\n\t\t\tif (dom && !c.__b) {\n\t\t\t\tc.__b = dom;\n\t\t\t\toldDom = null;\n\t\t\t}\n\t\t\tsetComponentProps(c, props, 1, context, mountAll);\n\t\t\tdom = c.base;\n\t\t\tif (oldDom && dom !== oldDom) {\n\t\t\t\toldDom._component = null;\n\t\t\t\trecollectNodeTree(oldDom, !1);\n\t\t\t}\n\t\t}\n\t\treturn dom;\n\t}\n\tfunction unmountComponent(component) {\n\t\tif (options.beforeUnmount) options.beforeUnmount(component);\n\t\tvar base = component.base;\n\t\tcomponent.__x = !0;\n\t\tif (component.componentWillUnmount) component.componentWillUnmount();\n\t\tcomponent.base = null;\n\t\tvar inner = component._component;\n\t\tif (inner) unmountComponent(inner);\n\t\telse if (base) {\n\t\t\tif (base.__preactattr_ && base.__preactattr_.ref)\n\t\t\t\tbase.__preactattr_.ref(null);\n\t\t\tcomponent.__b = base;\n\t\t\tremoveNode(base);\n\t\t\trecyclerComponents.push(component);\n\t\t\tremoveChildren(base);\n\t\t}\n\t\tapplyRef(component.__r, null);\n\t}\n\tfunction Component(props, context) {\n\t\tthis.__d = !0;\n\t\tthis.context = context;\n\t\tthis.props = props;\n\t\tthis.state = this.state || {};\n\t\tthis.__h = [];\n\t}\n\tfunction render(vnode, parent, merge) {\n\t\treturn diff(merge, vnode, {}, !1, parent, !1);\n\t}\n\tfunction createRef() {\n\t\treturn {};\n\t}\n\tvar VNode = function () {};\n\tvar options = {};\n\tvar stack = [];\n\tvar EMPTY_CHILDREN = [];\n\tvar defer =\n\t\t'function' == typeof Promise\n\t\t\t? Promise.resolve().then.bind(Promise.resolve())\n\t\t\t: setTimeout;\n\tvar IS_NON_DIMENSIONAL =\n\t\t/acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;\n\tvar items = [];\n\tvar mounts = [];\n\tvar diffLevel = 0;\n\tvar isSvgMode = !1;\n\tvar hydrating = !1;\n\tvar recyclerComponents = [];\n\textend(Component.prototype, {\n\t\tsetState: function (state, callback) {\n\t\t\tif (!this.__s) this.__s = this.state;\n\t\t\tthis.state = extend(\n\t\t\t\textend({}, this.state),\n\t\t\t\t'function' == typeof state ? state(this.state, this.props) : state\n\t\t\t);\n\t\t\tif (callback) this.__h.push(callback);\n\t\t\tenqueueRender(this);\n\t\t},\n\t\tforceUpdate: function (callback) {\n\t\t\tif (callback) this.__h.push(callback);\n\t\t\trenderComponent(this, 2);\n\t\t},\n\t\trender: function () {}\n\t});\n\tvar preact = {\n\t\th: h,\n\t\tcreateElement: h,\n\t\tcloneElement: cloneElement,\n\t\tcreateRef: createRef,\n\t\tComponent: Component,\n\t\trender: render,\n\t\trerender: rerender,\n\t\toptions: options\n\t};\n\tif ('undefined' != typeof module) module.exports = preact;\n\telse self.preact = preact;\n})();\n//# sourceMappingURL=preact.js.map\n"
  },
  {
    "path": "test/node/index.test.js",
    "content": "import { expect } from 'chai';\nimport * as preact from '../../';\n\ndescribe('build artifact', () => {\n\t// #1075 Check that the build artifact has the correct exports\n\tit('should have exported properties', () => {\n\t\texpect(typeof preact).to.equal('object');\n\t\texpect(preact).to.have.property('createElement');\n\t\texpect(preact).to.have.property('h');\n\t\texpect(preact).to.have.property('Component');\n\t\texpect(preact).to.have.property('render');\n\t\texpect(preact).to.have.property('hydrate');\n\t\t// expect(preact).to.have.property('options');\n\t});\n});\n"
  },
  {
    "path": "test/shared/createContext.test.jsx",
    "content": "import { createElement, createContext } from '../../src/index';\nimport { expect } from 'chai';\n\n/* eslint-env browser */\n\ndescribe('createContext', () => {\n\tit('should return a Provider and a Consumer', () => {\n\t\tconst context = createContext(null);\n\t\texpect(context).to.have.property('Provider');\n\t\texpect(context).to.have.property('Consumer');\n\t});\n\n\tit('should return a valid Provider Component', () => {\n\t\tconst { Provider } = createContext(null);\n\t\tconst contextValue = { value: 'test' };\n\t\tconst children = [<div>child1</div>, <div>child2</div>];\n\n\t\tconst providerComponent = <Provider {...contextValue}>{children}</Provider>;\n\t\t//expect(providerComponent).to.have.property('tag', 'Provider');\n\t\texpect(providerComponent.props.value).to.equal(contextValue.value);\n\t\texpect(providerComponent.props.children).to.equal(children);\n\t});\n});\n"
  },
  {
    "path": "test/shared/createElement.test.jsx",
    "content": "import { createElement } from '../../src/index';\nimport { expect } from 'chai';\n\nconst h = createElement;\n/*eslint-env browser */\n\n// const buildVNode = (nodeName, attributes, children=[]) => ({\n// \tnodeName,\n// \tchildren,\n// \tattributes,\n// \tkey: attributes && attributes.key\n// });\n\ndescribe('createElement(jsx)', () => {\n\tit('should return a VNode', () => {\n\t\tlet r;\n\t\texpect(() => (r = h('foo', null))).not.to.throw();\n\t\texpect(r).to.be.an('object');\n\t\t// expect(r).to.be.an.instanceof(VNode);\n\t\texpect(r).to.have.property('type', 'foo');\n\t\texpect(r).to.have.property('props').that.eql({});\n\t\t// expect(r).to.have.deep.property('props.children').that.eql(null);\n\t});\n\n\tit('should set VNode#type property', () => {\n\t\texpect(<div />).to.have.property('type', 'div');\n\t\tfunction Test() {\n\t\t\treturn <div />;\n\t\t}\n\t\texpect(<Test />).to.have.property('type', Test);\n\t});\n\n\tit('should set VNode.constructor property to prevent json injection', () => {\n\t\tconst vnode = <span />;\n\t\texpect(vnode.constructor).to.equal(undefined);\n\t});\n\n\tit('should set VNode#props property', () => {\n\t\tconst props = {};\n\t\texpect(h('div', props).props).to.deep.equal(props);\n\t});\n\n\tit('should set VNode#key property', () => {\n\t\texpect(<div />).to.have.property('key').that.does.not.exist;\n\t\texpect(<div a=\"a\" />).to.have.property('key').that.does.not.exist;\n\t\texpect(<div key=\"1\" />).to.have.property('key', '1');\n\t});\n\n\tit('should not set VNode#props.key property', () => {\n\t\texpect(<div />).to.not.have.nested.property('props.key');\n\t\texpect(<div key=\"1\" />).to.not.have.nested.property('props.key');\n\t\texpect(<div key={0} />).to.not.have.nested.property('props.key');\n\t\texpect(<div key={''} />).to.not.have.nested.property('props.key');\n\t});\n\n\tit('should set VNode#ref property', () => {\n\t\texpect(<div />).to.have.property('ref').that.does.not.exist;\n\t\texpect(<div a=\"a\" />).to.have.property('ref').that.does.not.exist;\n\t\tconst emptyFunction = () => {};\n\t\texpect(<div ref={emptyFunction} />).to.have.property('ref', emptyFunction);\n\t});\n\n\tit('should not set VNode#props.ref property', () => {\n\t\texpect(<div />).to.not.have.nested.property('props.ref');\n\t\texpect(<div ref={() => {}} />).to.not.have.nested.property('props.ref');\n\t});\n\n\tit('should have ordered VNode properties', () => {\n\t\texpect(Object.keys(<div />).filter(key => !/^_/.test(key))).to.deep.equal([\n\t\t\t'type',\n\t\t\t'props',\n\t\t\t'key',\n\t\t\t'ref',\n\t\t\t'constructor'\n\t\t]);\n\t});\n\n\tit('should preserve raw props', () => {\n\t\tlet props = { foo: 'bar', baz: 10, func: () => {} },\n\t\t\tr = h('foo', props);\n\t\texpect(r).to.be.an('object').with.property('props').that.deep.equals(props);\n\t});\n\n\tit('should support element children', () => {\n\t\tlet kid1 = h('bar', null);\n\t\tlet kid2 = h('baz', null);\n\t\tlet r = h('foo', null, kid1, kid2);\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.deep.property('props.children', [kid1, kid2]);\n\t});\n\n\tit('should support multiple element children, given as arg list', () => {\n\t\tlet kid1 = h('bar', null);\n\t\tlet kid3 = h('test', null);\n\t\tlet kid2 = h('baz', null, kid3);\n\n\t\tlet r = h('foo', null, kid1, kid2);\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.deep.property('props.children', [kid1, kid2]);\n\t});\n\n\tit('should handle multiple element children, given as an array', () => {\n\t\tlet kid1 = h('bar', null);\n\t\tlet kid3 = h('test', null);\n\t\tlet kid2 = h('baz', null, kid3);\n\n\t\tlet r = h('foo', null, [kid1, kid2]);\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.deep.property('props.children', [kid1, kid2]);\n\t});\n\n\tit('should support nested children', () => {\n\t\tconst m = x => {\n\t\t\tconst result = h(x, null);\n\t\t\tdelete result._original;\n\t\t\treturn result;\n\t\t};\n\t\texpect(h('foo', null, m('a'), [m('b'), m('c')], m('d')))\n\t\t\t.to.have.nested.property('props.children')\n\t\t\t.that.eql([m('a'), [m('b'), m('c')], m('d')]);\n\n\t\texpect(h('foo', null, [m('a'), [m('b'), m('c')], m('d')]))\n\t\t\t.to.have.nested.property('props.children')\n\t\t\t.that.eql([m('a'), [m('b'), m('c')], m('d')]);\n\n\t\texpect(h('foo', { children: [m('a'), [m('b'), m('c')], m('d')] }))\n\t\t\t.to.have.nested.property('props.children')\n\t\t\t.that.eql([m('a'), [m('b'), m('c')], m('d')]);\n\n\t\texpect(h('foo', { children: [[m('a'), [m('b'), m('c')], m('d')]] }))\n\t\t\t.to.have.nested.property('props.children')\n\t\t\t.that.eql([[m('a'), [m('b'), m('c')], m('d')]]);\n\n\t\texpect(h('foo', { children: m('a') }))\n\t\t\t.to.have.nested.property('props.children')\n\t\t\t.that.eql(m('a'));\n\n\t\texpect(h('foo', { children: 'a' }))\n\t\t\t.to.have.nested.property('props.children')\n\t\t\t.that.eql('a');\n\t});\n\n\tit('should support text children', () => {\n\t\tlet r = h('foo', null, 'textstuff');\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.property('props.children')\n\t\t\t.that.equals('textstuff');\n\t});\n\n\tit('should override children if null is provided as an argument', () => {\n\t\tlet r = h('foo', { foo: 'bar', children: 'baz' }, null);\n\n\t\texpect(r).to.be.an('object').to.deep.nested.include({\n\t\t\t'props.foo': 'bar',\n\t\t\t'props.children': null\n\t\t});\n\t});\n\n\tit('should NOT set children prop when unspecified', () => {\n\t\tlet r = h('foo', { foo: 'bar' });\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.to.have.nested.property('props.foo')\n\t\t\t.not.to.have.nested.property('props.children');\n\t});\n\n\tit('should NOT merge adjacent text children', () => {\n\t\tconst bar = h('bar', null);\n\t\tconst barClone = h('bar', null);\n\t\tconst baz = h('baz', null);\n\t\tconst bazClone = h('baz', null);\n\t\tconst baz2 = h('baz', null);\n\t\tconst baz2Clone = h('baz', null);\n\n\t\tdelete bar._original;\n\t\tdelete barClone._original;\n\t\tdelete baz._original;\n\t\tdelete bazClone._original;\n\t\tdelete baz2._original;\n\t\tdelete baz2Clone._original;\n\n\t\tlet r = h(\n\t\t\t'foo',\n\t\t\tnull,\n\t\t\t'one',\n\t\t\t'two',\n\t\t\tbar,\n\t\t\t'three',\n\t\t\tbaz,\n\t\t\tbaz2,\n\t\t\t'four',\n\t\t\tnull,\n\t\t\t'five',\n\t\t\t'six'\n\t\t);\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.property('props.children')\n\t\t\t.that.deep.equals([\n\t\t\t\t'one',\n\t\t\t\t'two',\n\t\t\t\tbarClone,\n\t\t\t\t'three',\n\t\t\t\tbazClone,\n\t\t\t\tbaz2Clone,\n\t\t\t\t'four',\n\t\t\t\tnull,\n\t\t\t\t'five',\n\t\t\t\t'six'\n\t\t\t]);\n\t});\n\n\tit('should not merge nested adjacent text children', () => {\n\t\tlet r = h(\n\t\t\t'foo',\n\t\t\tnull,\n\t\t\t'one',\n\t\t\t['two', null, 'three'],\n\t\t\tnull,\n\t\t\t['four', null, 'five', null],\n\t\t\t'six',\n\t\t\tnull\n\t\t);\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.property('props.children')\n\t\t\t.that.deep.equals([\n\t\t\t\t'one',\n\t\t\t\t['two', null, 'three'],\n\t\t\t\tnull,\n\t\t\t\t['four', null, 'five', null],\n\t\t\t\t'six',\n\t\t\t\tnull\n\t\t\t]);\n\t});\n\n\tit('should not merge children that are boolean values', () => {\n\t\tlet r = h('foo', null, 'one', true, 'two', false, 'three');\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.property('props.children')\n\t\t\t.that.deep.equals(['one', true, 'two', false, 'three']);\n\t});\n\n\tit('should not merge children of components', () => {\n\t\tlet Component = ({ children }) => children;\n\t\tlet r = h(Component, null, 'x', 'y');\n\n\t\texpect(r)\n\t\t\t.to.be.an('object')\n\t\t\t.with.nested.property('props.children')\n\t\t\t.that.deep.equals(['x', 'y']);\n\t});\n\n\tit('should ignore props.children if children are manually specified', () => {\n\t\tconst element = (\n\t\t\t<div a children={['a', 'b']}>\n\t\t\t\tc\n\t\t\t</div>\n\t\t);\n\t\tconst childrenless = <div a>c</div>;\n\t\tdelete element._original;\n\t\tdelete childrenless._original;\n\n\t\texpect(element).to.eql(childrenless);\n\t});\n});\n"
  },
  {
    "path": "test/shared/exports.test.js",
    "content": "import {\n\tcreateElement,\n\th,\n\tcreateContext,\n\tComponent,\n\tFragment,\n\trender,\n\thydrate,\n\tcloneElement,\n\toptions,\n\tcreateRef,\n\ttoChildArray,\n\tisValidElement\n} from '../../src/index';\nimport { expect } from 'chai';\n\ndescribe('preact', () => {\n\tit('should be available as named exports', () => {\n\t\texpect(h).to.be.a('function');\n\t\texpect(createElement).to.be.a('function');\n\t\texpect(Component).to.be.a('function');\n\t\texpect(Fragment).to.exist;\n\t\texpect(render).to.be.a('function');\n\t\texpect(hydrate).to.be.a('function');\n\t\texpect(cloneElement).to.be.a('function');\n\t\texpect(createContext).to.be.a('function');\n\t\texpect(options).to.exist.and.be.an('object');\n\t\texpect(createRef).to.be.a('function');\n\t\texpect(isValidElement).to.be.a('function');\n\t\texpect(toChildArray).to.be.a('function');\n\t});\n});\n"
  },
  {
    "path": "test/shared/isValidElement.test.js",
    "content": "import { createElement, isValidElement, Component } from '../../src/index';\nimport { expect } from 'chai';\nimport { isValidElementTests } from './isValidElementTests';\n\nisValidElementTests(expect, isValidElement, createElement, Component);\n"
  },
  {
    "path": "test/shared/isValidElementTests.jsx",
    "content": "// @jsxRuntime classic\n// @jsx createElement\n\nexport function isValidElementTests(\n\texpect,\n\tisValidElement,\n\tcreateElement,\n\tComponent\n) {\n\tdescribe('isValidElement', () => {\n\t\tit('should check if the argument is a valid vnode', () => {\n\t\t\t// Failure cases\n\t\t\texpect(isValidElement(123)).to.equal(false);\n\t\t\texpect(isValidElement(0)).to.equal(false);\n\t\t\texpect(isValidElement('')).to.equal(false);\n\t\t\texpect(isValidElement('abc')).to.equal(false);\n\t\t\texpect(isValidElement(null)).to.equal(false);\n\t\t\texpect(isValidElement(undefined)).to.equal(false);\n\t\t\texpect(isValidElement(true)).to.equal(false);\n\t\t\texpect(isValidElement(false)).to.equal(false);\n\t\t\texpect(isValidElement([])).to.equal(false);\n\t\t\texpect(isValidElement([123])).to.equal(false);\n\t\t\texpect(isValidElement([null])).to.equal(false);\n\n\t\t\t// Success cases\n\t\t\texpect(isValidElement(<div />)).to.equal(true);\n\n\t\t\tconst Foo = () => 123;\n\t\t\texpect(isValidElement(<Foo />)).to.equal(true);\n\t\t\tclass Bar extends Component {\n\t\t\t\trender() {\n\t\t\t\t\treturn <div />;\n\t\t\t\t}\n\t\t\t}\n\t\t\texpect(isValidElement(<Bar />)).to.equal(true);\n\t\t});\n\t});\n}\n"
  },
  {
    "path": "test/ts/Component.test.tsx",
    "content": "import { expect } from 'chai';\nimport { createElement, Component, RenderableProps, Fragment } from '../../';\n\nexport class ContextComponent extends Component<{ foo: string }> {\n\tgetChildContext() {\n\t\treturn { something: 2 };\n\t}\n\n\trender() {\n\t\treturn null;\n\t}\n}\n\nexport interface SimpleComponentProps {\n\tinitialName: string | null;\n}\n\nexport interface SimpleState {\n\tname: string | null;\n}\n\nexport class SimpleComponent extends Component<\n\tSimpleComponentProps,\n\tSimpleState\n> {\n\tconstructor(props: SimpleComponentProps) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\tname: props.initialName\n\t\t};\n\t}\n\n\trender() {\n\t\tif (!this.state.name) {\n\t\t\treturn null;\n\t\t}\n\t\tconst { initialName, children } = this.props;\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<span>\n\t\t\t\t\t{initialName} / {this.state.name}\n\t\t\t\t</span>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\t}\n}\n\nclass DestructuringRenderPropsComponent extends Component<\n\tSimpleComponentProps,\n\tSimpleState\n> {\n\tconstructor(props: SimpleComponentProps) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\tname: props.initialName\n\t\t};\n\t}\n\n\trender({ initialName, children }: RenderableProps<SimpleComponentProps>) {\n\t\tif (!this.state.name) {\n\t\t\treturn null;\n\t\t}\n\t\treturn (\n\t\t\t<span>\n\t\t\t\t{this.props.initialName} / {this.state.name}\n\t\t\t</span>\n\t\t);\n\t}\n}\n\ninterface RandomChildrenComponentProps {\n\tnum?: number;\n\tval?: string;\n\tspan?: boolean;\n}\n\nclass RandomChildrenComponent extends Component<RandomChildrenComponentProps> {\n\trender() {\n\t\tconst { num, val, span } = this.props;\n\t\tif (num) {\n\t\t\treturn num;\n\t\t}\n\t\tif (val) {\n\t\t\treturn val;\n\t\t}\n\t\tif (span) {\n\t\t\treturn <span>hi</span>;\n\t\t}\n\t\treturn null;\n\t}\n}\n\nclass StaticComponent extends Component<SimpleComponentProps, SimpleState> {\n\tstatic getDerivedStateFromProps(\n\t\tprops: SimpleComponentProps,\n\t\tstate: SimpleState\n\t): Partial<SimpleState> {\n\t\treturn {\n\t\t\t...props,\n\t\t\t...state\n\t\t};\n\t}\n\n\tstatic getDerivedStateFromError(err: Error) {\n\t\treturn {\n\t\t\tname: err.message\n\t\t};\n\t}\n\n\trender() {\n\t\treturn null;\n\t}\n}\n\nfunction MapperItem(props: { foo: number }) {\n\treturn <div />;\n}\n\nfunction Mapper() {\n\treturn [1, 2, 3].map(x => <MapperItem foo={x} key={x} />);\n}\n\nclass Button extends Component {\n\thandleClick(this: HTMLButtonElement, event: MouseEvent) {\n\t\tevent.preventDefault();\n\t\tif (event.target instanceof HTMLElement) {\n\t\t\tconsole.log(event.target.localName);\n\t\t}\n\t}\n\n\trender() {\n\t\treturn <button onClick={this.handleClick}>{this.props.children}</button>;\n\t}\n}\n\ndescribe('Component', () => {\n\tconst component = new SimpleComponent({ initialName: 'da name' });\n\n\tit('has state', () => {\n\t\texpect(component.state.name).to.eq('da name');\n\t});\n\n\tit('has props', () => {\n\t\texpect(component.props.initialName).to.eq('da name');\n\t});\n\n\tdescribe('setState', () => {\n\t\t// No need to execute these tests. because we only need to check if\n\t\t// the types are working. Executing them would require the DOM.\n\t\t// TODO: Run TS tests in our standard karma setup\n\t\tit.skip('can be used with an object', () => {\n\t\t\tcomponent.setState({ name: 'another name' });\n\t\t});\n\n\t\tit.skip('can be used with a function', () => {\n\t\t\tconst updater = (state: any, props: any) => ({\n\t\t\t\tname: `${state.name} - ${props.initialName}`\n\t\t\t});\n\t\t\tcomponent.setState(updater);\n\t\t});\n\t});\n\n\tdescribe('render', () => {\n\t\tit('can return null', () => {\n\t\t\tconst comp = new SimpleComponent({ initialName: null });\n\t\t\tconst actual = comp.render();\n\n\t\t\texpect(actual).to.eq(null);\n\t\t});\n\t});\n\n\tdescribe('Fragment', () => {\n\t\tit('should render nested Fragments', () => {\n\t\t\tvar vnode = (\n\t\t\t\t<Fragment>\n\t\t\t\t\t<Fragment>foo</Fragment>\n\t\t\t\t\tbar\n\t\t\t\t</Fragment>\n\t\t\t);\n\n\t\t\texpect(vnode.type).to.be.equal(Fragment);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/ts/VNode.test.tsx",
    "content": "import { expect } from 'chai';\nimport {\n\tcreateElement,\n\tComponent,\n\ttoChildArray,\n\tFunctionalComponent,\n\tComponentConstructor,\n\tComponentFactory,\n\tVNode,\n\tComponentChildren,\n\tcloneElement,\n\tComponentChild\n} from '../../';\n\nfunction getDisplayType(vnode: VNode | string | number) {\n\tif (typeof vnode === 'string' || typeof vnode == 'number') {\n\t\treturn vnode.toString();\n\t} else if (typeof vnode.type == 'string') {\n\t\treturn vnode.type;\n\t} else {\n\t\treturn vnode.type.displayName;\n\t}\n}\n\nclass SimpleComponent extends Component<{}, {}> {\n\trender() {\n\t\treturn <div>{this.props.children}</div>;\n\t}\n}\n\nconst SimpleFunctionalComponent = () => <div />;\n\nconst a: ComponentFactory = SimpleComponent;\nconst b: ComponentFactory = SimpleFunctionalComponent;\n\ndescribe('VNode TS types', () => {\n\tit('is returned by h', () => {\n\t\tconst actual = <div className=\"wow\" />;\n\t\texpect(actual).to.include.all.keys('type', 'props', 'key');\n\t});\n\n\tit('is returned by h', () => {\n\t\tconst actual = <div className=\"wow\" />;\n\t\texpect(actual).to.include.all.keys('type', 'props', 'key');\n\t});\n\n\tit('createElement conforms to the VNode type', () => {\n\t\tconst arr: VNode[] = [];\n\t\tarr.push(createElement('div', null));\n\t\texpect(true).to.be.true;\n\t});\n\n\tit('has a nodeName equal to the construction function when SFC', () => {\n\t\tconst sfc = <SimpleFunctionalComponent />;\n\t\texpect(sfc.type).to.be.instanceOf(Function);\n\t\tconst constructor = sfc.type as FunctionalComponent<any>;\n\t\texpect(constructor.name).to.eq('SimpleFunctionalComponent');\n\t});\n\n\tit('has a nodeName equal to the constructor of a component', () => {\n\t\tconst sfc = <SimpleComponent />;\n\t\texpect(sfc.type).to.be.instanceOf(Function);\n\t\tconst constructor = sfc.type as ComponentConstructor<any>;\n\t\texpect(constructor.name).to.eq('SimpleComponent');\n\t});\n\n\tit('has children which is an array of string or other vnodes', () => {\n\t\tconst comp = (\n\t\t\t<SimpleComponent>\n\t\t\t\t<SimpleComponent>child1</SimpleComponent>\n\t\t\t\tchild2\n\t\t\t</SimpleComponent>\n\t\t);\n\n\t\texpect(comp.props.children).to.be.instanceOf(Array);\n\t\texpect(comp.props.children[1]).to.be.a('string');\n\t});\n\n\tit('children type should work with toChildArray', () => {\n\t\tconst comp: VNode = <SimpleComponent>child1 {1}</SimpleComponent>;\n\n\t\tconst children = toChildArray(comp.props.children);\n\t\texpect(children).to.have.lengthOf(2);\n\t});\n\n\tit('toChildArray should filter out some types', () => {\n\t\tconst compChild = <SimpleComponent />;\n\t\tconst comp: VNode = (\n\t\t\t<SimpleComponent>\n\t\t\t\ta{null}\n\t\t\t\t{true}\n\t\t\t\t{false}\n\t\t\t\t{2}\n\t\t\t\t{undefined}\n\t\t\t\t{['b', 'c']}\n\t\t\t\t{compChild}\n\t\t\t</SimpleComponent>\n\t\t);\n\n\t\tconst children = toChildArray(comp.props.children);\n\t\texpect(children).to.deep.equal(['a', 2, 'b', 'c', compChild]);\n\t});\n\n\tit('functions like getDisplayType should work', () => {\n\t\tfunction TestComp(props: { children?: ComponentChildren }) {\n\t\t\treturn <div>{props.children}</div>;\n\t\t}\n\t\tTestComp.displayName = 'TestComp';\n\n\t\tconst compChild = <TestComp />;\n\t\tconst comp: VNode = (\n\t\t\t<SimpleComponent>\n\t\t\t\ta{null}\n\t\t\t\t{true}\n\t\t\t\t{false}\n\t\t\t\t{2}\n\t\t\t\t{undefined}\n\t\t\t\t{['b', 'c']}\n\t\t\t\t{compChild}\n\t\t\t</SimpleComponent>\n\t\t);\n\n\t\tconst types = toChildArray(comp.props.children).map(getDisplayType);\n\t\texpect(types).to.deep.equal(['a', '2', 'b', 'c', 'TestComp']);\n\t});\n\n\tit('component should work with cloneElement', () => {\n\t\tconst comp: VNode = (\n\t\t\t<SimpleComponent>\n\t\t\t\t<div>child 1</div>\n\t\t\t</SimpleComponent>\n\t\t);\n\t\tconst clone: VNode = cloneElement(comp);\n\n\t\texpect(comp.type).to.equal(clone.type);\n\t\texpect(comp.props).not.to.equal(clone.props);\n\t\texpect(comp.props).to.deep.equal(clone.props);\n\t});\n\n\tit('component should work with cloneElement using generics', () => {\n\t\tconst comp: VNode<string> = <SimpleComponent></SimpleComponent>;\n\t\tconst clone: VNode<string> = cloneElement<string>(comp);\n\n\t\texpect(comp.type).to.equal(clone.type);\n\t\texpect(comp.props).not.to.equal(clone.props);\n\t\texpect(comp.props).to.deep.equal(clone.props);\n\t});\n});\n\nclass ComponentWithFunctionChild extends Component<{\n\tchildren: (num: number) => string;\n}> {\n\trender() {\n\t\treturn null;\n\t}\n}\n<ComponentWithFunctionChild>\n\t{num => num.toFixed(2)}\n</ComponentWithFunctionChild>;\n\nclass ComponentWithStringChild extends Component<{ children: string }> {\n\trender() {\n\t\treturn null;\n\t}\n}\n<ComponentWithStringChild>child</ComponentWithStringChild>;\n\nclass ComponentWithNumberChild extends Component<{ children: number }> {\n\trender() {\n\t\treturn null;\n\t}\n}\n<ComponentWithNumberChild>{1}</ComponentWithNumberChild>;\n\nclass ComponentWithBooleanChild extends Component<{ children: boolean }> {\n\trender() {\n\t\treturn null;\n\t}\n}\n<ComponentWithBooleanChild>{false}</ComponentWithBooleanChild>;\n\nclass ComponentWithNullChild extends Component<{ children: null }> {\n\trender() {\n\t\treturn null;\n\t}\n}\n<ComponentWithNullChild>{null}</ComponentWithNullChild>;\n\nclass ComponentWithNumberChildren extends Component<{ children: number[] }> {\n\trender() {\n\t\treturn null;\n\t}\n}\n<ComponentWithNumberChildren>\n\t{1}\n\t{2}\n</ComponentWithNumberChildren>;\n\nconst ComponentReturningComponentChildren = ({\n\tchildren\n}: {\n\tchildren: ComponentChild;\n}) => children;\n\n<ComponentReturningComponentChildren>123</ComponentReturningComponentChildren>;\n"
  },
  {
    "path": "test/ts/custom-elements.tsx",
    "content": "import { createElement, Component, createContext, HTMLAttributes, MouseEventHandler } from '../../';\n\ndeclare module '../../' {\n\tnamespace createElement.JSX {\n\t\tinterface IntrinsicElements {\n\t\t\t// Custom element can use JSX EventHandler definitions\n\t\t\t'clickable-ce': {\n\t\t\t\toptionalAttr?: string;\n\t\t\t\tonClick?: MouseEventHandler<HTMLElement>;\n\t\t\t};\n\n\t\t\t// Custom Element that extends HTML attributes\n\t\t\t'color-picker': HTMLAttributes & {\n\t\t\t\t// Required attribute\n\t\t\t\tspace: 'rgb' | 'hsl' | 'hsv';\n\t\t\t\t// Optional attribute\n\t\t\t\talpha?: boolean;\n\t\t\t};\n\n\t\t\t// Custom Element with custom interface definition\n\t\t\t'custom-whatever': WhateveElAttributes;\n\t\t}\n\t}\n}\n\n// Whatever Element definition\n\ninterface WhateverElement {\n\tinstanceProp: string;\n}\n\ninterface WhateverElementEvent {\n\teventProp: number;\n}\n\ninterface WhateveElAttributes extends HTMLAttributes {\n\tsomeattribute?: string;\n\tonsomeevent?: (this: WhateverElement, ev: WhateverElementEvent) => void;\n}\n\n// Ensure context still works\nconst Ctx = createContext({ contextValue: '' });\n\n// Sample component that uses custom elements\n\nclass SimpleComponent extends Component {\n\tcomponentProp = 'componentProp';\n\trender() {\n\t\t// Render inside div to ensure standard JSX elements still work\n\t\treturn (\n\t\t\t<Ctx.Provider value={{ contextValue: 'value' }}>\n\t\t\t\t<div>\n\t\t\t\t\t<clickable-ce\n\t\t\t\t\t\tonClick={e => {\n\t\t\t\t\t\t\t// `this` should be instance of SimpleComponent since this is an\n\t\t\t\t\t\t\t// arrow function\n\t\t\t\t\t\t\tconsole.log(this.componentProp);\n\n\t\t\t\t\t\t\t// Validate `currentTarget` is HTMLElement\n\t\t\t\t\t\t\tconsole.log('clicked ', e.currentTarget.style.display);\n\t\t\t\t\t\t}}\n\t\t\t\t\t></clickable-ce>\n\t\t\t\t\t<color-picker space=\"rgb\" dir=\"rtl\"></color-picker>\n\t\t\t\t\t<custom-whatever\n\t\t\t\t\t\tdir=\"auto\" // Inherited prop from HTMLAttributes\n\t\t\t\t\t\tsomeattribute=\"string\"\n\t\t\t\t\t\tonsomeevent={function (e) {\n\t\t\t\t\t\t\t// Validate `this` and `e` are the right type\n\t\t\t\t\t\t\tconsole.log('clicked', this.instanceProp, e.eventProp);\n\t\t\t\t\t\t}}\n\t\t\t\t\t></custom-whatever>\n\n\t\t\t\t\t{/* Ensure context still works */}\n\t\t\t\t\t<Ctx.Consumer>\n\t\t\t\t\t\t{({ contextValue }) => contextValue.toLowerCase()}\n\t\t\t\t\t</Ctx.Consumer>\n\t\t\t\t</div>\n\t\t\t</Ctx.Provider>\n\t\t);\n\t}\n}\n\nconst component = <SimpleComponent />;\nclass SimpleComponentWithContextAsProvider extends Component {\n\tcomponentProp = 'componentProp';\n\trender() {\n\t\t// Render inside div to ensure standard JSX elements still work\n\t\treturn (\n\t\t\t<Ctx value={{ contextValue: 'value' }}>\n\t\t\t\t<div>\n\t\t\t\t\t{/* Ensure context still works */}\n\t\t\t\t\t<Ctx.Consumer>\n\t\t\t\t\t\t{({ contextValue }) => contextValue.toLowerCase()}\n\t\t\t\t\t</Ctx.Consumer>\n\t\t\t\t</div>\n\t\t\t</Ctx>\n\t\t);\n\t}\n}\nconst component2 = <SimpleComponentWithContextAsProvider />;\n"
  },
  {
    "path": "test/ts/dom-attributes.test-d.tsx",
    "content": "import {\n\tcreateElement,\n\tFragment,\n\tSignalLike,\n\tUnpackSignal,\n\tAriaAttributes\n} from 'preact';\n\nfunction createSignal<T>(value: T): SignalLike<T> {\n\treturn {\n\t\tvalue,\n\t\tpeek() {\n\t\t\treturn value;\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn () => {};\n\t\t}\n\t};\n}\n\n// @ts-expect-error A button should not have a role of presentation\nconst badAriaRole = <button role=\"presentation\" />;\nconst validAriaRole = <button role=\"slider\" />;\nconst signalBadAriaRole = (\n\t// @ts-expect-error A button should not have a role of presentation\n\t<button role={createSignal('presentation' as const)} />\n);\nconst signalValidAriaRole = <button role={createSignal('slider' as const)} />;\n\n// @ts-expect-error A map should never have any role set\nconst invalidAriaRole = <map role=\"presentation\" />;\nconst signalInvalidAriaRole = (\n\t// @ts-expect-error A map should never have any role set\n\t<button role={createSignal('presentation' as const)} />\n);\nconst validMissingAriaRole = <base href=\"\"></base>;\nconst signalValidMissingAriaRole = (\n\t// @ts-expect-error A map should never have any role set\n\t<button role={createSignal('presentation' as const)} />\n);\n\n// More complex role tests w/ unions\n\nconst aWithHrefValid = <a href=\"foo\" role=\"button\"></a>;\n// @ts-expect-error An anchor with an href should not have a role of slider\nconst aWithHrefInvalid = <a href=\"foo\" role=\"slider\"></a>;\n\nconst aWithoutHrefValid = <a role=\"button\"></a>;\n\nconst areaWithHrefValid = <area href=\"foo\" role=\"link\"></area>;\n// @ts-expect-error An area with an href should not have a role of button\nconst areaWithHrefInvalid = <area href=\"foo\" role=\"button\"></area>;\n\nconst areaWithoutHrefValid = <area role=\"button\"></area>;\n// @ts-expect-error An area with an href should not have a role of button\nconst areaWithoutHrefInvalid = <area role=\"slider\"></area>;\n\nconst imgWithAccessibleNameAriaLabelValid = (\n\t<img aria-label=\"foo\" role=\"button\" />\n);\nconst imgWithAccessibleNameAriaLabelledByValid = (\n\t<img aria-labelledby=\"foo\" role=\"button\" />\n);\nconst imgWithAccessibleNameAltValid = <img alt=\"foo\" role=\"button\" />;\nconst imgWithAccessibleNameTitleValid = <img title=\"foo\" role=\"button\" />;\nconst imgWithAccessibleNameAriaLabelInvalid = (\n\t// @ts-expect-error An img with an accessible name should not have a role of presentation\n\t<img aria-label=\"foo\" role=\"presentation\" />\n);\nconst imgWithAccessibleNameAriaLabelledByInvalid = (\n\t// @ts-expect-error An img with an accessible name should not have a role of presentation\n\t<img aria-labelledby=\"foo\" role=\"presentation\" />\n);\n// @ts-expect-error An img with an accessible name should not have a role of presentation\nconst imgWithAccessibleNameAltInvalid = <img alt=\"foo\" role=\"presentation\" />;\n// @ts-expect-error An img with an accessible name should not have a role of presentation\nconst imgWithAccessibleNameValid = <img title=\"foo\" role=\"presentation\" />;\n\nconst imgWithoutAccessibleNameValid = <img role=\"presentation\" />;\n// @ts-expect-error An img without an accessible name should not have a role of button\nconst imgWithoutAccessibleNameInvalid = <img role=\"button\" />;\n\nconst inputTypeButtonValid = <input type=\"button\" role=\"checkbox\" />;\n// @ts-expect-error An input of type button should not have a role of presentation\nconst inputTypeButtonInvalid = <input type=\"button\" role=\"presentation\" />;\n\nconst inputTypeCheckboxValid = (\n\t<input type=\"checkbox\" role=\"menuitemcheckbox\" />\n);\n// @ts-expect-error An input of type checkbox should not have a role of presentation\nconst inputTypeCheckboxInvalid = <input type=\"checkbox\" role=\"presentation\" />;\n\nconst inputTypeColorValid = <input type=\"color\" />;\n// @ts-expect-error An input of type color should not have a role\nconst inputTypeColorInvalid = <input type=\"color\" role=\"button\" />;\n\nconst inputTypeDateValid = <input type=\"date\" />;\n// @ts-expect-error An input of type date should not have a role\nconst inputTypeDateInvalid = <input type=\"date\" role=\"button\" />;\n\nconst inputTypeDatetimeLocalValid = <input type=\"datetime-local\" />;\nconst inputTypeDatetimeLocalInvalid = (\n\t// @ts-expect-error An input of type datetime-local should not have a role\n\t<input type=\"datetime-local\" role=\"button\" />\n);\n\nconst inputTypeEmailValid = <input type=\"email\" role=\"textbox\" />;\n// @ts-expect-error An input of type email, without a list attribute, should not have a role of button\nconst inputTypeEmailInvalid = <input type=\"email\" role=\"button\" />;\n\nconst inputTypeFileValid = <input type=\"file\" />;\n// @ts-expect-error An input of type file should not have a role\nconst inputTypeFileInvalid = <input type=\"file\" role=\"button\" />;\n\nconst inputTypeHiddenValid = <input type=\"hidden\" />;\n// @ts-expect-error An input of type hidden should not have a role\nconst inputTypeHiddenInvalid = <input type=\"hidden\" role=\"button\" />;\n\nconst inputTypeImageValid = <input type=\"image\" role=\"button\" />;\n// @ts-expect-error An input of type image should not have a role of presentation\nconst inputTypeImageInvalid = <input type=\"image\" role=\"presentation\" />;\n\nconst inputTypeMonthValid = <input type=\"month\" />;\n// @ts-expect-error An input of type month should not have a role\nconst inputTypeMonthInvalid = <input type=\"month\" role=\"button\" />;\n\nconst inputTypeNumberValid = <input type=\"number\" role=\"spinbutton\" />;\n// @ts-expect-error An input of type number should not have a role of button\nconst inputTypeNumberInvalid = <input type=\"number\" role=\"button\" />;\n\nconst inputTypePasswordValid = <input type=\"password\" />;\n// @ts-expect-error An input of type password should not have a role\nconst inputTypePasswordInvalid = <input type=\"password\" role=\"button\" />;\n\nconst inputTypeRadioValid = <input type=\"radio\" role=\"menuitemradio\" />;\n// @ts-expect-error An input of type radio should not have a role of button\nconst inputTypeRadioInvalid = <input type=\"radio\" role=\"button\" />;\n\nconst inputTypeRangeValid = <input type=\"range\" role=\"slider\" />;\n// @ts-expect-error An input of type range should not have a role of button\nconst inputTypeRangeInvalid = <input type=\"range\" role=\"button\" />;\n\nconst inputTypeResetValid = <input type=\"reset\" role=\"slider\" />;\n// @ts-expect-error An input of type reset should not have a role of presentation\nconst inputTypeResetInvalid = <input type=\"reset\" role=\"presentation\" />;\n\nconst inputTypeSearchValid = <input type=\"search\" role=\"searchbox\" />;\n// @ts-expect-error An input of type search should not have a role of button\nconst inputTypeSearchInvalid = <input type=\"search\" role=\"button\" />;\n\nconst inputTypeSubmitValid = <input type=\"submit\" role=\"button\" />;\n// @ts-expect-error An input of type submit should not have a role of presentation\nconst inputTypeSubmitInvalid = <input type=\"submit\" role=\"presentation\" />;\n\nconst inputTypeTelValid = <input type=\"tel\" role=\"textbox\" />;\n// @ts-expect-error An input of type tel should not have a role of presentation\nconst inputTypeTelInvalid = <input type=\"tel\" role=\"presentation\" />;\n\nconst inputTypeTextValid = <input type=\"text\" role=\"combobox\" />;\n// @ts-expect-error An input of type text should not have a role of presentation\nconst inputTypeTextInvalid = <input type=\"text\" role=\"presentation\" />;\n\nconst inputTypeOmittedValid = <input role=\"combobox\" />;\n// @ts-expect-error An input of type text should not have a role of presentation\nconst inputTypeOmittedInvalid = <input role=\"presentation\" />;\n\nconst inputTypeEmailListValid = (\n\t<input type=\"email\" list=\"foo\" role=\"combobox\" />\n);\n// @ts-expect-error An input of type email, with a list attribute, should not have a role of button\nconst inputTypeEmailListInvalid = <input type=\"email\" role=\"button\" />;\n\nconst inputTypeSearchListValid = (\n\t<input type=\"search\" list=\"foo\" role=\"combobox\" />\n);\n// @ts-expect-error An input of type search, with a list attribute, should not have a role of button\nconst inputTypeSearchListInvalid = <input type=\"search\" role=\"button\" />;\n\nconst inputTypeTelListValid = <input type=\"tel\" list=\"foo\" role=\"combobox\" />;\n// @ts-expect-error An input of type tel, with a list attribute, should not have a role of button\nconst inputTypeTelListInvalid = <input type=\"tel\" role=\"button\" />;\n\nconst inputTypeTextListValid = <input type=\"text\" list=\"foo\" role=\"combobox\" />;\n// @ts-expect-error An input of type text, with a list attribute, should not have a role of button\nconst inputTypeTextListInvalid = <input type=\"text\" role=\"button\" />;\n\nconst inputTypeOmittedListValid = (\n\t<input type=\"text\" list=\"foo\" role=\"combobox\" />\n);\n// @ts-expect-error An input of type text, with a list attribute, should not have a role of button\nconst inputTypeOmittedListInvalid = <input type=\"text\" role=\"button\" />;\n\nconst inputTypeUrlListValid = <input type=\"url\" list=\"foo\" role=\"combobox\" />;\n// @ts-expect-error An input of type url, with a list attribute, should not have a role of button\nconst inputTypeUrlListInvalid = <input type=\"url\" role=\"button\" />;\n\nconst inputTypeTimeValid = <input type=\"time\" />;\n// @ts-expect-error An input of type time should not have a role\nconst inputTypeTimeInvalid = <input type=\"time\" role=\"button\" />;\n\nconst inputTypeUrlValid = <input type=\"url\" role=\"textbox\" />;\n// @ts-expect-error An input of type url should not have a role of button\nconst inputTypeUrlInvalid = <input type=\"url\" role=\"button\" />;\n\nconst inputTypeWeekValid = <input type=\"week\" />;\n// @ts-expect-error An input of type week should not have a role\nconst inputTypeWeekInvalid = <input type=\"week\" role=\"button\" />;\n\nconst selectValid = <select role=\"menu\" />;\n// @ts-expect-error A select should not have a role of button\nconst selectInvalid = <select role=\"button\" />;\n\nconst selectMultipleValid = <select multiple={true} role=\"listbox\" />;\n// @ts-expect-error A select multiple should not have a role of menu\nconst selectMultipleInvalid = <select multiple={true} role=\"menu\" />;\n\nconst selectSizeValid = <select size={5} role=\"listbox\" />;\n// @ts-expect-error A select with a size other than `0` or `1` should not have a role of menu\nconst selectSizeInvalid = <select size={5} role=\"menu\" />;\n\n// @ts-expect-error We should correctly type aria attributes like autocomplete\nconst badAriaValues = <div aria-autocomplete=\"bad-value\" />;\nconst validAriaValues = <div aria-autocomplete=\"none\" />;\nconst undefAriaValues = <div aria-autocomplete={undefined} />;\nconst noAriaValues = <div />;\n\nconst signalBadAriaValues = (\n\t// @ts-expect-error We should correctly type aria attributes like autocomplete\n\t<div aria-autocomplete={createSignal('bad-value' as const)} />\n);\nconst signalValidAriaValues = (\n\t<div aria-autocomplete={createSignal('none' as 'none' | undefined)} />\n);\nconst signalValidAriaValues2 = (\n\t<div\n\t\taria-autocomplete={createSignal(\n\t\t\t'none' as UnpackSignal<AriaAttributes['aria-autocomplete']>\n\t\t)}\n\t/>\n);\n\nconst validRole = <div role=\"button\" />;\n// @ts-expect-error We should correctly type aria roles\nconst invalidRole = <div role=\"invalid-role\" />;\n// @ts-expect-error We should disallow `generic` as it should not ever be explicitly set\nconst invalidRole2 = <div role=\"generic\" />;\nconst fallbackRole = <div role=\"none presentation\" />;\n\nconst booleanishTest = (\n\t<>\n\t\t<div aria-haspopup={true} />\n\t\t<div aria-haspopup={false} />\n\t\t<div aria-haspopup={'true'} />\n\t\t<div aria-haspopup={'false'} />\n\t\t<div aria-haspopup={'dialog'} />\n\t</>\n);\n\nconst dangerouslySetInnerHTML = (\n\t<>\n\t\t<div dangerouslySetInnerHTML={{ __html: 'string' }} />\n\t</>\n);\n"
  },
  {
    "path": "test/ts/hoc.test.tsx",
    "content": "import { expect } from 'chai';\nimport {\n\tcreateElement,\n\tComponentFactory,\n\tComponentConstructor,\n\tComponent\n} from '../../';\nimport { SimpleComponent, SimpleComponentProps } from './Component.test';\n\nexport interface highlightedProps {\n\tisHighlighted: boolean;\n}\n\nexport function highlighted<T>(\n\tWrappable: ComponentFactory<T>\n): ComponentConstructor<T & highlightedProps> {\n\treturn class extends Component<T & highlightedProps> {\n\t\tconstructor(props: T & highlightedProps) {\n\t\t\tsuper(props);\n\t\t}\n\n\t\trender() {\n\t\t\tlet className = this.props.isHighlighted ? 'highlighted' : '';\n\t\t\treturn (\n\t\t\t\t<div className={className}>\n\t\t\t\t\t<Wrappable {...this.props} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\ttoString() {\n\t\t\treturn `Highlighted ${Wrappable.name}`;\n\t\t}\n\t};\n}\n\nconst HighlightedSimpleComponent =\n\thighlighted<SimpleComponentProps>(SimpleComponent);\n\ndescribe('hoc', () => {\n\tit('wraps the given component', () => {\n\t\tconst highlight = new HighlightedSimpleComponent({\n\t\t\tinitialName: 'initial name',\n\t\t\tisHighlighted: true\n\t\t});\n\n\t\texpect(highlight.toString()).to.eq('Highlighted SimpleComponent');\n\t});\n});\n"
  },
  {
    "path": "test/ts/jsx-namespace.test-d.tsx",
    "content": "import { createElement, Component } from '../../';\n\n// declare global JSX types that should not be mixed with preact's internal types\ndeclare global {\n\tnamespace JSX {\n\t\tinterface Element {\n\t\t\tunknownProperty: string;\n\t\t}\n\t}\n}\n\nclass SimpleComponent extends Component {\n\trender() {\n\t\treturn <div>It works</div>;\n\t}\n}\n"
  },
  {
    "path": "test/ts/package.json",
    "content": "{\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "test/ts/preact-global.test-d.tsx",
    "content": "import { createElement } from '../../src';\n\n// Test that preact types are available via the global `preact` namespace.\n\nlet component: preact.ComponentChild;\ncomponent = <div>Hello World</div>;\n"
  },
  {
    "path": "test/ts/preact.tsx",
    "content": "import {\n\tcreateElement,\n\trender,\n\tComponent,\n\tComponentProps,\n\tFunctionalComponent,\n\tAnyComponent,\n\th,\n\tcreateRef,\n\tSignalLike,\n\tComponentChildren,\n\tTargetedEvent,\n\tTargetedInputEvent,\n\tTargetedToggleEvent,\n\tTargetedSubmitEvent,\n\tAllHTMLAttributes,\n\tHTMLAttributes,\n\tInputHTMLAttributes,\n} from '../../';\n\nfunction createSignal<T>(value: T): SignalLike<T> {\n\treturn {\n\t\tvalue,\n\t\tpeek() {\n\t\t\treturn value;\n\t\t},\n\t\tsubscribe() {\n\t\t\treturn () => {};\n\t\t}\n\t};\n}\n\ninterface DummyProps {\n\tinitialInput: string;\n}\n\ninterface DummyState {\n\tinput: string;\n}\n\nclass DummyComponent extends Component<DummyProps, DummyState> {\n\tconstructor(props: DummyProps) {\n\t\tsuper(props);\n\t\tthis.state = {\n\t\t\tinput: `x${this.props}x`\n\t\t};\n\t}\n\n\tprivate setRef = (el: AnyComponent<any>) => {\n\t\tconsole.log(el);\n\t};\n\n\trender({ initialInput }: DummyProps, { input }: DummyState) {\n\t\treturn (\n\t\t\t<div>\n\t\t\t\t<DummerComponent initialInput={initialInput} input={input} />\n\t\t\t\t{/* Can specify all Preact attributes on a typed FunctionalComponent */}\n\t\t\t\t<ComponentWithChildren\n\t\t\t\t\tinitialInput={initialInput}\n\t\t\t\t\tinput={input}\n\t\t\t\t\tkey=\"1\"\n\t\t\t\t\tref={this.setRef}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t}\n}\n\ninterface DummerComponentProps extends DummyProps, DummyState {}\n\nfunction DummerComponent({ input, initialInput }: DummerComponentProps) {\n\treturn (\n\t\t<div>\n\t\t\tInput: {input}, initial: {initialInput}\n\t\t</div>\n\t);\n}\n\nrender(createElement('div', { title: 'test', key: '1' }), document);\nrender(\n\tcreateElement(DummyComponent, { initialInput: 'The input', key: '1' }),\n\tdocument\n);\nrender(\n\tcreateElement(DummerComponent, {\n\t\tinitialInput: 'The input',\n\t\tinput: 'New input',\n\t\tkey: '1'\n\t}),\n\tdocument\n);\nrender(h('div', { title: 'test', key: '1' }), document);\nrender(h(DummyComponent, { initialInput: 'The input', key: '1' }), document);\nrender(\n\th(DummerComponent, {\n\t\tinitialInput: 'The input',\n\t\tinput: 'New input',\n\t\tkey: '1'\n\t}),\n\tdocument\n);\n\n// Mounting into different types of Nodes\nrender(h('div', {}), document.createElement('div'));\nrender(h('div', {}), document);\nrender(h('div', {}), document.createElement('div').shadowRoot!);\nrender(h('div', {}), document.createDocumentFragment());\n\n// From https://gist.github.com/developit/f4c67a2ede71dc2fab7f357f39cff28c, modified to be TypeScript compliant\nfunction createRootFragment(parent: Element, replaceNode: Element | Element[]) {\n\tconst replaceNodes: Element[] = ([] as Element[]).concat(replaceNode);\n\tconst s = replaceNodes[replaceNodes.length - 1].nextSibling;\n\tfunction insert(c: Node, r: Node | null) {\n\t\treturn parent.insertBefore(c, r || s);\n\t}\n\treturn ((parent as any).__k = {\n\t\tnodeType: 1,\n\t\tparentNode: parent,\n\t\tfirstChild: replaceNodes[0],\n\t\tchildNodes: replaceNodes,\n\t\tcontains: (c: Node) => parent.contains(c),\n\t\tinsertBefore: insert,\n\t\tappendChild: (c: Node) => insert(c, null),\n\t\tremoveChild: function (c: Node) {\n\t\t\treturn parent.removeChild(c);\n\t\t}\n\t});\n}\n\nrender(\n\th('div', {}),\n\tcreateRootFragment(\n\t\tdocument.createElement('div'),\n\t\tdocument.createElement('div')\n\t)\n);\n\n// Accessing children\nconst ComponentWithChildren: FunctionalComponent<DummerComponentProps> = ({\n\tinput,\n\tinitialInput,\n\tchildren\n}) => {\n\treturn (\n\t\t<div>\n\t\t\t<span>{initialInput}</span>\n\t\t\t<span>{input}</span>\n\t\t\t<span>{children}</span>\n\t\t</div>\n\t);\n};\n\nconst UseOfComponentWithChildren = () => {\n\treturn (\n\t\t<ComponentWithChildren initialInput=\"initial\" input=\"input\">\n\t\t\t<span>child 1</span>\n\t\t\t<span>child 2</span>\n\t\t</ComponentWithChildren>\n\t);\n};\n\nconst DummyChildren: FunctionalComponent = ({ children }) => {\n\treturn children;\n};\n\nfunction ReturnChildren(props: { children: preact.ComponentChildren }) {\n\treturn props.children;\n}\n\nfunction TestUndefinedChildren() {\n\treturn (\n\t\t<ReturnChildren>\n\t\t\t<ReturnChildren>Hello</ReturnChildren>\n\t\t</ReturnChildren>\n\t);\n}\n\n// using ref and or jsx\nclass ComponentUsingRef extends Component<any, any> {\n\tprivate array: string[];\n\tprivate refs: (Element | null)[] = [];\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.array = ['1', '2'];\n\t}\n\n\trender() {\n\t\tthis.refs = [];\n\t\treturn (\n\t\t\t<div jsx>\n\t\t\t\t{this.array.map(el => (\n\t\t\t\t\t<span ref={this.setRef}>{el}</span>\n\t\t\t\t))}\n\n\t\t\t\t{/* Can specify Preact attributes on a component */}\n\t\t\t\t<DummyComponent initialInput=\"1\" key=\"1\" ref={this.setRef} />\n\t\t\t</div>\n\t\t);\n\t}\n\n\tprivate setRef = (el: Element | null) => {\n\t\tthis.refs.push(el);\n\t};\n}\n\n// using lifecycles\nclass ComponentWithLifecycle extends Component<DummyProps, DummyState> {\n\trender() {\n\t\treturn <div>Hi</div>;\n\t}\n\n\tcomponentWillMount() {\n\t\tconsole.log('componentWillMount');\n\t}\n\n\tcomponentDidMount() {\n\t\tconsole.log('componentDidMount');\n\t}\n\n\tcomponentWillUnmount() {\n\t\tconsole.log('componentWillUnmount');\n\t}\n\n\tcomponentWillReceiveProps(nextProps: DummyProps, nextCtx: any) {\n\t\tconst { initialInput } = nextProps;\n\t\tconsole.log('componentWillReceiveProps', initialInput, nextCtx);\n\t}\n\n\tshouldComponentUpdate(\n\t\tnextProps: DummyProps,\n\t\tnextState: DummyState,\n\t\tnextContext: any\n\t) {\n\t\treturn false;\n\t}\n\n\tcomponentWillUpdate(\n\t\tnextProps: DummyProps,\n\t\tnextState: DummyState,\n\t\tnextContext: any\n\t) {\n\t\tconsole.log('componentWillUpdate', nextProps, nextState, nextContext);\n\t}\n\n\tcomponentDidUpdate(\n\t\tpreviousProps: DummyProps,\n\t\tpreviousState: DummyState,\n\t\tpreviousContext: any\n\t) {\n\t\tconsole.log(\n\t\t\t'componentDidUpdate',\n\t\t\tpreviousProps,\n\t\t\tpreviousState,\n\t\t\tpreviousContext\n\t\t);\n\t}\n}\n\n// Default props: JSX.LibraryManagedAttributes\n\nclass DefaultProps extends Component<{ text: string; bool: boolean }> {\n\tstatic defaultProps = {\n\t\ttext: 'hello'\n\t};\n\n\trender() {\n\t\treturn <div>{this.props.text}</div>;\n\t}\n}\n\nconst d1 = <DefaultProps bool={false} text=\"foo\" />;\nconst d2 = <DefaultProps bool={false} />;\n\nclass DefaultPropsWithUnion extends Component<\n\t{ default: boolean } & (\n\t\t| {\n\t\t\t\ttype: 'string';\n\t\t\t\tstr: string;\n\t\t  }\n\t\t| {\n\t\t\t\ttype: 'number';\n\t\t\t\tnum: number;\n\t\t  }\n\t)\n> {\n\tstatic defaultProps = {\n\t\tdefault: true\n\t};\n\n\trender() {\n\t\treturn <div />;\n\t}\n}\n\nconst d3 = <DefaultPropsWithUnion type=\"string\" str={'foo'} />;\nconst d4 = <DefaultPropsWithUnion type=\"number\" num={0xf00} />;\nconst d5 = <DefaultPropsWithUnion type=\"string\" str={'foo'} default={false} />;\nconst d6 = <DefaultPropsWithUnion type=\"number\" num={0xf00} default={false} />;\n\nclass DefaultUnion extends Component<\n\t| {\n\t\t\ttype: 'number';\n\t\t\tnum: number;\n\t  }\n\t| {\n\t\t\ttype: 'string';\n\t\t\tstr: string;\n\t  }\n> {\n\tstatic defaultProps = {\n\t\ttype: 'number',\n\t\tnum: 1\n\t};\n\n\trender() {\n\t\treturn <div />;\n\t}\n}\n\nconst d7 = <DefaultUnion />;\nconst d8 = <DefaultUnion num={1} />;\nconst d9 = <DefaultUnion type=\"number\" />;\nconst d10 = <DefaultUnion type=\"string\" str=\"foo\" />;\n\nclass ComponentWithDefaultProps extends Component<{ value: string }> {\n\tstatic defaultProps = { value: '' };\n\trender() {\n\t\treturn <div>{this.props.value}</div>;\n\t}\n}\n\nconst withDefaultProps = <ComponentWithDefaultProps />;\n\ninterface PartialState {\n\tfoo: string;\n\tbar: number;\n}\n\nclass ComponentWithPartialSetState extends Component<{}, PartialState> {\n\trender({}, { foo, bar }: PartialState) {\n\t\treturn (\n\t\t\t<button onClick={() => this.handleClick('foo')}>\n\t\t\t\t{foo}-{bar}\n\t\t\t</button>\n\t\t);\n\t}\n\thandleClick = (value: keyof PartialState) => {\n\t\tthis.setState({ [value]: 'updated' });\n\t};\n}\n\nconst withPartialSetState = <ComponentWithPartialSetState />;\n\nlet functionalProps: ComponentProps<typeof DummerComponent> = {\n\tinitialInput: '',\n\tinput: ''\n};\n\nlet classProps: ComponentProps<typeof DummyComponent> = {\n\tinitialInput: ''\n};\n\nlet elementProps: ComponentProps<'button'> = {\n\ttype: 'button'\n};\n\n// Typing of style property\nconst acceptsNumberAsLength = <div style={{ marginTop: 20 }} />;\nconst acceptsStringAsLength = <div style={{ marginTop: '20px' }} />;\n\nconst ReturnNull: FunctionalComponent = () => null;\n\n// Should accept arbitrary properties outside of JSX.HTMLAttributes\nh('option', { x: 'foo' });\ncreateElement('option', { value: 'foo' });\n\n// Refs should work on elements\nconst ref = createRef<HTMLDivElement>();\ncreateElement('div', { ref: ref }, 'hi');\nh('div', { ref: ref }, 'hi');\n\n// Refs should work on functions\nconst functionRef = createRef();\nconst RefComponentTest = () => <p>hi</p>;\ncreateElement(RefComponentTest, { ref: functionRef }, 'hi');\nh(RefComponentTest, { ref: functionRef }, 'hi');\n\n// Should accept onInput\nconst onInput = (e: TargetedInputEvent<HTMLInputElement>) => {};\n<input onInput={onInput} />;\n<input onInput={e => e.currentTarget.value} />;\ncreateElement('input', { onInput: onInput });\nh('input', { onInput: onInput });\n\n// Should accept onBeforeInput\nconst onBeforeInput = (e: TargetedInputEvent<HTMLInputElement>) => {};\n<input onBeforeInput={e => e.currentTarget.value} />;\ncreateElement('input', { onBeforeInput: onBeforeInput });\nh('input', { onBeforeInput: onBeforeInput });\n\n// Should accept onSubmit\nconst onSubmit = (e: TargetedSubmitEvent<HTMLFormElement>) => {};\n<form onSubmit={e => e.currentTarget.elements} />;\ncreateElement('form', { onSubmit: onSubmit });\nh('form', { onSubmit: onSubmit });\n\n// Should accept onToggle\nconst onToggle = (e: TargetedToggleEvent<HTMLDetailsElement>) => {};\n<dialog onToggle={e => ({ newState: e.newState, oldState: e.oldState })} />;\ncreateElement('dialog', { onToggle: onToggle });\nh('dialog', { onToggle: onToggle });\n\n// Should default to correct event target element for the attribute interface\nh<InputHTMLAttributes>('input', { onClick: e => e.currentTarget.capture });\ncreateElement<InputHTMLAttributes>('input', {\n\tonClick: e => e.currentTarget.capture\n});\n<input onClick={e => e.currentTarget.capture} />;\n\nfunction Checkbox({ onChange }: HTMLAttributes<HTMLInputElement>) {\n\tfunction handleChange(\n\t\tthis: void,\n\t\tevent: TargetedEvent<HTMLInputElement>\n\t) {\n\t\tonChange?.call(this, event);\n\t}\n\n\treturn <input onChange={handleChange} />;\n}\n\n// `AllHTMLAttributes` should support all interfaces used within `JSX.IntrinsicElements`\nconst allHTMLAttributes: AllHTMLAttributes<HTMLMarqueeElement> = {\n\t// Global HTMLAttributes\n\tclass: 'foo',\n\n\t// Per-element attributes\n\tautoCapitalize: 'off',\n\tdateTime: '2021-01-01',\n\thref: createSignal('https://example.com'),\n\titemID: 'foo',\n\tmaxlength: createSignal(10),\n\tplaysInline: true,\n\n\t// ClassAttributes\n\tref: createRef<HTMLMarqueeElement>(),\n\n\t// DOMAttributes\n\tonClick: (e: TargetedEvent<HTMLMarqueeElement>) => {},\n\n\t// AriaAttributes\n\t'aria-colcount': 1\n};\n"
  },
  {
    "path": "test/ts/refs.tsx",
    "content": "import {\n\tcreateElement,\n\tComponent,\n\tcreateRef,\n\tFunctionalComponent,\n\tFragment,\n\tRefObject,\n\tRefCallback\n} from '../../';\n\n// Test Fixtures\nconst Foo: FunctionalComponent = () => <span>Foo</span>;\nclass Bar extends Component {\n\trender() {\n\t\treturn <span>Bar</span>;\n\t}\n}\n\n// Using Refs\nclass CallbackRef extends Component {\n\tdivRef: RefCallback<HTMLDivElement> = div => {\n\t\tif (div !== null) {\n\t\t\tconsole.log(div.tagName);\n\t\t}\n\t};\n\tfooRef: RefCallback<Component> = foo => {\n\t\tif (foo !== null) {\n\t\t\tconsole.log(foo);\n\t\t}\n\t};\n\tbarRef: RefCallback<Bar> = bar => {\n\t\tif (bar !== null) {\n\t\t\tconsole.log(bar);\n\t\t}\n\t};\n\n\trender() {\n\t\treturn (\n\t\t\t<Fragment>\n\t\t\t\t<div ref={this.divRef} />\n\t\t\t\t<Foo ref={this.fooRef} />\n\t\t\t\t<Bar ref={this.barRef} />\n\t\t\t</Fragment>\n\t\t);\n\t}\n}\n\nclass CreateRefComponent extends Component {\n\tprivate divRef: RefObject<HTMLDivElement> = createRef();\n\tprivate fooRef: RefObject<Component> = createRef();\n\tprivate barRef: RefObject<Bar> = createRef();\n\n\tcomponentDidMount() {\n\t\tif (this.divRef.current != null) {\n\t\t\tconsole.log(this.divRef.current.tagName);\n\t\t}\n\n\t\tif (this.fooRef.current != null) {\n\t\t\tconsole.log(this.fooRef.current);\n\t\t}\n\n\t\tif (this.barRef.current != null) {\n\t\t\tconsole.log(this.barRef.current);\n\t\t}\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<Fragment>\n\t\t\t\t<div ref={this.divRef} />\n\t\t\t\t<Foo ref={this.fooRef} />\n\t\t\t\t<Bar ref={this.barRef} />\n\t\t\t</Fragment>\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "test/ts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"module\": \"es6\",\n    \"moduleResolution\": \"node\",\n    \"lib\": [\"es6\", \"dom\"],\n    \"strict\": true,\n    \"typeRoots\": [\"../../\", \"../../node_modules\"],\n    \"types\": [\"vitest/globals\"],\n    \"forceConsistentCasingInFileNames\": true,\n    \"jsx\": \"react\",\n    \"jsxFactory\": \"createElement\",\n    \"jsxFragmentFactory\": \"Fragment\",\n    \"skipLibCheck\": true,\n    \"paths\": {\n      \"preact\": [\"../../\"],\n      \"preact/*\": [\"../../*\"]\n    }\n  },\n  \"include\": [\"./**/*.ts\", \"./**/*.tsx\"]\n}\n"
  },
  {
    "path": "test-utils/package.json",
    "content": "{\n  \"name\": \"test-utils\",\n  \"amdName\": \"preactTestUtils\",\n  \"private\": true,\n  \"description\": \"Test-utils for Preact\",\n  \"main\": \"dist/testUtils.js\",\n  \"module\": \"dist/testUtils.mjs\",\n  \"umd:main\": \"dist/testUtils.umd.js\",\n  \"source\": \"src/index.js\",\n  \"types\": \"src/index.d.ts\",\n  \"license\": \"MIT\",\n  \"mangle\": {\n    \"regex\": \"^_\"\n  },\n  \"peerDependencies\": {\n    \"preact\": \"^10.0.0\"\n  }\n}\n"
  },
  {
    "path": "test-utils/src/index.d.ts",
    "content": "export function setupRerender(): () => void;\nexport function act(callback: () => void | Promise<void>): Promise<void>;\nexport function teardown(): void;\n"
  },
  {
    "path": "test-utils/src/index.js",
    "content": "import { options } from 'preact';\n\n/**\n * Setup a rerender function that will drain the queue of pending renders\n * @returns {() => void}\n */\nexport function setupRerender() {\n\toptions.__test__previousDebounce = options.debounceRendering;\n\toptions.debounceRendering = cb => (options.__test__drainQueue = cb);\n\treturn () => options.__test__drainQueue && options.__test__drainQueue();\n}\n\nconst isThenable = value => value != null && typeof value.then == 'function';\n\n/** Depth of nested calls to `act`. */\nlet actDepth = 0;\n\n/**\n * Run a test function, and flush all effects and rerenders after invoking it.\n *\n * Returns a Promise which resolves \"immediately\" if the callback is\n * synchronous or when the callback's result resolves if it is asynchronous.\n *\n * @param {() => void|Promise<void>} cb The function under test. This may be sync or async.\n * @return {Promise<void>}\n */\nexport function act(cb) {\n\tif (++actDepth > 1) {\n\t\t// If calls to `act` are nested, a flush happens only when the\n\t\t// outermost call returns. In the inner call, we just execute the\n\t\t// callback and return since the infrastructure for flushing has already\n\t\t// been set up.\n\t\t//\n\t\t// If an exception occurs, the outermost `act` will handle cleanup.\n\t\ttry {\n\t\t\tconst result = cb();\n\t\t\tif (isThenable(result)) {\n\t\t\t\treturn result.then(\n\t\t\t\t\t() => {\n\t\t\t\t\t\t--actDepth;\n\t\t\t\t\t},\n\t\t\t\t\te => {\n\t\t\t\t\t\t--actDepth;\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t--actDepth;\n\t\t\tthrow e;\n\t\t}\n\t\t--actDepth;\n\t\treturn Promise.resolve();\n\t}\n\n\tconst previousRequestAnimationFrame = options.requestAnimationFrame;\n\tconst rerender = setupRerender();\n\n\t/** @type {() => void} */\n\tlet flushes = [],\n\t\ttoFlush;\n\n\t// Override requestAnimationFrame so we can flush pending hooks.\n\toptions.requestAnimationFrame = fc => flushes.push(fc);\n\n\tconst finish = () => {\n\t\ttry {\n\t\t\trerender();\n\t\t\twhile (flushes.length) {\n\t\t\t\ttoFlush = flushes;\n\t\t\t\tflushes = [];\n\n\t\t\t\ttoFlush.forEach(x => x());\n\t\t\t\trerender();\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tif (!err) {\n\t\t\t\terr = e;\n\t\t\t}\n\t\t} finally {\n\t\t\tteardown();\n\t\t}\n\n\t\toptions.requestAnimationFrame = previousRequestAnimationFrame;\n\t\t--actDepth;\n\t};\n\n\tlet err;\n\tlet result;\n\n\ttry {\n\t\tresult = cb();\n\t} catch (e) {\n\t\terr = e;\n\t}\n\n\tif (isThenable(result)) {\n\t\treturn result.then(finish, err => {\n\t\t\tfinish();\n\t\t\tthrow err;\n\t\t});\n\t}\n\n\t// nb. If the callback is synchronous, effects must be flushed before\n\t// `act` returns, so that the caller does not have to await the result,\n\t// even though React recommends this.\n\tfinish();\n\tif (err) {\n\t\tthrow err;\n\t}\n\treturn Promise.resolve();\n}\n\n/**\n * Teardown test environment and reset preact's internal state\n */\nexport function teardown() {\n\tif (options.__test__drainQueue) {\n\t\t// Flush any pending updates leftover by test\n\t\toptions.__test__drainQueue();\n\t\tdelete options.__test__drainQueue;\n\t}\n\n\tif (typeof options.__test__previousDebounce != 'undefined') {\n\t\toptions.debounceRendering = options.__test__previousDebounce;\n\t\tdelete options.__test__previousDebounce;\n\t} else {\n\t\toptions.debounceRendering = undefined;\n\t}\n}\n"
  },
  {
    "path": "test-utils/test/shared/act.test.jsx",
    "content": "import { options, createElement, render } from 'preact';\nimport { useEffect, useReducer, useState } from 'preact/hooks';\nimport { act } from 'preact/test-utils';\nimport { setupScratch, teardown } from '../../../test/_util/helpers';\nimport { vi } from 'vitest';\n\n// IE11 doesn't support `new Event()`\nfunction createEvent(name) {\n\tif (typeof Event == 'function') return new Event(name);\n\n\tconst event = document.createEvent('Event');\n\tevent.initEvent(name, true, true);\n\treturn event;\n}\n\ndescribe('act', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = setupScratch();\n\t});\n\n\tafterEach(() => {\n\t\tteardown(scratch);\n\t\toptions.debounceRendering = undefined;\n\t});\n\n\tit('should reset options after act finishes', () => {\n\t\texpect(options.requestAnimationFrame).to.equal(undefined);\n\t\tact(() => null);\n\t\texpect(options.requestAnimationFrame).to.equal(undefined);\n\t});\n\n\tit('should flush pending effects', () => {\n\t\tlet spy = vi.fn();\n\t\tfunction StateContainer() {\n\t\t\tuseEffect(spy);\n\t\t\treturn <div />;\n\t\t}\n\t\tact(() => render(<StateContainer />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t});\n\n\tit('should flush pending and initial effects', () => {\n\t\tconst spy = vi.fn();\n\t\tfunction StateContainer() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tuseEffect(() => spy(), [count]);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Count: {count}</p>\n\t\t\t\t\t<button onClick={() => setCount(c => c + 11)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tact(() => render(<StateContainer />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.textContent).to.include('Count: 0');\n\t\tact(() => {\n\t\t\tconst button = scratch.querySelector('button');\n\t\t\tbutton.click();\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(scratch.textContent).to.include('Count: 0');\n\t\t});\n\t\texpect(spy).toHaveBeenCalledTimes(2);\n\t\texpect(scratch.textContent).to.include('Count: 1');\n\t});\n\n\tit('should flush series of hooks', () => {\n\t\tconst spy = vi.fn();\n\t\tconst spy2 = vi.fn();\n\t\tfunction StateContainer() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tuseEffect(() => {\n\t\t\t\tspy();\n\t\t\t\tif (count === 1) {\n\t\t\t\t\tsetCount(() => 2);\n\t\t\t\t}\n\t\t\t}, [count]);\n\t\t\tuseEffect(() => {\n\t\t\t\tif (count === 2) {\n\t\t\t\t\tspy2();\n\t\t\t\t\tsetCount(() => 4);\n\t\t\t\t\treturn () => setCount(() => 3);\n\t\t\t\t}\n\t\t\t}, [count]);\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Count: {count}</p>\n\t\t\t\t\t<button onClick={() => setCount(c => c + 1)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t\tact(() => render(<StateContainer />, scratch));\n\t\texpect(spy).toHaveBeenCalledOnce();\n\t\texpect(scratch.textContent).to.include('Count: 0');\n\t\tact(() => {\n\t\t\tconst button = scratch.querySelector('button');\n\t\t\tbutton.click();\n\t\t});\n\t\texpect(spy).toHaveBeenCalledTimes(5);\n\t\texpect(spy2).toHaveBeenCalledOnce();\n\t\texpect(scratch.textContent).to.include('Count: 3');\n\t});\n\n\tit('should drain the queue of hooks', () => {\n\t\tconst spy = vi.fn();\n\t\tfunction StateContainer() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tuseEffect(() => spy());\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\t<p>Count: {count}</p>\n\t\t\t\t\t<button onClick={() => setCount(c => c + 11)} />\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\trender(<StateContainer />, scratch);\n\t\texpect(scratch.textContent).to.include('Count: 0');\n\t\tact(() => {\n\t\t\tconst button = scratch.querySelector('button');\n\t\t\tbutton.click();\n\t\t\texpect(scratch.textContent).to.include('Count: 0');\n\t\t});\n\t\texpect(scratch.textContent).to.include('Count: 1');\n\t});\n\n\tit('should restore options.requestAnimationFrame', () => {\n\t\tconst spy = vi.fn();\n\n\t\toptions.requestAnimationFrame = spy;\n\t\tact(() => null);\n\n\t\texpect(options.requestAnimationFrame).to.equal(spy);\n\t\texpect(spy).not.toHaveBeenCalled();\n\t});\n\n\tit('should restore options.debounceRendering', () => {\n\t\tconst spy = vi.fn();\n\n\t\toptions.debounceRendering = spy;\n\t\tact(() => null);\n\n\t\texpect(options.debounceRendering).to.equal(spy);\n\t\texpect(spy).not.toHaveBeenCalled();\n\t});\n\n\tit('should restore options.debounceRendering when it was undefined before', () => {\n\t\tact(() => null);\n\t\texpect(options.debounceRendering).to.equal(undefined);\n\t});\n\n\tit('should flush state updates if there are pending state updates before `act` call', () => {\n\t\tfunction CounterButton() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tconst increment = () => setCount(count => count + 1);\n\t\t\treturn <button onClick={increment}>{count}</button>;\n\t\t}\n\n\t\trender(<CounterButton />, scratch);\n\t\tconst button = scratch.querySelector('button');\n\n\t\t// Click button. This will schedule an update which is deferred, as is\n\t\t// normal for Preact, since it happens outside an `act` call.\n\t\tbutton.dispatchEvent(createEvent('click'));\n\n\t\texpect(button.textContent).to.equal('0');\n\n\t\tact(() => {\n\t\t\t// Click button a second time. This will schedule a second update.\n\t\t\tbutton.dispatchEvent(createEvent('click'));\n\t\t});\n\t\t// All state updates should be applied synchronously after the `act`\n\t\t// callback has run but before `act` returns.\n\t\texpect(button.textContent).to.equal('2');\n\t});\n\n\tit('should flush effects if there are pending effects before `act` call', () => {\n\t\tfunction Counter() {\n\t\t\tconst [count, setCount] = useState(0);\n\t\t\tuseEffect(() => {\n\t\t\t\tsetCount(count => count + 1);\n\t\t\t}, []);\n\t\t\treturn <div>{count}</div>;\n\t\t}\n\n\t\t// Render a component which schedules an effect outside of an `act`\n\t\t// call. This will be scheduled to execute after the next paint as usual.\n\t\trender(<Counter />, scratch);\n\t\texpect(scratch.firstChild.textContent).to.equal('0');\n\n\t\t// Render a component inside an `act` call, this effect should be\n\t\t// executed synchronously before `act` returns.\n\t\tact(() => {\n\t\t\trender(<div />, scratch);\n\t\t\trender(<Counter />, scratch);\n\t\t});\n\t\texpect(scratch.firstChild.textContent).to.equal('1');\n\t});\n\n\tit('returns a Promise if invoked with a sync callback', () => {\n\t\tconst result = act(() => {});\n\t\texpect(result.then).to.be.a('function');\n\t\treturn result;\n\t});\n\n\tit('returns a Promise if invoked with an async callback', () => {\n\t\tconst result = act(async () => {});\n\t\texpect(result.then).to.be.a('function');\n\t\treturn result;\n\t});\n\n\tit('should await \"thenable\" result of callback before flushing', async () => {\n\t\tconst events = [];\n\n\t\tfunction TestComponent() {\n\t\t\tuseEffect(() => {\n\t\t\t\tevents.push('flushed effect');\n\t\t\t}, []);\n\t\t\tevents.push('scheduled effect');\n\t\t\treturn <div>Test</div>;\n\t\t}\n\n\t\tconst delay = ms => new Promise(resolve => setTimeout(resolve, ms));\n\n\t\tevents.push('began test');\n\t\tconst acted = act(async () => {\n\t\t\tevents.push('began act callback');\n\t\t\tawait delay(1);\n\t\t\trender(<TestComponent />, scratch);\n\t\t\tevents.push('end act callback');\n\t\t});\n\t\tevents.push('act returned');\n\t\tawait acted;\n\t\tevents.push('act result resolved');\n\n\t\texpect(events).to.deep.equal([\n\t\t\t'began test',\n\t\t\t'began act callback',\n\t\t\t'act returned',\n\t\t\t'scheduled effect',\n\t\t\t'end act callback',\n\t\t\t'flushed effect',\n\t\t\t'act result resolved'\n\t\t]);\n\t});\n\n\tcontext('when `act` calls are nested', () => {\n\t\tit('should invoke nested sync callback and return a Promise', () => {\n\t\t\tlet innerResult;\n\t\t\tconst spy = vi.fn();\n\n\t\t\tact(() => {\n\t\t\t\tinnerResult = act(spy);\n\t\t\t});\n\n\t\t\texpect(spy).toHaveBeenCalledOnce();\n\t\t\texpect(innerResult.then).to.be.a('function');\n\t\t});\n\n\t\tit('should invoke nested async callback and return a Promise', async () => {\n\t\t\tconst events = [];\n\n\t\t\tawait act(async () => {\n\t\t\t\tevents.push('began outer act callback');\n\t\t\t\tawait act(async () => {\n\t\t\t\t\tevents.push('began inner act callback');\n\t\t\t\t\tawait Promise.resolve();\n\t\t\t\t\tevents.push('end inner act callback');\n\t\t\t\t});\n\t\t\t\tevents.push('end outer act callback');\n\t\t\t});\n\t\t\tevents.push('act finished');\n\n\t\t\texpect(events).to.deep.equal([\n\t\t\t\t'began outer act callback',\n\t\t\t\t'began inner act callback',\n\t\t\t\t'end inner act callback',\n\t\t\t\t'end outer act callback',\n\t\t\t\t'act finished'\n\t\t\t]);\n\t\t});\n\n\t\tit('should only flush effects when outer `act` call returns', () => {\n\t\t\tlet counter = 0;\n\n\t\t\tfunction Widget() {\n\t\t\t\tuseEffect(() => {\n\t\t\t\t\t++counter;\n\t\t\t\t});\n\t\t\t\tconst [, forceUpdate] = useReducer(x => x + 1, 0);\n\t\t\t\treturn <button onClick={forceUpdate}>test</button>;\n\t\t\t}\n\n\t\t\tact(() => {\n\t\t\t\trender(<Widget />, scratch);\n\t\t\t\tconst button = scratch.querySelector('button');\n\t\t\t\texpect(counter).to.equal(0);\n\n\t\t\t\tact(() => {\n\t\t\t\t\tbutton.dispatchEvent(createEvent('click'));\n\t\t\t\t});\n\n\t\t\t\t// Effect triggered by inner `act` call should not have been\n\t\t\t\t// flushed yet.\n\t\t\t\texpect(counter).to.equal(0);\n\t\t\t});\n\n\t\t\t// Effects triggered by inner `act` call should now have been\n\t\t\t// flushed.\n\t\t\texpect(counter).to.equal(2);\n\t\t});\n\n\t\tit('should only flush updates when outer `act` call returns', () => {\n\t\t\tfunction Button() {\n\t\t\t\tconst [count, setCount] = useState(0);\n\t\t\t\tconst increment = () => setCount(count => count + 1);\n\t\t\t\treturn <button onClick={increment}>{count}</button>;\n\t\t\t}\n\n\t\t\trender(<Button />, scratch);\n\t\t\tconst button = scratch.querySelector('button');\n\t\t\texpect(button.textContent).to.equal('0');\n\n\t\t\tact(() => {\n\t\t\t\tact(() => {\n\t\t\t\t\tbutton.dispatchEvent(createEvent('click'));\n\t\t\t\t});\n\n\t\t\t\t// Update triggered by inner `act` call should not have been\n\t\t\t\t// flushed yet.\n\t\t\t\texpect(button.textContent).to.equal('0');\n\t\t\t});\n\n\t\t\t// Updates from outer and inner `act` calls should now have been\n\t\t\t// flushed.\n\t\t\texpect(button.textContent).to.equal('1');\n\t\t});\n\t});\n\n\tdescribe('when `act` callback throws an exception', () => {\n\t\tfunction BrokenWidget() {\n\t\t\tthrow new Error('BrokenWidget is broken');\n\t\t}\n\n\t\tlet effectCount;\n\n\t\tfunction WorkingWidget() {\n\t\t\tconst [count, setCount] = useState(0);\n\n\t\t\tuseEffect(() => {\n\t\t\t\t++effectCount;\n\t\t\t}, []);\n\n\t\t\tif (count === 0) {\n\t\t\t\tsetCount(1);\n\t\t\t}\n\n\t\t\treturn <div>{count}</div>;\n\t\t}\n\n\t\tbeforeEach(() => {\n\t\t\teffectCount = 0;\n\t\t});\n\n\t\tconst renderBroken = () => {\n\t\t\tact(() => {\n\t\t\t\trender(<BrokenWidget />, scratch);\n\t\t\t});\n\t\t};\n\n\t\tconst renderWorking = () => {\n\t\t\tact(() => {\n\t\t\t\trender(<WorkingWidget />, scratch);\n\t\t\t});\n\t\t};\n\n\t\tconst tryRenderBroken = () => {\n\t\t\ttry {\n\t\t\t\trenderBroken();\n\t\t\t} catch (e) {}\n\t\t};\n\n\t\tconst tryNestedRenderBroken = () => {\n\t\t\tact(() => {\n\t\t\t\ttryRenderBroken();\n\t\t\t});\n\t\t};\n\n\t\tdescribe('synchronously', () => {\n\t\t\tit('should rethrow the exception', () => {\n\t\t\t\texpect(renderBroken).to.throw('BrokenWidget is broken');\n\t\t\t});\n\n\t\t\tit('should not affect state updates in future renders', () => {\n\t\t\t\ttryRenderBroken();\n\t\t\t\trenderWorking();\n\t\t\t\texpect(scratch.textContent).to.equal('1');\n\t\t\t});\n\n\t\t\tit('should not affect state updates in future renders when nested `act` throws an exception', () => {\n\t\t\t\ttryNestedRenderBroken();\n\t\t\t\trenderWorking();\n\t\t\t\texpect(scratch.textContent).to.equal('1');\n\t\t\t});\n\n\t\t\tit('should not affect effects in future renders', () => {\n\t\t\t\ttryRenderBroken();\n\t\t\t\trenderWorking();\n\t\t\t\texpect(effectCount).to.equal(1);\n\t\t\t});\n\t\t});\n\n\t\tdescribe('asynchronously', () => {\n\t\t\tconst renderBrokenAsync = async () => {\n\t\t\t\tawait act(async () => {\n\t\t\t\t\trender(<BrokenWidget />, scratch);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tit('should rethrow the exception', async () => {\n\t\t\t\tlet err;\n\t\t\t\ttry {\n\t\t\t\t\tawait renderBrokenAsync();\n\t\t\t\t} catch (e) {\n\t\t\t\t\terr = e;\n\t\t\t\t}\n\t\t\t\texpect(err.message).to.equal('BrokenWidget is broken');\n\t\t\t});\n\n\t\t\tit('should rethrow the exception in nested act calls', async () => {\n\t\t\t\tlet err;\n\t\t\t\ttry {\n\t\t\t\t\tawait act(async () => {\n\t\t\t\t\t\tawait renderBrokenAsync();\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\terr = e;\n\t\t\t\t}\n\t\t\t\texpect(err.message).to.equal('BrokenWidget is broken');\n\t\t\t});\n\n\t\t\tit('should not affect state updates in future renders', async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait renderBrokenAsync();\n\t\t\t\t} catch (e) {}\n\n\t\t\t\trenderWorking();\n\t\t\t\texpect(scratch.textContent).to.equal('1');\n\t\t\t});\n\n\t\t\tit('should not affect effects in future renders', async () => {\n\t\t\t\ttry {\n\t\t\t\t\tawait renderBrokenAsync();\n\t\t\t\t} catch (e) {}\n\n\t\t\t\trenderWorking();\n\t\t\t\texpect(effectCount).to.equal(1);\n\t\t\t});\n\t\t});\n\n\t\tdescribe('in an effect', () => {\n\t\t\tfunction BrokenEffect() {\n\t\t\t\tuseEffect(() => {\n\t\t\t\t\tthrow new Error('BrokenEffect effect');\n\t\t\t\t}, []);\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst renderBrokenEffect = () => {\n\t\t\t\tact(() => {\n\t\t\t\t\trender(<BrokenEffect />, scratch);\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tit('should rethrow the exception', () => {\n\t\t\t\texpect(renderBrokenEffect).to.throw('BrokenEffect effect');\n\t\t\t});\n\n\t\t\tit('should not affect state updates in future renders', () => {\n\t\t\t\ttry {\n\t\t\t\t\trenderBrokenEffect();\n\t\t\t\t} catch (e) {}\n\n\t\t\t\trenderWorking();\n\t\t\t\texpect(scratch.textContent).to.equal('1');\n\t\t\t});\n\n\t\t\tit('should restore custom `debounceRendering` hook', () => {\n\t\t\t\tconst prevDebounce = options.debounceRendering;\n\t\t\t\tconst tempDebounce = () => {};\n\t\t\t\toptions.debounceRendering = tempDebounce;\n\n\t\t\t\ttry {\n\t\t\t\t\trenderBrokenEffect();\n\t\t\t\t} catch (e) {}\n\n\t\t\t\ttry {\n\t\t\t\t\texpect(options.debounceRendering).to.equal(tempDebounce);\n\t\t\t\t} finally {\n\t\t\t\t\toptions.debounceRendering = prevDebounce;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit('should not affect effects in future renders', () => {\n\t\t\t\ttry {\n\t\t\t\t\trenderBrokenEffect();\n\t\t\t\t} catch (e) {}\n\n\t\t\t\trenderWorking();\n\t\t\t\texpect(effectCount).to.equal(1);\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('act function with finish implementations', () => {\n\t\tbeforeEach(function () {\n\t\t\toptions.requestAnimationFrame = null;\n\t\t});\n\n\t\tit('should execute the flush callback using single flush', () => {\n\t\t\tlet called = false;\n\n\t\t\tact(() => {\n\t\t\t\toptions.requestAnimationFrame(() => {\n\t\t\t\t\tcalled = true;\n\t\t\t\t});\n\t\t\t});\n\n\t\t\texpect(called).to.be.true;\n\t\t});\n\n\t\tit('should execute all callbacks using array flush', () => {\n\t\t\tlet callCount = 0;\n\n\t\t\tact(() => {\n\t\t\t\toptions.requestAnimationFrame(() => callCount++);\n\t\t\t\toptions.requestAnimationFrame(() => callCount++);\n\t\t\t\toptions.requestAnimationFrame(() => callCount++);\n\t\t\t});\n\n\t\t\texpect(callCount).to.equal(3);\n\t\t});\n\n\t\tit('should handle errors in single flush', () => {\n\t\t\texpect(() => {\n\t\t\t\tact(() => {\n\t\t\t\t\toptions.requestAnimationFrame(() => {\n\t\t\t\t\t\tthrow new Error('Single flush error');\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}).to.throw('Single flush error');\n\t\t});\n\n\t\tit('should handle errors in array flush', () => {\n\t\t\texpect(() => {\n\t\t\t\tact(() => {\n\t\t\t\t\toptions.requestAnimationFrame(() => {\n\t\t\t\t\t\tthrow new Error('Array flush error');\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}).to.throw('Array flush error');\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test-utils/test/shared/rerender.test.jsx",
    "content": "import { options, createElement, render, Component } from 'preact';\nimport { teardown, setupRerender } from 'preact/test-utils';\nimport { vi } from 'vitest';\n\ndescribe('setupRerender & teardown', () => {\n\t/** @type {HTMLDivElement} */\n\tlet scratch;\n\n\tbeforeEach(() => {\n\t\tscratch = document.createElement('div');\n\t});\n\n\tit('should restore previous debounce', () => {\n\t\tlet spy = (options.debounceRendering = vi.fn());\n\n\t\tsetupRerender();\n\t\tteardown();\n\n\t\texpect(options.debounceRendering).to.equal(spy);\n\t});\n\n\tit('teardown should flush the queue', () => {\n\t\t/** @type {() => void} */\n\t\tlet increment;\n\t\tclass Counter extends Component {\n\t\t\tconstructor(props) {\n\t\t\t\tsuper(props);\n\n\t\t\t\tthis.state = { count: 0 };\n\t\t\t\tincrement = () => this.setState({ count: this.state.count + 1 });\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\treturn <div>{this.state.count}</div>;\n\t\t\t}\n\t\t}\n\n\t\tvi.spyOn(Counter.prototype, 'render');\n\n\t\t// Setup rerender\n\t\tsetupRerender();\n\n\t\t// Initial render\n\t\trender(<Counter />, scratch);\n\t\texpect(Counter.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<div>0</div>');\n\n\t\t// queue rerender\n\t\tincrement();\n\t\texpect(Counter.prototype.render).toHaveBeenCalledOnce();\n\t\texpect(scratch.innerHTML).to.equal('<div>0</div>');\n\n\t\t// Pretend test forgot to call rerender. Teardown should do that\n\t\tteardown();\n\t\texpect(Counter.prototype.render).toHaveBeenCalledTimes(2);\n\t\texpect(scratch.innerHTML).to.equal('<div>1</div>');\n\t});\n});\n"
  },
  {
    "path": "types/weak-key.d.ts",
    "content": "declare global {\n\texport interface WeakKeyTypes {\n\t\tobject: object;\n\t}\n\n\texport type WeakKey = WeakKeyTypes[keyof WeakKeyTypes];\n}\n\nexport {};\n"
  },
  {
    "path": "vitest.config.mjs",
    "content": "import { defineConfig } from 'vitest/config';\nimport { transformAsync } from '@babel/core';\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\n\nconst MINIFY = process.env.MINIFY === 'true';\nconst COVERAGE = process.env.COVERAGE === 'true';\n\nconst root = path.resolve(__dirname);\nconst alias = {\n\t'^react$': path.join(\n\t\troot,\n\t\tMINIFY ? 'compat/dist/compat.mjs' : 'compat/src/index.js'\n\t),\n\t'^react-dom$': path.join(\n\t\troot,\n\t\tMINIFY ? 'compat/dist/compat.mjs' : 'compat/src/index.js'\n\t),\n\t'^preact$': path.join(root, MINIFY ? 'dist/preact.mjs' : 'src/index.js'),\n\t'^preact/compat$': path.join(\n\t\troot,\n\t\tMINIFY ? 'compat/dist/compat.mjs' : 'compat/src/index.js'\n\t),\n\t'^preact/jsx-runtime$': path.join(\n\t\troot,\n\t\tMINIFY ? 'jsx-runtime/dist/jsxRuntime.mjs' : 'jsx-runtime/src/index.js'\n\t),\n\t'^preact/jsx-runtime/src$': path.join(\n\t\troot,\n\t\tMINIFY ? 'jsx-runtime/dist/jsxRuntime.mjs' : 'jsx-runtime/src'\n\t),\n\t'^preact/jsx-dev-runtime$': path.join(\n\t\troot,\n\t\tMINIFY\n\t\t\t? 'jsx-dev-runtime/dist/jsx-dev-runtime.js'\n\t\t\t: 'jsx-dev-runtime/src/index.js'\n\t),\n\t'^preact/debug$': path.join(\n\t\troot,\n\t\tMINIFY ? 'debug/dist/debug.mjs' : 'debug/src/index.js'\n\t),\n\t'^preact/devtools$': path.join(\n\t\troot,\n\t\tMINIFY ? 'devtools/dist/devtools.js' : 'devtools/src/index.js'\n\t),\n\t'^preact/hooks$': path.join(\n\t\troot,\n\t\tMINIFY ? 'hooks/dist/hooks.mjs' : 'hooks/src/index.js'\n\t),\n\t'^preact/test-utils$': path.join(\n\t\troot,\n\t\tMINIFY ? 'test-utils/dist/testUtils.mjs' : 'test-utils/src/index.js'\n\t)\n};\n\nconst rollupAlias = [\n\t{\n\t\tfind: /^react$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'compat/dist/compat.mjs')\n\t\t\t: path.join(root, 'compat/src/index.js')\n\t},\n\t{\n\t\tfind: /^react-dom$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'compat/dist/compat.mjs')\n\t\t\t: path.join(root, 'compat/src/index.js')\n\t},\n\t{ find: /^preact$/, replacement: path.join(root, 'src/index.js') },\n\t{\n\t\tfind: /^preact\\/compat$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'compat/dist/compat.mjs')\n\t\t\t: path.join(root, 'compat/src/index.js')\n\t},\n\t{\n\t\tfind: /^preact\\/jsx-runtime$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'jsx-runtime/dist/jsxRuntime.mjs')\n\t\t\t: path.join(root, 'jsx-runtime/src/index.js')\n\t},\n\t{\n\t\tfind: /^preact\\/jsx-runtime\\/src$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'jsx-runtime/dist/jsxRuntime.mjs')\n\t\t\t: path.join(root, 'jsx-runtime/src')\n\t},\n\t{\n\t\tfind: /^preact\\/jsx-dev-runtime$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'jsx-runtime/dist/jsxRuntime.mjs')\n\t\t\t: path.join(root, 'jsx-runtime/src/index.js')\n\t},\n\t{\n\t\tfind: /^preact\\/debug$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'debug/dist/debug.mjs')\n\t\t\t: path.join(root, 'debug/src/index.js')\n\t},\n\t{\n\t\tfind: /^preact\\/devtools$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'devtools/dist/devtools.mjs')\n\t\t\t: path.join(root, 'devtools/src/index.js')\n\t},\n\t{\n\t\tfind: /^preact\\/hooks$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'hooks/dist/hooks.mjs')\n\t\t\t: path.join(root, 'hooks/src/index.js')\n\t},\n\t{\n\t\tfind: /^preact\\/test-utils$/,\n\t\treplacement: MINIFY\n\t\t\t? path.join(root, 'test-utils/dist/testUtils.mjs')\n\t\t\t: path.join(root, 'test-utils/src/index.js')\n\t}\n];\n\nconst rename = {};\nconst mangle = readFileSync('./mangle.json', 'utf8');\nconst mangleJson = JSON.parse(mangle);\nfor (let prop in mangleJson.props.props) {\n\tlet name = prop;\n\tif (name[0] === '$') {\n\t\tname = name.slice(1);\n\t}\n\n\trename[name] = mangleJson.props.props[prop];\n}\n\nexport default defineConfig({\n\tresolve: {\n\t\talias: rollupAlias,\n\t\tdedupe: ['preact']\n\t},\n\tesbuild: {\n\t\tloader: 'jsx',\n\t\tinclude: /.*\\.jsx$/,\n\t\texclude: ['node_nodules'],\n\t\tjsx: 'transform',\n\t\tjsxFactory: 'createElement',\n\t\tjsxFragment: 'Fragment',\n\t},\n\tplugins: [\n\t\t{\n\t\t\tname: 'rename-mangle-properties',\n\t\t\tasync transform(code, id) {\n\t\t\t\tif (id.includes('node_modules')) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst shouldTransform = id.includes('src') || id.includes('test');\n\t\t\t\tif (!shouldTransform) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst transformed = await transformAsync(code, {\n\t\t\t\t\tfilename: id,\n\t\t\t\t\tconfigFile: false,\n\t\t\t\t\tplugins: [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t'babel-plugin-transform-rename-properties',\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\trename\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t],\n\t\t\t\t\tinclude: ['**/src/**/*.js', '**/test/**/*.js', '**/test/**/*.jsx'],\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tcode: transformed.code,\n\t\t\t\t\tmap: transformed.map\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t],\n\toptimizeDeps: {\n\t\texclude: [\n\t\t\t'preact',\n\t\t\t'preact/compat',\n\t\t\t'preact/test-utils',\n\t\t\t'preact/debug',\n\t\t\t'preact/hooks',\n\t\t\t'preact/devtools',\n\t\t\t'preact/jsx-runtime',\n\t\t\t'preact/jsx-dev-runtime',\n\t\t\t'preact-router',\n\t\t\t'react',\n\t\t\t'react-dom'\n\t\t],\n\t\tesbuildOptions: {\n\t\t\talias,\n\t\t}\n\t},\n\ttest: {\n\t\tcache: false,\n\t\tglobals: true,\n\t\tcoverage: {\n\t\t\tenabled: COVERAGE,\n\t\t\tinclude: MINIFY\n\t\t\t\t? [\n\t\t\t\t\t\t'dist/preact.mjs',\n\t\t\t\t\t\t'compat/dist/compat.mjs',\n\t\t\t\t\t\t'devtools/dist/devtools.mjs',\n\t\t\t\t\t\t'jsx-runtime/dist/jsxRuntime.mjs',\n\t\t\t\t\t\t'debug/dist/debug.mjs',\n\t\t\t\t\t\t'hooks/dist/hooks.mjs',\n\t\t\t\t\t\t'test-utils/dist/testUtils.mjs'\n\t\t\t\t\t]\n\t\t\t\t: [\n\t\t\t\t\t\t'src/**/*',\n\t\t\t\t\t\t'debug/src/**/*',\n\t\t\t\t\t\t'devtools/src/**/*',\n\t\t\t\t\t\t'hooks/src/**/*',\n\t\t\t\t\t\t'compeat/src/**/*',\n\t\t\t\t\t\t'jsx-runtime/src/**/*',\n\t\t\t\t\t\t'test-utils/src/**/*'\n\t\t\t\t\t],\n\t\t\textension: ['.js', '.mjs'],\n\t\t\tprovider: 'v8',\n\t\t\treporter: ['html', 'lcovonly', 'text-summary'],\n\t\t\treportsDirectory: './coverage'\n\t\t},\n\t\tprojects: [\n\t\t\t{\n\t\t\t\textends: true,\n\t\t\t\ttest: {\n\t\t\t\t\tinclude: ['./test/{shared,node,ts}/**/*.test.js?(x)']\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\textends: true,\n\t\t\t\ttest: {\n\t\t\t\t\tinclude: [\n\t\t\t\t\t\t'{debug,devtools,hooks,compat,test-utils,jsx-runtime}/test/{browser,shared}/**/*.test.js?(x)',\n\t\t\t\t\t\t'./test/{browser,shared}/**/*.test.js?(x)'\n\t\t\t\t\t],\n\t\t\t\t\tsetupFiles: ['./vitest.setup.js'],\n\t\t\t\t\t// dangerouslyIgnoreUnhandledErrors: true,\n\t\t\t\t\tbrowser: {\n\t\t\t\t\t\t// TODO: isolate doesn't work it leaks across all pages\n\t\t\t\t\t\t// isolate: false,\n\t\t\t\t\t\tprovider: 'playwright',\n\t\t\t\t\t\tenabled: true,\n\t\t\t\t\t\tscreenshotFailures: false,\n\t\t\t\t\t\theadless: true,\n\t\t\t\t\t\tinstances: [{ browser: 'chromium' }]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n});\n"
  },
  {
    "path": "vitest.setup.js",
    "content": "import { expect, describe } from 'vitest';\n\nglobalThis.context = describe;\n\nwindow.addEventListener('error', () => {});\n\n// Something that's loaded before this file polyfills Symbol object.\n// We need to verify that it works in IE without that.\nif (/Trident/.test(window.navigator.userAgent)) {\n\twindow.Symbol = undefined;\n}\n\n// Fix Function#name on browsers that do not support it (IE).\n// Taken from: https://stackoverflow.com/a/17056530/755391\nif (!function f() {}.name) {\n\tObject.defineProperty(Function.prototype, 'name', {\n\t\tget() {\n\t\t\tlet name = (this.toString().match(/^function\\s*([^\\s(]+)/) || [])[1];\n\t\t\t// For better performance only parse once, and then cache the\n\t\t\t// result through a new accessor for repeated access.\n\t\t\tObject.defineProperty(this, 'name', { value: name });\n\t\t\treturn name;\n\t\t}\n\t});\n}\n\nexpect.extend({\n\tequalNode: (obj, expected) => {\n\t\tif (expected == null) {\n\t\t\treturn {\n\t\t\t\tpass: obj == null,\n\t\t\t\tmessage: () => `expected node to \"== null\" but got ${obj} instead.`\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tpass: obj.tagName === expected.tagName && obj === expected,\n\t\t\t\tmessage: () =>\n\t\t\t\t\t`expected node to have tagName ${expected.tagName} but got ${obj.tagName} instead.`\n\t\t\t};\n\t\t}\n\t}\n});\n"
  }
]