[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "content": "# chore: enable prettier trailing commas (#11167)\n134ce6817984bad0f5fb043481502531fee9b1db\n# chore: rename test packages (#11172)\n5170e44920458090b8b43ee9cfe5010c25dfe22b\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: \"\\U0001F41E Bug report\"\ndescription: Report an issue with Vite\nlabels: [pending triage]\ntype: Bug\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: textarea\n    id: bug-description\n    attributes:\n      label: Describe the bug\n      description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!\n      placeholder: I am doing ... What I expect is ... What actually happening is ...\n    validations:\n      required: true\n  - type: input\n    id: reproduction\n    attributes:\n      label: Reproduction\n      description: Please provide a link via [vite.new](https://vite.new/) or a link to a repo that can reproduce the problem you ran into. `npm create vite@latest` and `npm create vite-extra@latest` (for SSR or library repros) can be used as a starter template. A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required ([Why?](https://antfu.me/posts/why-reproductions-are-required)). If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a \"needs reproduction\" label. If no reproduction is provided after 3 days, it will be auto-closed.\n      placeholder: Reproduction URL\n    validations:\n      required: true\n  - type: textarea\n    id: reproduction-steps\n    attributes:\n      label: Steps to reproduce\n      description: Please provide any reproduction steps that may need to be described. E.g. if it happens only when running the dev or build script make sure it's clear which one to use.\n      placeholder: Run `npm install` followed by `npm run dev`\n  - type: textarea\n    id: system-info\n    attributes:\n      label: System Info\n      description: Output of `npx envinfo --system --npmPackages '{vite,@vitejs/*,rollup,rolldown}' --binaries --browsers`\n      render: shell\n      placeholder: System, Binaries, Browsers\n    validations:\n      required: true\n  - type: dropdown\n    id: package-manager\n    attributes:\n      label: Used Package Manager\n      description: Select the used package manager\n      options:\n        - npm\n        - yarn\n        - pnpm\n        - bun\n    validations:\n      required: true\n  - type: textarea\n    id: logs\n    attributes:\n      label: Logs\n      description: |\n        Optional if provided reproduction. Please try not to insert an image but copy paste the log text.\n\n        1. Run `vite` or `vite build` with the `--debug` flag.\n        2. Provide the error log here in the format below.\n\n        ````\n        <details>\n        <summary>Click to expand!</summary>\n\n        ```shell\n        // paste the log text here\n        ```\n        </details>\n        ````\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/vitejs/vite/blob/main/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guidelines](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md).\n          required: true\n        - label: Read the [docs](https://vite.dev/guide).\n          required: true\n        - label: Check that there isn't [already an issue](https://github.com/vitejs/vite/issues) that reports the same bug to avoid creating a duplicate.\n          required: true\n        - label: Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to [vuejs/core](https://github.com/vuejs/core) instead.\n          required: true\n        - label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/vitejs/vite/discussions) or join our [Discord Chat Server](https://chat.vite.dev/).\n          required: true\n        - label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug.\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Vite Plugin React Issues\n    url: https://github.com/vitejs/vite-plugin-react/issues/new/choose\n    about: React related issues should be reported on the vite-plugin-react repository.\n  - name: Vite Plugin Vue Issues\n    url: https://github.com/vitejs/vite-plugin-vue/issues/new/choose\n    about: Vue related issues should be reported on the vite-plugin-vue repository.\n  - name: Discord Chat\n    url: https://chat.vite.dev\n    about: Ask questions and discuss with other Vite users in real time.\n  - name: Questions & Discussions\n    url: https://github.com/vitejs/vite/discussions\n    about: Use GitHub discussions for message-board style questions and discussions.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/docs.yml",
    "content": "name: \"\\U0001F4DA Documentation\"\ndescription: Suggest a change or new page to be added to vite.dev\nlabels: [documentation]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this issue!\n  - type: checkboxes\n    id: documentation_is\n    attributes:\n      label: Documentation is\n      options:\n        - label: Missing\n        - label: Outdated\n        - label: Confusing\n        - label: Not sure?\n  - type: textarea\n    id: description\n    attributes:\n      label: Explain in Detail\n      description: A clear and concise description of your suggestion. If you intend to submit a PR for this issue, tell us in the description. Thanks!\n      placeholder: The description of ... page is not clear. I thought it meant ... but it wasn't.\n    validations:\n      required: true\n  - type: textarea\n    id: suggestion\n    attributes:\n      label: Your Suggestion for Changes\n    validations:\n      required: true\n  - type: input\n    id: reproduction\n    attributes:\n      label: Reproduction\n      description: If you have a reproduction, please provide a link via [vite.new](https://vite.new/) or a link to a repo that can reproduce the problem you ran into. `npm create vite@latest` and `npm create vite-extra@latest` (for SSR or library repros) can be used as a starter template.\n      placeholder: Reproduction URL\n  - type: textarea\n    id: reproduction-steps\n    attributes:\n      label: Steps to reproduce\n      description: Please provide any reproduction steps that may need to be described. E.g. if it happens only when running the dev or build script make sure it's clear which one to use.\n      placeholder: Run `npm install` followed by `npm run dev`\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: \"\\U0001F680 New feature proposal\"\ndescription: Propose a new feature to be added to Vite\nlabels: [\"pending triage\"]\ntype: Feature\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for your interest in the project and taking the time to fill out this feature report!\n  - type: textarea\n    id: feature-description\n    attributes:\n      label: Description\n      description: \"Clear and concise description of the problem. Please make the reason and usecases as detailed as possible. If you intend to submit a PR for this issue, tell us in the description. Thanks!\"\n      placeholder: As a developer using Vite I want [goal / wish] so that [benefit].\n    validations:\n      required: true\n  - type: textarea\n    id: suggested-solution\n    attributes:\n      label: Suggested solution\n      description: \"In module [xy] we could provide following implementation...\"\n    validations:\n      required: true\n  - type: textarea\n    id: alternative\n    attributes:\n      label: Alternative\n      description: Clear and concise description of any alternative solutions or features you've considered.\n  - type: textarea\n    id: additional-context\n    attributes:\n      label: Additional context\n      description: Any other context or screenshots about the feature request here.\n  - type: checkboxes\n    id: checkboxes\n    attributes:\n      label: Validations\n      description: Before submitting the issue, please make sure you do the following\n      options:\n        - label: Follow our [Code of Conduct](https://github.com/vitejs/vite/blob/main/CODE_OF_CONDUCT.md)\n          required: true\n        - label: Read the [Contributing Guidelines](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md).\n          required: true\n        - label: Read the [docs](https://vite.dev/guide).\n          required: true\n        - label: Check that there isn't already an issue that request the same feature to avoid creating a duplicate.\n          required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\n- What is this PR solving? Write a clear and concise description.\n- Reference the issues it solves (e.g. `fixes #123`).\n- What other alternatives have you explored?\n- Are there any parts you think require more attention from reviewers?\n\nAlso, please make sure you do the following:\n\n- Read the Contributing Guidelines at https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md.\n- Check that there isn't already a PR that solves the problem the same way. If you find a duplicate, please help us review it.\n- Update the corresponding documentation if needed.\n- Include relevant tests that fail without this PR but pass with it. If the tests are not included, explain why.\n\nThank you for contributing to Vite!\n-->\n"
  },
  {
    "path": ".github/commit-convention.md",
    "content": "## Git Commit Message Convention\n\n> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).\n\n#### TL;DR:\n\nMessages must be matched by the following regex:\n\n<!-- prettier-ignore -->\n```js\n/^(revert: )?(feat|fix|docs|style|refactor|perf|test|build|ci|chore)(\\(.+\\))?!?: .{1,50}/\n```\n\n#### Examples\n\n```\nfeat(dev): add 'comments' option\nfix(dev): fix dev error\nperf(build)!: remove 'foo' option\nrevert: feat(compiler): add 'comments' option\n```\n\n### Revert\n\nIf the PR reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit\n\n### Scope\n\nThe scope could be anything specifying the place of the commit change. For example `dev`, `build`, `workflow`, `cli` etc...\n\n### Subject\n\nThe subject contains a succinct description of the change:\n\n- use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"\n- don't capitalize the first letter\n- no dot (.) at the end\n"
  },
  {
    "path": ".github/copilot-instructions.md",
    "content": "This is a TypeScript project that implements a frontend build tooling called Vite. Please follow these guidelines when contributing:\n\n## Code Standards\n\n- Run `pnpm run lint` to ensure that your code adheres to the code standards.\n- Run `pnpm run format` to format your code.\n- Build: `pnpm run build`\n- Test: `pnpm run test` (uses Vitest and Playwright)\n\n## Repository Structure\n\n- `docs/`: Documentation\n- `packages/create-vite`: The source code for the `create-vite` command\n- `packages/plugin-legacy`: The source code for the `@vitejs/plugin-legacy` plugin\n- `packages/vite`: The source code for the Vite core\n- `playground/`: E2E tests\n\n## PR Guidelines\n\n### PR Title & Commit Messages\n\n- Follow the [commit message convention](./commit-convention.md)\n\n### PR Description\n\n- What does this PR solve? - Clear problem/feature description\n- Why was this approach chosen? - Implementation rationale\n- If this is a new feature, include a convincing reason.\n- If this adds a new config option, verify problem can't be solved with smarter defaults, existing options, or a plugin\n- If this is a bug fix, explain what caused the bug - Link to relevant code if possible\n\n### Code Style & Standards\n\n- Code follows TypeScript best practices\n- Maintains existing code structure and organization\n- Comments explain \"why\", not \"what\"\n\n### Testing\n\n- Prefer unit tests if it can be tested without using mocks\n- E2E tests should be added in the `playground/` directory\n\n### Documentation\n\n- Update documentation for public API changes\n- Documentation changes go in `docs/` folder\n\n### Other Considerations\n\n- No concerning performance impacts\n"
  },
  {
    "path": ".github/renovate.json5",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\"config:recommended\", \"schedule:weekly\", \"group:allNonMajor\"],\n  \"labels\": [\"dependencies\"],\n  \"ignorePaths\": [\"**/__tests__/**\"],\n  \"rangeStrategy\": \"bump\",\n  \"postUpdateOptions\": [\"pnpmDedupe\"],\n  \"packageRules\": [\n    {\n      \"matchDepTypes\": [\"peerDependencies\"],\n      \"enabled\": false,\n    },\n    {\n      \"matchDepTypes\": [\"action\"],\n      \"pinDigests\": true,\n      \"matchPackageNames\": [\"!actions/{/,}**\", \"!github/{/,}**\"],\n    },\n    {\n      \"groupName\": \"rolldown-related dependencies\",\n      \"matchDepNames\": [\n        \"rolldown\",\n        \"rolldown-plugin-dts\",\n        \"tsdown\",\n        \"@oxc-project/*\",\n        \"oxc-*\",\n      ],\n    },\n  ],\n  \"ignoreDeps\": [\n    // manually bumping\n    \"rollup\",\n    \"node\",\n    \"typescript\",\n    \"@rollup/plugin-dynamic-import-vars\", // prefer version using tinyglobby\n\n    // pinned\n    \"slash3\",\n    \"slash5\",\n    \"vue34\",\n\n    // breaking changes\n    \"kill-port\", // `kill-port:^2.0.0 has perf issues (#8392)\n\n    // v1 is a drop-in replacement for debug, while v2 introduces breaking changes\n    \"obug\",\n  ],\n  \"github-actions\": {\n    \"managerFilePatterns\": [\n      // default values\n      \"/(^|/)(workflow-templates|\\\\.(?:github|gitea|forgejo)/(?:workflows|actions))/.+\\\\.ya?ml$/\",\n      \"/(^|/)action\\\\.ya?ml$/\",\n      // custom value\n      \"/(^|/)docs/guide/static-deploy-github-pages\\\\.yaml$/\",\n    ],\n  },\n  \"customManagers\": [\n    {\n      \"customType\": \"regex\",\n      \"managerFilePatterns\": [\"/packages/create-vite/src/index\\\\.ts$/\"],\n      \"matchStrings\": [\n        \"//\\\\s*renovate:\\\\s+datasource=(?<datasource>\\\\S+)\\\\s+depName=(?<depName>\\\\S+)\\\\s+(?:var|let|const)\\\\s+\\\\S+\\\\s*=\\\\s*[\\\"'](?<currentValue>[^\\\"']+)[\\\"']\",\n      ],\n    },\n  ],\n}\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\nenv:\n  # 7 GiB by default on GitHub, setting to 6 GiB\n  # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources\n  NODE_OPTIONS: --max-old-space-size=6144\n  # install playwright binary manually (because pnpm only runs install script once)\n  PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: \"1\"\n  # Vitest auto retry on flaky segfault\n  VITEST_SEGFAULT_RETRY: 3\n\n# Remove default permissions of GITHUB_TOKEN for security\n# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs\npermissions: {}\n\non:\n  push:\n    branches:\n      - main\n      - release/*\n      - feat/*\n      - fix/*\n      - perf/*\n      - \"v[0-9]+\" # v1, v2, ...\n      - \"v[0-9]+.[0-9]+\" # v4.0, v4.1, ...\n  pull_request:\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.number || github.sha }}\n  cancel-in-progress: true\n\njobs:\n  changed:\n    name: Get changed files\n    runs-on: ubuntu-slim\n    outputs:\n      should_skip: ${{ steps.changed-files.outputs.only_changed == 'true' }}\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n        with:\n          # Assume PRs are less than 50 commits\n          fetch-depth: 50\n\n      - name: Get changed files\n        id: changed-files\n        uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5\n        with:\n          files: |\n            docs/**\n            .github/**\n            !.github/workflows/ci.yml\n            packages/create-vite/template**\n            **.md\n\n  test:\n    needs: changed\n    if: needs.changed.outputs.should_skip != 'true'\n    timeout-minutes: 20\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        os: [ubuntu-latest]\n        node_version: [20, 22, 24]\n        include:\n          # Active LTS + other OS\n          - os: macos-latest\n            node_version: 24\n          - os: windows-latest\n            node_version: 24\n      fail-fast: false\n\n    name: \"Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}\"\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n\n      - name: Set node version to ${{ matrix.node_version }}\n        uses: actions/setup-node@v6\n        with:\n          node-version: ${{ matrix.node_version }}\n          cache: \"pnpm\"\n\n      - name: Install deps\n        run: pnpm install\n\n      # Install playwright's binary under custom directory to cache\n      - name: (non-windows) Set Playwright path and Get playwright version\n        if: runner.os != 'Windows'\n        run: |\n          echo \"PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin\" >> $GITHUB_ENV\n          PLAYWRIGHT_VERSION=\"$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies[\"playwright-chromium\"].version')\"\n          echo \"PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION\" >> $GITHUB_ENV\n      - name: (windows) Set Playwright path and Get playwright version\n        if: runner.os == 'Windows'\n        run: |\n          echo \"PLAYWRIGHT_BROWSERS_PATH=$HOME\\.cache\\playwright-bin\" >> $env:GITHUB_ENV\n          $env:PLAYWRIGHT_VERSION=\"$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies[\"playwright-chromium\"].version')\"\n          echo \"PLAYWRIGHT_VERSION=$env:PLAYWRIGHT_VERSION\" >> $env:GITHUB_ENV\n\n      - name: Cache Playwright's binary\n        uses: actions/cache@v5\n        with:\n          key: ${{ runner.os }}-playwright-bin-v1-${{ env.PLAYWRIGHT_VERSION }}\n          path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}\n          restore-keys: |\n            ${{ runner.os }}-playwright-bin-v1-\n\n      - name: Install Playwright\n        # does not need to explicitly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved\n        run: pnpm playwright install chromium\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Test unit\n        run: pnpm run test-unit\n\n      - name: Test serve\n        run: pnpm run test-serve\n\n      - name: Test build\n        run: pnpm run test-build\n\n  test-passed:\n    if: (!cancelled() && !failure())\n    needs: test\n    runs-on: ubuntu-slim\n    name: Build & Test Passed or Skipped\n    steps:\n      - run: echo \"Build & Test Passed or Skipped\"\n\n  test-failed:\n    if: (!cancelled() && failure())\n    needs: test\n    runs-on: ubuntu-slim\n    name: Build & Test Failed\n    steps:\n      - run: echo \"Build & Test Failed\"\n\n  lint:\n    timeout-minutes: 10\n    runs-on: ubuntu-latest\n    name: \"Lint: node-24, ubuntu-latest\"\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n\n      - name: Set node version to 24\n        uses: actions/setup-node@v6\n        with:\n          node-version: 24\n          cache: \"pnpm\"\n\n      - name: Install deps\n        run: pnpm install\n\n      - name: Build\n        run: pnpm run build\n\n      - name: Lint\n        run: pnpm run lint\n\n      - name: Check formatting\n        run: pnpm prettier --write --log-level=warn . && git diff --exit-code\n\n      - name: Typecheck\n        run: pnpm run typecheck\n\n      - name: Test docs\n        run: pnpm run test-docs\n\n      # From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions\n      - name: Check workflow files\n        run: |\n          bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)\n          ./actionlint -color -shellcheck=\"\"\n"
  },
  {
    "path": ".github/workflows/copilot-setup-steps.yml",
    "content": "on:\n  workflow_dispatch:\n  push:\n    paths:\n      - .github/workflows/copilot-setup-steps.yml\n  pull_request:\n    paths:\n      - .github/workflows/copilot-setup-steps.yml\n\njobs:\n  copilot-setup-steps:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n\n      - name: Set node version to 24\n        uses: actions/setup-node@v6\n        with:\n          node-version: 24\n          cache: \"pnpm\"\n\n      - name: Install deps\n        run: pnpm install\n\n      # Install playwright's binary under custom directory to cache\n      - name: (non-windows) Set Playwright path and Get playwright version\n        if: runner.os != 'Windows'\n        run: |\n          echo \"PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin\" >> $GITHUB_ENV\n          PLAYWRIGHT_VERSION=\"$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies[\"playwright-chromium\"].version')\"\n          echo \"PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION\" >> $GITHUB_ENV\n      - name: (windows) Set Playwright path and Get playwright version\n        if: runner.os == 'Windows'\n        run: |\n          echo \"PLAYWRIGHT_BROWSERS_PATH=$HOME\\.cache\\playwright-bin\" >> $env:GITHUB_ENV\n          $env:PLAYWRIGHT_VERSION=\"$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies[\"playwright-chromium\"].version')\"\n          echo \"PLAYWRIGHT_VERSION=$env:PLAYWRIGHT_VERSION\" >> $env:GITHUB_ENV\n\n      - name: Install Playwright\n        # does not need to explicitly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved\n        run: pnpm playwright install chromium\n"
  },
  {
    "path": ".github/workflows/ecosystem-ci-trigger.yml",
    "content": "name: ecosystem-ci trigger\n\non:\n  issue_comment:\n    types: [created]\n\njobs:\n  trigger:\n    runs-on: ubuntu-slim\n    if: github.repository == 'vitejs/vite' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')\n    permissions:\n      issues: write # to add / delete reactions, post comments\n      pull-requests: write # to read PR data, and to add labels\n      actions: read # to check workflow status\n    steps:\n      - name: Check User Permissions\n        uses: actions/github-script@v8\n        id: check-permissions\n        with:\n          script: |\n            const user = context.payload.sender.login\n            console.log(`Validate user: ${user}`)\n\n            const additionalAllowedUsers = ['lukastaegert']\n\n            let hasTriagePermission = false\n            try {\n              const { data } = await github.rest.repos.getCollaboratorPermissionLevel({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                username: user,\n              });\n              hasTriagePermission = data.user.permissions.triage\n            } catch (e) {\n              console.warn(e)\n            }\n\n            if (hasTriagePermission || additionalAllowedUsers.includes(user)) {\n              console.log('User is allowed. Adding +1 reaction.')\n              await github.rest.reactions.createForIssueComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                comment_id: context.payload.comment.id,\n                content: '+1',\n              })\n            } else {\n              console.log('User is not allowed. Adding -1 reaction.')\n              await github.rest.reactions.createForIssueComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                comment_id: context.payload.comment.id,\n                content: '-1',\n              })\n              throw new Error('User does not have the necessary permissions.')\n            }\n\n      - name: Get PR Data\n        uses: actions/github-script@v8\n        id: get-pr-data\n        with:\n          script: |\n            console.log(`Get PR info: ${context.repo.owner}/${context.repo.repo}#${context.issue.number}`)\n            const { data: pr } = await github.rest.pulls.get({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              pull_number: context.issue.number\n            })\n\n            const commentCreatedAt = new Date(context.payload.comment.created_at)\n            const commitPushedAt = new Date(pr.head.repo.pushed_at)\n\n            console.log(`Comment created at: ${commentCreatedAt.toISOString()}`)\n            console.log(`PR last pushed at: ${commitPushedAt.toISOString()}`)\n\n            // Check if any commits were pushed after the comment was created\n            if (commitPushedAt > commentCreatedAt) {\n              const errorMsg = [\n                '⚠️ Security warning: PR was updated after the trigger command was posted.',\n                '',\n                `Comment posted at: ${commentCreatedAt.toISOString()}`,\n                `PR last pushed at: ${commitPushedAt.toISOString()}`,\n                '',\n                'This could indicate an attempt to inject code after approval.',\n                'Please review the latest changes and re-run /ecosystem-ci run if they are acceptable.'\n              ].join('\\n')\n\n              core.setFailed(errorMsg)\n\n              await github.rest.issues.createComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: context.issue.number,\n                body: errorMsg\n              })\n\n              throw new Error('PR was pushed to after comment was created')\n            }\n\n            core.setOutput('head_sha', pr.head.sha)\n            return {\n              num: context.issue.number,\n              branchName: pr.head.ref,\n              commit: pr.head.sha,\n              repo: pr.head.repo.full_name\n            }\n\n      - name: Check Package Existence\n        uses: actions/github-script@v8\n        id: check-package\n        with:\n          script: |\n            const prData = ${{ steps.get-pr-data.outputs.result }}\n            const url = `https://pkg.pr.new/vite@${prData.commit}`\n            const response = await fetch(url)\n            console.log(`Package check URL: ${url}, Status: ${response.status}`)\n\n            // Add 'rocket' reaction to the issue comment\n            if (response.status === 404) {\n              const { data: reaction } = await github.rest.reactions.createForIssueComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                comment_id: context.payload.comment.id,\n                content: 'rocket',\n              })\n              return { exists: false, reaction: reaction.id }\n            }\n\n            return { exists: true, reaction: null }\n\n      - name: Generate Token\n        id: generate-token\n        uses: actions/create-github-app-token@v3\n        with:\n          app-id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }}\n          private-key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }}\n          repositories: |\n            vite\n            vite-ecosystem-ci\n\n      - name: Trigger Preview Release (if Package Not Found)\n        if: fromJSON(steps.check-package.outputs.result).exists == false\n        uses: actions/github-script@v8\n        id: trigger-preview-release\n        env:\n          PR_DATA: ${{ steps.get-pr-data.outputs.result }}\n        with:\n          github-token: ${{ steps.generate-token.outputs.token }}\n          script: |\n            const prData = JSON.parse(process.env.PR_DATA)\n            console.log('Package not found, triggering preview release...')\n\n            // Add label \"trigger: preview\" to the PR\n            await github.rest.issues.addLabels({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: prData.num,\n              labels: ['trigger: preview']\n            })\n            console.log('Added \"trigger: preview\" label.')\n\n      - name: Wait for Preview Release Completion (if Package Not Found)\n        if: fromJSON(steps.check-package.outputs.result).exists == false\n        uses: actions/github-script@v8\n        id: wait-preview-release\n        env:\n          PR_DATA: ${{ steps.get-pr-data.outputs.result }}\n          REACTION: ${{ fromJSON(steps.check-package.outputs.result).reaction }}\n        with:\n          script: |\n            const prData = JSON.parse(process.env.PR_DATA)\n            const reaction = +process.env.REACTION\n            const workflowFileName = 'preview-release.yml'\n            const workflow = await github.rest.actions.getWorkflow({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              workflow_id: workflowFileName,\n            })\n            const workflowId = workflow.data.id\n            console.log(`Waiting for workflow ID ${workflowId} to complete...`)\n\n            const maxRetries = 60 // Wait up to 10 minutes\n            const delay = 10000 // 10 seconds\n            let completed = false\n\n            for (let i = 0; i < maxRetries; i++) {\n              const runsData = await github.rest.actions.listWorkflowRuns({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                workflow_id: workflowId,\n                head_sha: prData.commit,\n                per_page: 100,\n                page: 1,\n              })\n\n              const runs = runsData.data.workflow_runs\n\n              if (runs.length > 0) {\n                const latestRun = runs[0]\n                console.log(`Latest run status: ${latestRun.status}, conclusion: ${latestRun.conclusion}`)\n                if (latestRun.status === 'completed') {\n                  if (latestRun.conclusion === 'success') {\n                    console.log('Preview release workflow completed successfully.')\n                    completed = true\n                    break\n                  } else if (latestRun.conclusion === 'skipped') {\n                   // noop\n                  } else {\n                    throw new Error('Preview Release workflow failed.')\n                  }\n                }\n              }\n\n              console.log(`Retrying... (${i + 1}/${maxRetries})`)\n              await new Promise(resolve => setTimeout(resolve, delay))\n            }\n\n            if (!completed) {\n              throw new Error('Preview Release workflow did not complete in time.')\n            }\n\n            // Remove the 'rocket' reaction\n            if (reaction) {\n              await github.rest.reactions.deleteForIssueComment({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                comment_id: context.payload.comment.id,\n                reaction_id: reaction,\n              })\n              console.log('Removed \"rocket\" reaction.')\n            }\n\n      - name: Trigger Downstream Workflow\n        uses: actions/github-script@v8\n        id: trigger\n        env:\n          COMMENT: ${{ github.event.comment.body }}\n          PR_DATA: ${{ steps.get-pr-data.outputs.result }}\n        with:\n          github-token: ${{ steps.generate-token.outputs.token }}\n          script: |\n            const comment = process.env.COMMENT.trim()\n            const prData = JSON.parse(process.env.PR_DATA)\n\n            const suite = comment.split('\\n')[0].replace(/^\\/ecosystem-ci run/, '').trim()\n\n            await github.rest.actions.createWorkflowDispatch({\n              owner: context.repo.owner,\n              repo: 'vite-ecosystem-ci',\n              workflow_id: 'ecosystem-ci-from-pr.yml',\n              ref: 'main',\n              inputs: {\n                prNumber: '' + prData.num,\n                branchName: prData.branchName,\n                repo: prData.repo,\n                commit: prData.commit,\n                suite: suite === '' ? '-' : suite\n              }\n            })\n"
  },
  {
    "path": ".github/workflows/issue-close-require.yml",
    "content": "name: Issue Close Require\n\non:\n  schedule:\n    - cron: \"0 0 * * *\"\n\njobs:\n  close-issues:\n    if: github.repository == 'vitejs/vite'\n    runs-on: ubuntu-slim\n    permissions:\n      issues: write # for actions-cool/issues-helper to update issues\n      pull-requests: write # for actions-cool/issues-helper to update PRs\n    steps:\n      - name: needs reproduction\n        uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3\n        with:\n          actions: \"close-issues\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          labels: \"needs reproduction\"\n          inactive-day: 3\n"
  },
  {
    "path": ".github/workflows/issue-labeled.yml",
    "content": "name: Issue Labeled\n\non:\n  issues:\n    types: [labeled]\n\njobs:\n  reply-labeled:\n    if: github.repository == 'vitejs/vite'\n    runs-on: ubuntu-slim\n    permissions:\n      issues: write # for actions-cool/issues-helper to update issues\n      pull-requests: write # for actions-cool/issues-helper to update PRs\n    steps:\n      - name: contribution welcome\n        if: github.event.label.name == 'contribution welcome' || github.event.label.name == 'help wanted'\n        uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3\n        with:\n          actions: \"remove-labels\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          issue-number: ${{ github.event.issue.number }}\n          labels: \"pending triage, needs reproduction\"\n\n      - name: remove pending\n        if: (github.event.label.name == 'enhancement' || contains(github.event.label.description, '(priority)')) && contains(github.event.issue.labels.*.name, 'pending triage')\n        uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3\n        with:\n          actions: \"remove-labels\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          issue-number: ${{ github.event.issue.number }}\n          labels: \"pending triage\"\n\n      - name: needs reproduction\n        if: github.event.label.name == 'needs reproduction'\n        uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3\n        with:\n          actions: \"create-comment, remove-labels\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          issue-number: ${{ github.event.issue.number }}\n          body: |\n            Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository or [StackBlitz](https://vite.new). Issues marked with `needs reproduction` will be closed if they have no activity within 3 days.\n          labels: \"pending triage\"\n"
  },
  {
    "path": ".github/workflows/issue-template-check.yml",
    "content": "name: Issue Template Check\n\non:\n  issues:\n    types: [opened]\n\njobs:\n  evaluate-issue:\n    if: \"!github.event.issue.pull_request\"\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      issues: read\n      pull-requests: read\n    outputs:\n      agent_output: ${{ steps.agent.outputs.agent_output }}\n      template_type: ${{ steps.detect.outputs.template_type }}\n      skip: ${{ steps.detect.outputs.skip }}\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Detect issue type\n        id: detect\n        uses: actions/github-script@v8\n        with:\n          script: |\n            const labels = context.payload.issue.labels.map(l => l.name);\n            const issueType = context.payload.issue.type?.name;\n\n            if (issueType === 'Bug') {\n              core.setOutput('template_type', 'bug_report');\n              core.setOutput('skip', 'false');\n            } else if (issueType === 'Feature') {\n              core.setOutput('template_type', 'feature_request');\n              core.setOutput('skip', 'false');\n            } else if (labels.includes('documentation')) {\n              core.setOutput('template_type', 'docs');\n              core.setOutput('skip', 'false');\n            } else {\n              core.info('Issue was not created from a recognized template. Skipping.');\n              core.setOutput('template_type', 'unknown');\n              core.setOutput('skip', 'true');\n            }\n\n      - uses: warpdotdev/oz-agent-action@827a9ad5438c195eb9d1d9a7acece3a8000be512 # v1\n        if: steps.detect.outputs.skip == 'false'\n        id: agent\n        with:\n          prompt: |\n            You are an issue reviewer for the Vite project.\n\n            The issue template type detected is: ${{ steps.detect.outputs.template_type }}\n\n            Read the matching issue template from the checked-out repository at:\n            .github/ISSUE_TEMPLATE/${{ steps.detect.outputs.template_type }}.yml\n\n            Then evaluate the following issue to determine if it faithfully follows that template.\n\n            Issue title: ${{ github.event.issue.title }}\n            Issue body:\n            ${{ github.event.issue.body }}\n\n            Here is a summary of the required fields per template type:\n\n            **bug_report** required fields:\n            1. Describe the bug (required) - A clear and concise description, not vague or just a generic error message\n            2. Reproduction (required) - A valid link to a reproduction (vite.new or GitHub repo URL), not empty or plain text\n            3. Steps to reproduce - Steps needed to reproduce (optional)\n            4. System Info (required) - Output of the envinfo command, must look like actual system/envinfo output\n            5. Used Package Manager (required) - One of: npm, yarn, pnpm, bun\n            6. Logs - Optional error logs\n            7. Validations (required) - All checkboxes must be checked\n\n            **feature_request** required fields:\n            1. Description (required) - Clear and concise description of the problem and use cases\n            2. Suggested solution (required) - A proposed implementation or approach. If it suggests a new option, check against \"Think Before Adding Yet Another Option\" in the CONTRIBUTING.md\n            3. Alternative - Alternative solutions considered (optional)\n            4. Additional context - Any other context (optional)\n            5. Validations (required) - All checkboxes must be checked\n\n            **docs** required fields:\n            1. Documentation is - Checkboxes indicating the issue type: Missing, Outdated, Confusing, Not sure (optional but at least one should be checked)\n            2. Explain in Detail (required) - A clear description of the documentation issue\n            3. Your Suggestion for Changes (required) - What should be changed\n            4. Reproduction - Optional link via vite.new or GitHub repo\n            5. Steps to reproduce - Optional reproduction steps\n\n            Evaluate the issue against the criteria for its detected template type. Focus on whether the required fields are present and substantive (not empty placeholders or placeholder text).\n\n            Respond with ONLY a JSON object (no markdown fencing) with these fields:\n            - \"template\": the template type that was checked\n            - \"compliant\": true/false\n            - \"missing\": an array of strings describing what is missing or inadequate (empty array if compliant)\n            - \"comment\": a polite, helpful comment to post if non-compliant, formatted in GitHub markdown. Address the user by their username @${{ github.event.issue.user.login }}. Ask them to update the issue with the missing information. Reference the specific template they should follow. Be concise.\n          output_format: json\n          warp_api_key: ${{ secrets.WARP_API_KEY }}\n          profile: ${{ vars.WARP_AGENT_PROFILE || '' }}\n\n  post-results:\n    needs: evaluate-issue\n    if: needs.evaluate-issue.outputs.skip == 'false' && needs.evaluate-issue.outputs.agent_output\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      issues: write\n    steps:\n      - name: Write result to summary\n        uses: actions/github-script@v8\n        env:\n          TEMPLATE_TYPE: ${{ needs.evaluate-issue.outputs.template_type }}\n          AGENT_OUTPUT: ${{ needs.evaluate-issue.outputs.agent_output }}\n        with:\n          script: |\n            const output = process.env.AGENT_OUTPUT;\n            const templateType = process.env.TEMPLATE_TYPE;\n\n            try {\n              // The agent outputs streaming JSON format with multiple lines\n              // We need to extract the last line with type:\"agent\" and parse its text field\n              const lines = output.trim().split('\\n');\n              let agentText = null;\n              for (const line of lines) {\n                try {\n                  const parsed = JSON.parse(line);\n                  if (parsed.type === 'agent' && parsed.text) {\n                    agentText = parsed.text;\n                  }\n                } catch (e) {}\n              }\n\n              if (agentText) {\n                await core.summary\n                  .addHeading(`Issue Template Check (${templateType})`)\n                  .addCodeBlock(agentText, 'json')\n                  .write();\n              }\n            } catch (e) {\n              core.setFailed(`Failed to write summary: ${e.message}`);\n            }\n"
  },
  {
    "path": ".github/workflows/lock-closed-issues.yml",
    "content": "name: Lock Closed Issues\n\non:\n  schedule:\n    - cron: \"0 0 * * *\"\n\npermissions:\n  issues: write\n\njobs:\n  action:\n    if: github.repository == 'vitejs/vite'\n    runs-on: ubuntu-slim\n    steps:\n      - uses: actions-cool/issues-helper@71b62d7da76e59ff7b193904feb6e77d4dbb2777 # v3\n        with:\n          actions: \"lock-issues\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          #body: |\n          #  This issue has been locked since it has been closed for more than 14 days.\n          #\n          #  If you have found a concrete bug or regression related to it, please open a new [bug report](https://github.com/vitejs/vite/issues/new/choose) with a reproduction against the latest Vite version. If you have any other comments you should join the chat at [Vite Land](https://chat.vite.dev) or create a new [discussion](https://github.com/vitejs/vite/discussions).\n          issue-state: closed\n          inactive-day: 14\n"
  },
  {
    "path": ".github/workflows/preview-release.yml",
    "content": "name: Preview release\n\nenv:\n  # install playwright binary manually (because pnpm only runs install script once)\n  PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: \"1\"\n\npermissions:\n  pull-requests: write\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    types: [opened, synchronize, labeled]\n\njobs:\n  preview:\n    if: >\n      github.repository == 'vitejs/vite' &&\n      (github.event_name == 'push' ||\n      (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'trigger: preview')))\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n\n      - name: Set node version to 24\n        uses: actions/setup-node@v6\n        with:\n          node-version: 24\n          registry-url: https://registry.npmjs.org/\n          # disable cache, to avoid cache poisoning (https://docs.zizmor.sh/audits/#cache-poisoning)\n          package-manager-cache: false\n\n      - name: Disallow installation scripts\n        run: yq '.onlyBuiltDependencies = []' -i pnpm-workspace.yaml\n\n      - name: Install deps\n        run: pnpm install\n        env:\n          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: \"1\"\n\n      - name: Build Vite core\n        working-directory: ./packages/vite\n        run: pnpm build\n\n      - name: Build plugin-legacy\n        working-directory: ./packages/plugin-legacy\n        run: pnpm build\n\n      - run: pnpm dlx pkg-pr-new@0.0 publish --pnpm './packages/vite' './packages/plugin-legacy' --packageManager=pnpm,npm,yarn --commentWithDev\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish Package\n\non:\n  push:\n    tags:\n      - \"v*\" # Push events to matching v*, i.e. v1.0, v20.15.10\n      - \"plugin-*\" # Push events to matching plugin-*, i.e. plugin-(vue|vue-jsx|react|legacy)@1.0.0\n      - \"create-vite*\" # # Push events to matching create-vite*, i.e. create-vite@1.0.0\n\njobs:\n  publish:\n    # prevents this action from running on forks\n    if: github.repository == 'vitejs/vite'\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      id-token: write\n    environment: Release\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4.4.0\n\n      - name: Set node version to 24\n        uses: actions/setup-node@v6\n        with:\n          node-version: 24\n          registry-url: https://registry.npmjs.org/\n          # disable cache, to avoid cache poisoning (https://docs.zizmor.sh/audits/#cache-poisoning)\n          package-manager-cache: false\n\n      - name: Disallow installation scripts\n        run: yq '.onlyBuiltDependencies = []' -i pnpm-workspace.yaml\n\n      - name: Install deps\n        run: pnpm install\n        env:\n          PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: \"1\"\n\n      - name: Publish package\n        run: npm i -g npm@^11.5.2 && pnpm run ci-publish \"$REF_NAME\"\n        env:\n          REF_NAME: ${{ github.ref_name }}\n"
  },
  {
    "path": ".github/workflows/release-tag.yml",
    "content": "name: Add GitHub Release Tag\n\non:\n  push:\n    tags:\n      - \"v*\" # Push events to matching v*, i.e. v1.0, v20.15.10\n      - \"plugin-*\" # Push events to matching plugin-*, i.e. plugin-(vue|vue-jsx|react|legacy)@1.0.0\n      - \"create-vite*\" # # Push events to matching create-vite*, i.e. create-vite@1.0.0\n\n# $GITHUB_REF_NAME - https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables\n\njobs:\n  release:\n    if: github.repository == 'vitejs/vite'\n    runs-on: ubuntu-slim\n    permissions:\n      contents: write # for yyx990803/release-tag to create a release tag\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Get pkgName for tag\n        id: tag\n        run: |\n          # skip if alpha\n          if [[ $GITHUB_REF_NAME =~ alpha ]]; then\n            exit 0\n          fi\n\n          # matching v2.0.0 / v2.0.0-beta.8 etc\n          if [[ $GITHUB_REF_NAME =~ ^v.+ ]]; then\n            pkgName=\"vite\"\n          else\n            # `%@*` truncates @ and version number from the right side.\n            # https://stackoverflow.com/questions/9532654/expression-after-last-specific-character\n            pkgName=${GITHUB_REF_NAME%@*}\n          fi\n\n          echo \"pkgName=$pkgName\" >> $GITHUB_OUTPUT\n\n      - name: Create Release for Tag\n        # only run if tag is not alpha\n        if: steps.tag.outputs.pkgName\n        id: release_tag\n        uses: yyx990803/release-tag@8cccf7c5aa332d71d222df46677f70f77a8d2dc0 # v1.0.0\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          tag_name: ${{ github.ref }}\n          body: |\n            Please refer to [CHANGELOG.md](https://github.com/vitejs/vite/blob/${{ github.ref_name }}/packages/${{ steps.tag.outputs.pkgName }}/CHANGELOG.md) for details.\n"
  },
  {
    "path": ".github/workflows/semantic-pull-request.yml",
    "content": "name: Semantic Pull Request\n\non:\n  pull_request_target:\n    types:\n      - opened\n      - edited\n      - synchronize\n\njobs:\n  main:\n    if: github.repository == 'vitejs/vite'\n    runs-on: ubuntu-slim\n    name: Semantic Pull Request\n    permissions:\n      pull-requests: read\n    steps:\n      - name: Validate PR title\n        uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6\n        with:\n          subjectPattern: ^(?![A-Z]).+$\n          subjectPatternError: |\n            The subject \"{subject}\" found in the pull request title \"{title}\"\n            didn't match the configured pattern. Please ensure that the subject\n            doesn't start with an uppercase character.\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "!**/glob-import/dir/node_modules\n.DS_Store\n.idea\n.pnpm-store\n*.cpuprofile\n*.local\n*.log\n/.vscode/\n/docs/.vitepress/cache\n/docs/.vitepress/.temp\n/packages/vite/LICENSE\ndist\ndist-ssr\nexplorations\nnode_modules\nplayground-temp\ntemp\nTODOs.md\n.eslintcache\n"
  },
  {
    "path": ".prettierignore",
    "content": "packages/*/CHANGELOG.md\npackages/vite/src/node/ssr/__tests__/fixtures/errors/syntax-error.*\nplayground-temp/\ndist/\nLICENSE.md\npnpm-lock.yaml\npnpm-workspace.yaml\nplayground/tsconfig-json-load-error/has-error/tsconfig.json\nplayground/html/invalid.html\nplayground/html/invalidClick.html\nplayground/html/invalidEscape.html\nplayground/html/valid.html\nplayground/external/public/slash@3.0.0.js\nplayground/ssr-html/public/slash@3.0.0.js\nplayground/worker/classic-worker.js\nplayground/css/weapp.wxss\n"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"overrides\": [\n    {\n      \"files\": [\"**/*.json5\"],\n      \"options\": {\n        \"singleQuote\": false,\n        \"quoteProps\": \"preserve\"\n      }\n    },\n    {\n      \"files\": [\"**/*.yml\"],\n      \"options\": {\n        \"singleQuote\": false\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code Of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as 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, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, political party, or sexual identity and orientation. Note, however, that religion, political party, or other ideological affiliation provide no exemptions for the behavior we outline as unacceptable in this Code of Conduct.\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 by DM at [Vite Land](https://chat.vite.dev). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and 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 https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Vite Contributing Guide\n\nHi! We're really excited that you're interested in contributing to Vite! Before submitting your contribution, please read through the following guide. We also suggest you read the [Project Philosophy](https://vite.dev/guide/philosophy) in our documentation.\n\n## Repo Setup\n\nTo develop locally, fork the Vite repository and clone it in your local machine. The Vite repo is a monorepo using pnpm workspaces. The package manager used to install and link dependencies must be [pnpm](https://pnpm.io/). You can find the required pnpm version in `package.json` under the `packageManager` key.\n\nTo develop and test the core `vite` package:\n\n1. Run `pnpm i` in Vite's root folder.\n\n2. Run `pnpm run build` in Vite's root folder.\n\n3. If you are developing Vite itself, you can go to `packages/vite` and run `pnpm run dev` to automatically rebuild Vite whenever you change its code.\n\n> If you are working on multiple projects with different versions of pnpm, it's recommended to enable [Corepack](https://github.com/nodejs/corepack) by running `corepack enable`.\n\n### Cloning the repo on Windows\n\nOn Windows, you may want to [activate Developer Mode](https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) to resolve [issues with symlink creation for non-admins](https://github.com/vitejs/vite/issues/7390). Also, you may want to [set git `core.symlinks` to `true` to resolve issues with symlinks in git](https://github.com/vitejs/vite/issues/5242).\n\n### Ignoring commits when running `git blame`\n\nWe have a `.git-blame-ignore-revs` file to ignore formatting changes.\nTo make this file used by `git blame`, you need to run the following command.\n\n```sh\ngit config --local blame.ignoreRevsFile .git-blame-ignore-revs\n```\n\n## Documentation\n\nTo develop the `docs/` site:\n\n1. Run `pnpm run build` in Vite's root folder. This will generate the types for `twoslash` to work in the code examples. If the types are not available, errors will be logged in step 2 but does not prevent the site from working.\n\n2. Run `pnpm run docs` in Vite's root folder.\n\n### Docs Translation Contribution\n\nTo add a new language to the Vite docs, see [`vite-docs-template`](https://github.com/tony19/vite-docs-template/blob/main/.github/CONTRIBUTING.md).\n\n## Notes on Dependencies\n\nVite aims to be lightweight, and this includes being aware of the number of npm dependencies and their size.\n\nWe use Rolldown to pre-bundle most dependencies before publishing! Therefore, most dependencies, even those used in runtime source code, should be added under `devDependencies` by default. This also creates the following constraints that we need to be aware of in the codebase.\n\n### Usage of `require()`\n\nIn some cases, we intentionally lazy-require some dependencies to improve start-up performance. However, note that we cannot use simple `require('somedep')` calls since these are ignored in ESM files, so the dependency won't be included in the bundle, and the actual dependency won't even be there when published since they are in `devDependencies`.\n\nInstead, use `(await import('somedep')).default`.\n\n### Think Before Adding a Dependency\n\nMost deps should be added to `devDependencies` even if they are needed at runtime. Some exceptions are:\n\n- Type packages. Example: `@types/*`.\n- Deps that cannot be properly bundled due to binary files. Example: `esbuild`.\n- Deps that ship their own types that are used in Vite's own public types. Example: `rollup`.\n\nAvoid deps with large transitive dependencies that result in bloated size compared to the functionality it provides. For example, `http-proxy` itself is around 380kB in size, but `http-proxy-middleware` pulls in a ton of dependencies that make it 3MB(!) when a minimal custom middleware on top of `http-proxy` only requires a couple of lines of code.\n\n### Ensure Type Support\n\nVite aims to be fully usable as a dependency in a TypeScript project (e.g. it should provide proper typings for VitePress), and also in `vite.config.ts`. This means technically a dependency whose types are exposed needs to be part of `dependencies` instead of `devDependencies`. However, this also means we won't be able to bundle it.\n\nTo get around this, we inline some of these dependencies' types in `packages/vite/src/types`. This way, we can still expose the typing but bundle the dependency's source code.\n\nUse `pnpm run build-types-check` to check that the bundled types do not rely on types in `devDependencies`.\n\nFor types shared between client and node, they should be added into `packages/vite/types`. These types are not bundled and are published as is (though they are still considered internal).\n\n## Think Before Adding Yet Another Option\n\nWe already have many config options, and we should avoid fixing an issue by adding yet another one. Before adding an option, consider whether the problem:\n\n- is really worth addressing\n- can be fixed with a smarter default\n- has workaround using existing options\n- can be addressed with a plugin instead\n\n## Debugging\n\nTo use breakpoints and explore code execution, you can use the [\"Run and Debug\"](https://code.visualstudio.com/docs/editor/debugging) feature from VS Code.\n\n1. Add a `debugger` statement where you want to stop the code execution.\n\n2. Click the \"Run and Debug\" icon in the activity bar of the editor, which opens the [_Run and Debug view_](https://code.visualstudio.com/docs/editor/debugging#_run-and-debug-view).\n\n3. Click the \"JavaScript Debug Terminal\" button in the _Run and Debug view_, which opens a terminal in VS Code.\n\n4. From that terminal, go to `playground/xxx`, and run `pnpm run dev`.\n\n5. The execution will stop at the `debugger` statement, and you can use the [Debug toolbar](https://code.visualstudio.com/docs/editor/debugging#_debug-actions) to continue, step over, and restart the process...\n\n### Debugging Errors in Vitest Tests Using Playwright (Chromium)\n\nSome errors are masked and hidden away because of the layers of abstraction and sandboxed nature added by Vitest, Playwright, and Chromium. In order to see what's actually going wrong and the contents of the devtools console in those instances, follow this setup:\n\n1. Add a `debugger` statement to the `playground/vitestSetup.ts` -> `afterAll` hook. This will pause execution before the tests quit and the Playwright browser instance exits.\n\n2. Run the tests with the `debug-serve` script command, which will enable remote debugging: `pnpm run debug-serve resolve`.\n\n3. Wait for inspector devtools to open in your browser and the debugger to attach.\n\n4. In the sources panel in the right column, click the play button to resume execution, and allow the tests to run, which will open a Chromium instance.\n\n5. Focusing the Chromium instance, you can open the browser devtools and inspect the console there to find the underlying problems.\n\n6. To close everything, just stop the test process back in your terminal.\n\n### Debug Logging\n\nYou can set the `--debug` option to turn on debugging logs (e.g. `vite --debug resolve`). To see all debug logs, you can set `vite --debug *`, but be warned that it will be quite noisy. You can run `grep -r \"createDebugger('vite:\" packages/vite/src/` to see a list of available debug scopes.\n\n### Disabling Source Maps\n\nSource maps for Vite's source code are enabled by default when Vite is placed outside `node_modules` so that you can easily debug it. When bundling Vite in watch mode, source maps will be generated.\n\nHowever, this behavior may not be desirable when you are developing source map related features. In that case, you can disable source maps by setting the `DEBUG_DISABLE_SOURCE_MAP` environment variable to `1` when running Vite (e.g. `DEBUG_DISABLE_SOURCE_MAP=1 vite`). This environment variable can also be used to disable source map generation.\n\n## Testing Vite against external packages\n\nYou may wish to test your locally modified copy of Vite against another package that is built with Vite. For pnpm, after building Vite, you can use [`pnpm.overrides`](https://pnpm.io/package_json#pnpmoverrides) to do this. Note that `pnpm.overrides` must be specified in the root `package.json`, and you must list the package as a dependency in the root `package.json`:\n\n```json\n{\n  \"dependencies\": {\n    \"vite\": \"^7.0.0\"\n  },\n  \"pnpm\": {\n    \"overrides\": {\n      \"vite\": \"link:../path/to/vite/packages/vite\"\n    }\n  }\n}\n```\n\nAnd re-run `pnpm install` to link the package.\n\n## Running Tests\n\n### Integration Tests\n\nEach package under `playground/` contains a `__tests__` directory. The tests are run using [Vitest](https://vitest.dev/) + [Playwright](https://playwright.dev/) with custom integrations to make writing tests simple. The detailed setup is inside `vitest.config.e2e.ts` and `playground/vitest*.ts` files.\n\nSome playgrounds define variants to run the same app using different config setups. By convention, when running a test spec file in a nested folder in `__tests__`, the setup will try to use a config file named `vite.config-{folderName}.js` at the playground's root. You can see an example of variants in the [assets playground](https://github.com/vitejs/vite/tree/main/playground/assets).\n\nBefore running the tests, make sure that [Vite has been built](#repo-setup).\n\nEach integration test can be run under either dev server mode or build mode.\n\n- `pnpm test` by default runs every integration test in both serve and build mode, and also unit tests.\n\n- `pnpm run test-serve` runs tests only under serve mode.\n\n- `pnpm run test-build` runs tests only under build mode.\n\n`pnpm run test-serve [match]` or `pnpm run test-build [match]` runs tests in specific packages that match the given filter. e.g. `pnpm run test-serve assets` runs tests for both `playground/assets` and `playground/assets-sanitize` under serve mode. Note package matching is not available for the `pnpm test` script, which always runs all tests.\n\n### Unit Tests\n\nOther than tests under `playground/` for integration tests, packages might contain unit tests under their `__tests__` directory. Unit tests are powered by [Vitest](https://vitest.dev/). The detailed config is inside `vitest.config.ts` files.\n\n- `pnpm run test-unit` runs unit tests under each package.\n\n`pnpm run test-unit [match]` runs tests in specific packages that match the given filter.\n\n### Test Env and Helpers\n\nInside playground tests, you can import the `page` object from `~utils`, which is a Playwright [`Page`](https://playwright.dev/docs/api/class-page) instance that has already navigated to the served page of the current playground. So, writing a test is as simple as:\n\n```js\nimport { page } from '~utils'\n\ntest('should work', async () => {\n  expect(await page.textContent('.foo')).toMatch('foo')\n})\n```\n\nSome common test helpers (e.g. `testDir`, `isBuild`, or `editFile`) are also available in the utils. Source code is located at `playground/test-utils.ts`.\n\nNote: The test build environment uses a [different default set of Vite config](https://github.com/vitejs/vite/blob/main/playground/vitestSetup.ts#L207-L227) to skip transpilation during tests to make it faster. This may produce a different result compared to the default production build.\n\n### Extending the Test Suite\n\nTo add new tests, you should find a related playground to the fix or feature (or create a new one). As an example, static assets loading is tested in the [assets playground](https://github.com/vitejs/vite/tree/main/playground/assets). In this Vite app, there is a test for `?raw` imports with [a section defined in the `index.html` for it](https://github.com/vitejs/vite/blob/v6.3.1/playground/assets/index.html#L266-L267):\n\n```html\n<h2>?raw import</h2>\n<code class=\"raw\"></code>\n```\n\nThis will be modified [with the result of a file import](https://github.com/vitejs/vite/blob/v6.3.1/playground/assets/index.html#L543-L544):\n\n```js\nimport rawSvg from './nested/fragment.svg?raw'\ntext('.raw', rawSvg)\n```\n\n...where the `text` util is defined as:\n\n```js\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n```\n\nIn the [spec tests](https://github.com/vitejs/vite/blob/v6.3.1/playground/assets/__tests__/assets.spec.ts#L469-L471), the modifications to the DOM listed above are used to test this feature:\n\n```js\ntest('?raw import', async () => {\n  expect(await page.textContent('.raw')).toMatch('SVG')\n})\n```\n\n### Note on Test Dependencies\n\nIn many test cases, we need to mock dependencies using `link:` and `file:` protocols. `pnpm` treats `link:` as symlinks and `file:` as hardlinks. To test dependencies as if they were copied into `node_modules`, use the `file:` protocol. Otherwise, use the `link:` protocol.\n\nFor a mock dependency, make sure you add a `@vitejs/test-` prefix to the package name. This will avoid possible issues like false-positive alerts.\n\n## Pull Request Guidelines\n\n> [!NOTE]\n> You do not need to ask for permission to work on an open issue. You can start investigating or open a PR directly. If someone else ships a fix first, you can still help by reviewing or validating the solution.\n\n- Checkout a topic branch from a base branch (e.g. `main`), and merge back against that branch.\n\n- If adding a new feature:\n  - Add accompanying test case.\n  - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first, and have it approved before working on it.\n\n- If fixing a bug:\n  - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log (e.g. `fix: update entities encoding/decoding (fix #3899)`).\n  - Provide a detailed description of the bug in the PR. Live demo preferred.\n  - Add appropriate test coverage. If not applicable, explain in the PR description why tests are not included.\n\n- If it's a chore:\n  - For typos and comment changes, try to combine multiple of them into a single PR.\n  - **Note that we discourage contributors from submitting code refactors that are largely stylistic.** Code refactors are only accepted if it improves performance, or objectively improves code quality (e.g. makes a related bug fix or feature implementation easier, and it is as a separate PR to improve git history).\n    - The reason is that code readability is subjective. The maintainers of this project have chosen to write the code in its current style based on our preferences, and we do not want to spend time explaining our stylistic preferences. Contributors should just respect the established conventions when contributing code. Another aspect of it is that large scale stylistic changes result in massive diffs that touch multiple files, adding noise to the git history and makes tracing behavior changes across commits more cumbersome.\n\n- It's OK to have multiple small commits as you work on the PR. GitHub can automatically squash them before merging.\n\n- Make sure tests pass!\n\n- No need to worry about code style as long as you have installed the dev dependencies. Modified files are automatically formatted with Prettier on commit (by invoking [Git Hooks](https://git-scm.com/docs/githooks) via [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks)).\n\n- PR title must follow the [commit message convention](./.github/commit-convention.md) so that changelogs can be automatically generated.\n\n## Maintenance Guidelines\n\n> The following section is mostly for maintainers who have commit access, but it's helpful to go through if you intend to make non-trivial contributions to the codebase.\n\n### Issue Triaging Workflow\n\n```mermaid\nflowchart TD\n    start{Followed issue\n        template?}\n    start --NO--> close1[\"Close and ask to\n        follow template\"]\n    start --YES--> dupe{Is duplicate?}\n    dupe --YES--> close2[Close and point\n        to duplicate]\n    dupe --NO--> repro{Has proper\n      reproduction?}\n    repro --NO--> close3[Label: 'needs reproduction'\n        bot will auto close if no update\n        has been made in 3 days]\n    repro --YES--> real{Is actually a bug?}\n    real --NO--> intended{Is the intended\n        behaviour?}\n    intended --YES--> explain[Explain and close\n        point to docs if needed]\n    intended --NO--> open[Keep open for discussion\n        Remove 'pending triage' label]\n    real --YES--> real2[\"① Remove 'pending triage' label\n        ② Add related feature label if applicable\n        (e.g. 'feat: ssr')\n        ③ Add priority and meta labels (see below)\"]\n    real2 --> unusable{Does the\n        bug make Vite\n        unusable?}\n    unusable --YES--> maj{Does the bug\n        affect the majority\n        of Vite users?}\n    maj --YES--> p5[p5: urgent]\n    maj --NO--> p4[p4: important]\n    unusable --NO--> workarounds{Are there\n        workarounds for\n        the bug?}\n    workarounds --NO--> p3[p3: minor bug]\n    workarounds --YES--> p2[p2: edge case\n        has workaround]\n```\n\n### Pull Request Review Workflow\n\n```mermaid\nflowchart TD\n    start{Bug fix\n        or\n        feature}\n    start --BUG FIX--> strict_bug{\"Is this a 'strict fix'?\n        i.e. fixes an obvious oversight with no side effects\"}\n    start --FEATURE--> feature[• Discuss feature necessity\n        • Is there a better way to address the need?\n        • Review code quality\n        • Add labels\n        • Add to milestone\n        • Add to Team Board]\n    feature -.-> approve_non_strict[• Run vite-ecosystem-ci if needed\n        • Approve if you feel strongly that the PR is needed and add to milestone]\n    strict_bug --YES--> strict[• Verify the fix locally\n        • Review code quality\n        • Require test case if applicable\n        • Request changes if necessary\n        • Add labels]\n    strict_bug --NO--> non_strict[Discuss the potential side effects of the fix, e.g.\n        • Could it introduce implicit behavior changes in other cases?\n        • Does it introduce too much changes?\n        • Add labels\n        • Add to Team Board]\n    non_strict -.-> approve_non_strict\n    strict --> approve_strict[Approve if ready to be merged]\n    approve_strict --> merge_strict[Merge if approved by 2 or more team members]\n    approve_non_strict -.-> merge_non_strict[Merge if approved by 2 or more team members and the PR has been discussed in a team meeting]\n    merge_non_strict -.-> merge_extra\n    merge_strict --> merge_extra[\"• Use 'Squash and Merge'\n        • Edit commit message to follow convention\n        • In commit message body, list relevant issues being fixed e.g. 'fix #1234, fix #1235'\"]\n```\n\n### Release\n\nIf you have publish access, the steps below explain how to cut a release for a package. There are two phases for the release step: \"Release\" and \"Publish\".\n\n\"Release\" is done locally to generate the changelogs and git tags:\n\n1. Make sure the git remote for https://github.com/vitejs/vite is set as `origin`.\n2. In the `vite` project root `main` branch, run `git pull` and `pnpm i` to get it up-to-date. Then run `pnpm build`.\n3. Run `pnpm release` and follow the prompts to cut a release for a package. It will generate the changelog, a git release tag, and push them to `origin`. You can run with the `--dry` flag to test it out.\n4. When the command finishes, it will provide a link to https://github.com/vitejs/vite/actions/workflows/publish.yml.\n5. Click the link to visit the page, and follow the next steps below.\n\n\"Publish\" is done on GitHub Actions to publish the package to npm:\n\n1. Shortly in the workflows page, a new workflow will appear for the released package and is waiting for approval to publish to npm.\n2. Click on the workflow to open its page.\n3. Click on the \"Review deployments\" button in the yellow box, a popup will appear.\n4. Check \"Release\" and click \"Approve and deploy\".\n5. The package will start publishing to npm.\n\nTo learn more about how and when Vite does releases, check out the [Releases](https://vite.dev/releases) documentation.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019-present, VoidZero Inc. and Vite contributors\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": "<p align=\"center\">\n  <br>\n  <br>\n  <a href=\"https://vite.dev\" target=\"_blank\" rel=\"noopener noreferrer\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://vite.dev/vite-light.svg\">\n      <source media=\"(prefers-color-scheme: light)\" srcset=\"https://vite.dev/vite-dark.svg\">\n      <img alt=\"vite logo\" src=\"https://vite.dev/vite-dark.svg\" height=\"60\">\n    </picture>\n  </a>\n  <br>\n  <br>\n</p>\n<br/>\n<p align=\"center\">\n  <a href=\"https://npmjs.com/package/vite\"><img src=\"https://img.shields.io/npm/v/vite.svg\" alt=\"npm package\"></a>\n  <a href=\"https://nodejs.org/en/about/previous-releases\"><img src=\"https://img.shields.io/node/v/vite.svg\" alt=\"node compatibility\"></a>\n  <a href=\"https://github.com/vitejs/vite/actions/workflows/ci.yml\"><img src=\"https://github.com/vitejs/vite/actions/workflows/ci.yml/badge.svg?branch=main\" alt=\"build status\"></a>\n  <a href=\"https://docs.warp.dev/support-and-community/community/open-source-partnership\"><img src=\"https://img.shields.io/badge/Oz%20agents-triaging%20issues-white?logo=warp\" alt=\"issue triage powered by Oz\"></a>\n  <a href=\"https://chat.vite.dev\"><img src=\"https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord\" alt=\"discord chat\"></a>\n</p>\n<br/>\n\n# Vite ⚡\n\n> Next Generation Frontend Tooling\n\n- 💡 Instant Server Start\n- ⚡️ Lightning Fast HMR\n- 🛠️ Rich Features\n- 📦 Optimized Build\n- 🔩 Universal Plugin Interface\n- 🔑 Fully Typed APIs\n\nVite (French word for \"quick\", pronounced [`/viːt/`](https://cdn.jsdelivr.net/gh/vitejs/vite@main/docs/public/vite.mp3), like \"veet\") is a new breed of frontend build tooling that significantly improves the frontend development experience. It consists of two major parts:\n\n- A dev server that serves your source files over [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), with [rich built-in features](https://vite.dev/guide/features.html) and astonishingly fast [Hot Module Replacement (HMR)](https://vite.dev/guide/features.html#hot-module-replacement).\n\n- A [build command](https://vite.dev/guide/build.html) that bundles your code with [Rollup](https://rollupjs.org), pre-configured to output highly optimized static assets for production.\n\nIn addition, Vite is highly extensible via its [Plugin API](https://vite.dev/guide/api-plugin.html) and [JavaScript API](https://vite.dev/guide/api-javascript.html) with full typing support.\n\n[Read the Docs to Learn More](https://vite.dev).\n\n## Packages\n\n| Package                                         | Version (click for changelogs)                                                                                                    |\n| ----------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |\n| [vite](packages/vite)                           | [![vite version](https://img.shields.io/npm/v/vite.svg?label=%20)](packages/vite/CHANGELOG.md)                                    |\n| [@vitejs/plugin-legacy](packages/plugin-legacy) | [![plugin-legacy version](https://img.shields.io/npm/v/@vitejs/plugin-legacy.svg?label=%20)](packages/plugin-legacy/CHANGELOG.md) |\n| [create-vite](packages/create-vite)             | [![create-vite version](https://img.shields.io/npm/v/create-vite.svg?label=%20)](packages/create-vite/CHANGELOG.md)               |\n\n## Contribution\n\nSee [Contributing Guide](CONTRIBUTING.md).\n\n## License\n\n[MIT](LICENSE).\n\n## Sponsors\n\n<p align=\"center\">\n  <a target=\"_blank\" href=\"https://github.com/sponsors/yyx990803\">\n    <img alt=\"sponsors\" src=\"https://sponsors.vuejs.org/vite.svg?v2\">\n  </a>\n</p>\n"
  },
  {
    "path": "docs/.vitepress/buildEnd.config.ts",
    "content": "import path from 'node:path'\nimport { writeFileSync } from 'node:fs'\nimport { Feed } from 'feed'\nimport type { SiteConfig } from 'vitepress'\nimport { createContentLoader } from 'vitepress'\n\nconst siteUrl = 'https://vite.dev'\nconst blogUrl = `${siteUrl}/blog`\n\nexport const buildEnd = async (config: SiteConfig): Promise<void> => {\n  const feed = new Feed({\n    title: 'Vite',\n    description: 'Next Generation Frontend Tooling',\n    id: blogUrl,\n    link: blogUrl,\n    language: 'en',\n    image: 'https://vite.dev/og-image.jpg',\n    favicon: 'https://vite.dev/logo.svg',\n    copyright: 'Copyright © 2019-present VoidZero Inc. & Vite Contributors',\n  })\n\n  const posts = await createContentLoader('blog/*.md', {\n    excerpt: true,\n    render: true,\n  }).load()\n\n  posts.sort(\n    (a, b) =>\n      +new Date(b.frontmatter.date as string) -\n      +new Date(a.frontmatter.date as string),\n  )\n\n  for (const { url, excerpt, frontmatter, html } of posts) {\n    feed.addItem({\n      title: frontmatter.title,\n      id: `${siteUrl}${url}`,\n      link: `${siteUrl}${url}`,\n      description: excerpt,\n      content: html,\n      author: [\n        {\n          name: frontmatter.author.name,\n        },\n      ],\n      date: frontmatter.date,\n    })\n  }\n\n  writeFileSync(path.join(config.outDir, 'blog.rss'), feed.rss2())\n}\n"
  },
  {
    "path": "docs/.vitepress/config.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport type { HeadConfig } from 'vitepress'\nimport { defineConfig } from 'vitepress'\nimport { transformerTwoslash } from '@shikijs/vitepress-twoslash'\nimport {\n  groupIconMdPlugin,\n  groupIconVitePlugin,\n} from 'vitepress-plugin-group-icons'\nimport { graphvizMarkdownPlugin } from 'vitepress-plugin-graphviz'\nimport llmstxt from 'vitepress-plugin-llms'\nimport { markdownItImageSize } from 'markdown-it-image-size'\nimport { extendConfig } from '@voidzero-dev/vitepress-theme/config'\nimport type { FooterLink } from '@voidzero-dev/vitepress-theme'\nimport packageJson from '../../packages/vite/package.json' with { type: 'json' }\nimport { buildEnd } from './buildEnd.config'\n\nconst viteVersion = packageJson.version\nconst viteMajorVersion = +viteVersion.split('.')[0]\n\nconst ogDescription = 'Next Generation Frontend Tooling'\nconst ogImage = 'https://vite.dev/og-image.jpg'\nconst ogTitle = 'Vite'\nconst ogUrl = 'https://vite.dev'\n\n// netlify envs\nconst deployURL = process.env.DEPLOY_PRIME_URL || ''\nconst commitRef = process.env.COMMIT_REF?.slice(0, 8) || 'dev'\n\nconst deployType = (() => {\n  switch (deployURL) {\n    case 'https://main--vite-docs-main.netlify.app':\n      return 'main'\n    case '':\n      return 'local'\n    default:\n      return 'release'\n  }\n})()\nconst additionalTitle = ((): string => {\n  switch (deployType) {\n    case 'main':\n      return ' (main branch)'\n    case 'local':\n      return ' (local)'\n    case 'release':\n      return ''\n  }\n})()\nconst versionLinks = (() => {\n  const links: FooterLink[] = []\n\n  if (deployType !== 'main') {\n    links.push({\n      text: 'Unreleased Docs',\n      link: 'https://main.vite.dev',\n    })\n  }\n\n  if (deployType === 'main' || deployType === 'local') {\n    links.push({\n      text: `Vite ${viteMajorVersion} Docs (release)`,\n      link: 'https://vite.dev',\n    })\n  }\n\n  // Create version links from v2 onwards\n  for (let i = viteMajorVersion - 1; i >= 2; i--) {\n    links.push({\n      text: `Vite ${i} Docs`,\n      link: `https://v${i}.vite.dev`,\n    })\n  }\n\n  return links\n})()\n\nfunction inlineScript(file: string): HeadConfig {\n  return [\n    'script',\n    {},\n    fs.readFileSync(\n      path.resolve(import.meta.dirname, `./inlined-scripts/${file}`),\n      'utf-8',\n    ),\n  ]\n}\n\nconst config = defineConfig({\n  title: `Vite${additionalTitle}`,\n  description: 'Next Generation Frontend Tooling',\n  cleanUrls: true,\n  sitemap: {\n    hostname: 'https://vite.dev',\n  },\n  head: [\n    [\n      'link',\n      { rel: 'icon', type: 'image/svg+xml', href: '/logo-without-border.svg' },\n    ],\n    [\n      'link',\n      { rel: 'alternate', type: 'application/rss+xml', href: '/blog.rss' },\n    ],\n    ['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }],\n    inlineScript('banner.js'),\n    ['link', { rel: 'me', href: 'https://m.webtoo.ls/@vite' }],\n    ['meta', { property: 'og:type', content: 'website' }],\n    ['meta', { property: 'og:title', content: ogTitle }],\n    ['meta', { property: 'og:image', content: ogImage }],\n    ['meta', { property: 'og:url', content: ogUrl }],\n    ['meta', { property: 'og:description', content: ogDescription }],\n    ['meta', { property: 'og:site_name', content: 'vitejs' }],\n    ['meta', { name: 'twitter:card', content: 'summary_large_image' }],\n    ['meta', { name: 'twitter:site', content: '@vite_js' }],\n    ['meta', { name: 'theme-color', content: '#646cff' }],\n    [\n      'script',\n      {\n        src: 'https://cdn.usefathom.com/script.js',\n        'data-site': 'CBDFBSLI',\n        'data-spa': 'auto',\n        defer: '',\n      },\n    ],\n  ],\n\n  locales: {\n    root: { label: 'English' },\n    zh: { label: '简体中文', link: 'https://cn.vite.dev' },\n    ja: { label: '日本語', link: 'https://ja.vite.dev' },\n    es: { label: 'Español', link: 'https://es.vite.dev' },\n    pt: { label: 'Português', link: 'https://pt.vite.dev' },\n    ko: { label: '한국어', link: 'https://ko.vite.dev' },\n    de: { label: 'Deutsch', link: 'https://de.vite.dev' },\n    fa: { label: 'فارسی', link: 'https://fa.vite.dev' },\n  },\n\n  themeConfig: {\n    variant: 'vite',\n    logo: '/logo.svg',\n\n    banner: {\n      id: 'viteplus-alpha',\n      text: 'Announcing Vite+ Alpha: Open source. Unified. Next-gen.',\n      url: 'https://voidzero.dev/posts/announcing-vite-plus-alpha?utm_source=vite&utm_content=top_banner',\n    },\n\n    editLink: {\n      pattern: 'https://github.com/vitejs/vite/edit/main/docs/:path',\n      text: 'Suggest changes to this page',\n    },\n\n    socialLinks: [\n      { icon: 'bluesky', link: 'https://bsky.app/profile/vite.dev' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@vite' },\n      { icon: 'x', link: 'https://x.com/vite_js' },\n      { icon: 'discord', link: 'https://chat.vite.dev' },\n      { icon: 'github', link: 'https://github.com/vitejs/vite' },\n    ],\n\n    search: {\n      provider: 'algolia',\n      options: {\n        appId: '7H67QR5P0A',\n        apiKey: '208bb9c14574939326032b937431014b',\n        indexName: 'vitejs',\n        searchParameters: {\n          facetFilters: ['tags:en'],\n        },\n        insights: true,\n      },\n    },\n\n    carbonAds: {\n      code: 'CEBIEK3N',\n      placement: 'vitejsdev',\n    },\n\n    footer: {\n      copyright: `© 2019-present VoidZero Inc. and Vite contributors. (${commitRef})`,\n      nav: [\n        {\n          title: 'Vite',\n          items: [\n            { text: 'Guide', link: '/guide/' },\n            { text: 'Config', link: '/config/' },\n            { text: 'Plugins', link: '/plugins/' },\n          ],\n        },\n        {\n          title: 'Resources',\n          items: [\n            { text: 'Team', link: '/team' },\n            { text: 'Blog', link: '/blog' },\n            {\n              text: 'Releases',\n              link: 'https://github.com/vitejs/vite/releases',\n            },\n          ],\n        },\n        {\n          title: 'Versions',\n          items: versionLinks,\n        },\n      ],\n      social: [\n        { icon: 'github', link: 'https://github.com/vitejs/vite' },\n        { icon: 'discord', link: 'https://chat.vite.dev' },\n        { icon: 'bluesky', link: 'https://bsky.app/profile/vite.dev' },\n        { icon: 'x', link: 'https://x.com/vite_js' },\n      ],\n    },\n\n    nav: [\n      { text: 'Guide', link: '/guide/', activeMatch: '/guide/' },\n      { text: 'Config', link: '/config/', activeMatch: '/config/' },\n      { text: 'Plugins', link: '/plugins/', activeMatch: '/plugins/' },\n      {\n        text: 'Resources',\n        items: [\n          { text: 'Team', link: '/team' },\n          { text: 'Blog', link: '/blog' },\n          { text: 'Releases', link: '/releases' },\n          { text: 'Acknowledgements', link: '/acknowledgements' },\n          {\n            text: 'Plugin Registry',\n            link: 'https://registry.vite.dev/plugins',\n          },\n          {\n            text: 'The Documentary',\n            link: 'https://www.youtube.com/watch?v=bmWQqAKLgT4',\n          },\n          {\n            items: [\n              {\n                text: 'Bluesky',\n                link: 'https://bsky.app/profile/vite.dev',\n              },\n              {\n                text: 'Mastodon',\n                link: 'https://elk.zone/m.webtoo.ls/@vite',\n              },\n              {\n                text: 'X',\n                link: 'https://x.com/vite_js',\n              },\n              {\n                text: 'Discord Chat',\n                link: 'https://chat.vite.dev',\n              },\n              {\n                text: 'Awesome Vite',\n                link: 'https://github.com/vitejs/awesome-vite',\n              },\n              {\n                text: 'ViteConf',\n                link: 'https://viteconf.org',\n              },\n              {\n                text: 'DEV Community',\n                link: 'https://dev.to/t/vite',\n              },\n            ],\n          },\n        ],\n      },\n      {\n        text: `v${viteVersion}`,\n        items: [\n          {\n            text: 'Changelog',\n            link: 'https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md',\n          },\n          {\n            text: 'Contributing',\n            link: 'https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md',\n          },\n          {\n            items: versionLinks,\n          },\n        ],\n      },\n    ],\n\n    sidebar: {\n      '/guide/': [\n        {\n          text: 'Introduction',\n          items: [\n            {\n              text: 'Getting Started',\n              link: '/guide/',\n            },\n            {\n              text: 'Philosophy',\n              link: '/guide/philosophy',\n            },\n            {\n              text: 'Why Vite',\n              link: '/guide/why',\n            },\n          ],\n        },\n        {\n          text: 'Guide',\n          items: [\n            {\n              text: 'Features',\n              link: '/guide/features',\n            },\n            {\n              text: 'CLI',\n              link: '/guide/cli',\n            },\n            {\n              text: 'Using Plugins',\n              link: '/guide/using-plugins',\n            },\n            {\n              text: 'Dependency Pre-Bundling',\n              link: '/guide/dep-pre-bundling',\n            },\n            {\n              text: 'Static Asset Handling',\n              link: '/guide/assets',\n            },\n            {\n              text: 'Building for Production',\n              link: '/guide/build',\n            },\n            {\n              text: 'Deploying a Static Site',\n              link: '/guide/static-deploy',\n            },\n            {\n              text: 'Env Variables and Modes',\n              link: '/guide/env-and-mode',\n            },\n            {\n              text: 'Server-Side Rendering (SSR)',\n              link: '/guide/ssr',\n            },\n            {\n              text: 'Backend Integration',\n              link: '/guide/backend-integration',\n            },\n            {\n              text: 'Troubleshooting',\n              link: '/guide/troubleshooting',\n            },\n            {\n              text: 'Performance',\n              link: '/guide/performance',\n            },\n            {\n              text: `Migration from v${viteMajorVersion - 1}`,\n              link: '/guide/migration',\n            },\n            {\n              text: 'Breaking Changes',\n              link: '/changes/',\n            },\n          ],\n        },\n        {\n          text: 'APIs',\n          items: [\n            {\n              text: 'Plugin API',\n              link: '/guide/api-plugin',\n            },\n            {\n              text: 'HMR API',\n              link: '/guide/api-hmr',\n            },\n            {\n              text: 'JavaScript API',\n              link: '/guide/api-javascript',\n            },\n            {\n              text: 'Config Reference',\n              link: '/config/',\n            },\n          ],\n        },\n        {\n          text: 'Environment API',\n          items: [\n            {\n              text: 'Introduction',\n              link: '/guide/api-environment',\n            },\n            {\n              text: 'Environment Instances',\n              link: '/guide/api-environment-instances',\n            },\n            {\n              text: 'Plugins',\n              link: '/guide/api-environment-plugins',\n            },\n            {\n              text: 'Frameworks',\n              link: '/guide/api-environment-frameworks',\n            },\n            {\n              text: 'Runtimes',\n              link: '/guide/api-environment-runtimes',\n            },\n          ],\n        },\n      ],\n      '/config/': [\n        {\n          text: 'Config',\n          items: [\n            {\n              text: 'Configuring Vite',\n              link: '/config/',\n            },\n            {\n              text: 'Shared Options',\n              link: '/config/shared-options',\n            },\n            {\n              text: 'Server Options',\n              link: '/config/server-options',\n            },\n            {\n              text: 'Build Options',\n              link: '/config/build-options',\n            },\n            {\n              text: 'Preview Options',\n              link: '/config/preview-options',\n            },\n            {\n              text: 'Dep Optimization Options',\n              link: '/config/dep-optimization-options',\n            },\n            {\n              text: 'SSR Options',\n              link: '/config/ssr-options',\n            },\n            {\n              text: 'Worker Options',\n              link: '/config/worker-options',\n            },\n          ],\n        },\n      ],\n      '/changes/': [\n        {\n          text: 'Breaking Changes',\n          link: '/changes/',\n        },\n        {\n          text: 'Current',\n          items: [],\n        },\n        {\n          text: 'Future',\n          items: [\n            {\n              text: 'this.environment in Hooks',\n              link: '/changes/this-environment-in-hooks',\n            },\n            {\n              text: 'HMR hotUpdate Plugin Hook',\n              link: '/changes/hotupdate-hook',\n            },\n            {\n              text: 'Move to Per-environment APIs',\n              link: '/changes/per-environment-apis',\n            },\n            {\n              text: 'SSR Using ModuleRunner API',\n              link: '/changes/ssr-using-modulerunner',\n            },\n            {\n              text: 'Shared Plugins During Build',\n              link: '/changes/shared-plugins-during-build',\n            },\n          ],\n        },\n        {\n          text: 'Past',\n          items: [],\n        },\n      ],\n    },\n\n    outline: {\n      level: [2, 3],\n    },\n  },\n  transformHead(ctx) {\n    const path = ctx.page.replace(/(^|\\/)index\\.md$/, '$1').replace(/\\.md$/, '')\n\n    if (path !== '404') {\n      const canonicalUrl = path ? `${ogUrl}/${path}` : ogUrl\n      ctx.head.push(\n        ['link', { rel: 'canonical', href: canonicalUrl }],\n        ['meta', { property: 'og:title', content: ctx.pageData.title }],\n      )\n    }\n\n    // For the landing page, move the google font links to the top for better performance\n    if (path === '') {\n      const googleFontLinks: HeadConfig[] = []\n      for (let i = 0; i < ctx.head.length; i++) {\n        const tag = ctx.head[i]\n        if (\n          tag[0] === 'link' &&\n          (tag[1]?.href?.includes('fonts.googleapis.com') ||\n            tag[1]?.href?.includes('fonts.gstatic.com'))\n        ) {\n          ctx.head.splice(i, 1)\n          googleFontLinks.push(tag)\n          i--\n        }\n      }\n      ctx.head.unshift(...googleFontLinks)\n    }\n  },\n  markdown: {\n    // languages used for twoslash and jsdocs in twoslash\n    languages: ['ts', 'js', 'json'],\n    codeTransformers: [\n      transformerTwoslash(),\n      // add `style:*` support\n      {\n        root(hast) {\n          const meta = this.options.meta?.__raw\n            ?.split(' ')\n            .find((m) => m.startsWith('style:'))\n          if (meta) {\n            const style = meta.slice('style:'.length)\n            const rootPre = hast.children.find(\n              (n): n is typeof n & { type: 'element'; tagName: 'pre' } =>\n                n.type === 'element' && n.tagName === 'pre',\n            )\n            if (rootPre) {\n              rootPre.properties.style += '; ' + style\n            }\n          }\n        },\n      },\n    ],\n    async config(md) {\n      md.use(groupIconMdPlugin, {\n        titleBar: {\n          includeSnippet: true,\n        },\n      })\n      md.use(markdownItImageSize, {\n        publicDir: path.resolve(import.meta.dirname, '../public'),\n      })\n      await graphvizMarkdownPlugin(md)\n    },\n  },\n  vite: {\n    plugins: [\n      groupIconVitePlugin({\n        customIcon: {\n          firebase: 'vscode-icons:file-type-firebase',\n          '.gitlab-ci.yml': 'vscode-icons:file-type-gitlab',\n        },\n      }),\n      llmstxt({\n        ignoreFiles: ['blog/*', 'blog.md', 'index.md', 'team.md'],\n        description: 'The Build Tool for the Web',\n        details: `\\\n- 💡 Instant Server Start\n- ⚡️ Lightning Fast HMR\n- 🛠️ Rich Features\n- 📦 Optimized Build\n- 🔩 Universal Plugin Interface\n- 🔑 Fully Typed APIs\n\nVite is a new breed of frontend build tooling that significantly improves the frontend development experience. It consists of two major parts:\n\n- A dev server that serves your source files over [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), with [rich built-in features](https://vite.dev/guide/features.md) and astonishingly fast [Hot Module Replacement (HMR)](https://vite.dev/guide/features.md#hot-module-replacement).\n\n- A [build command](https://vite.dev/guide/build.md) that bundles your code with [Rollup](https://rollupjs.org), pre-configured to output highly optimized static assets for production.\n\nIn addition, Vite is highly extensible via its [Plugin API](https://vite.dev/guide/api-plugin.md) and [JavaScript API](https://vite.dev/guide/api-javascript.md) with full typing support.`,\n      }),\n    ],\n    optimizeDeps: {\n      include: ['@shikijs/vitepress-twoslash/client'],\n    },\n    define: {\n      __VITE_VERSION__: JSON.stringify(viteVersion),\n    },\n  },\n  buildEnd,\n})\n\nexport default extendConfig(config)\n"
  },
  {
    "path": "docs/.vitepress/inlined-scripts/banner.d.ts",
    "content": "interface Window {\n  __VITE_BANNER_ID__: string\n}\n"
  },
  {
    "path": "docs/.vitepress/inlined-scripts/banner.js",
    "content": ";(() => {\n  const restore = (key, cls, def = false) => {\n    const saved = localStorage.getItem(key)\n    if (saved ? saved !== 'false' : def) {\n      document.documentElement.classList.add(cls)\n    }\n  }\n\n  window.__VITE_BANNER_ID__ = 'viteplusannouncement'\n  restore(`vite-docs-banner-${__VITE_BANNER_ID__}`, 'banner-dismissed')\n})()\n"
  },
  {
    "path": "docs/.vitepress/theme/components/AsideSponsors.vue",
    "content": "<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { VPDocAsideSponsors } from '@voidzero-dev/vitepress-theme'\nimport { useSponsor, voidZero } from '../composables/sponsor'\n\nconst { data } = useSponsor()\n\nconst sponsors = computed(() => {\n  return [\n    { size: 'small' as const, items: [voidZero] },\n    ...(data.value?.map((sponsor) => {\n      return {\n        size: (sponsor.size === 'big' ? 'mini' : 'xmini') as 'mini' | 'xmini',\n        items: sponsor.items,\n      }\n    }) ?? []),\n  ]\n})\n</script>\n\n<template>\n  <a\n    class=\"viteconf\"\n    href=\"https://www.youtube.com/playlist?list=PLqGQbXn_GDmkJaoykvHCUmXUPjhgH2bVr\"\n    target=\"_blank\"\n  >\n    <img\n      width=\"22\"\n      height=\"22\"\n      src=\"../../../images/viteconf.svg\"\n      alt=\"ViteConf Logo\"\n    />\n    <span>\n      <p class=\"extra-info\">Building Together</p>\n      <p class=\"heading\">ViteConf 2025</p>\n      <p class=\"extra-info\">View the replays</p>\n    </span>\n  </a>\n  <VPDocAsideSponsors v-if=\"data\" :data=\"sponsors\" />\n</template>\n\n<style scoped>\n.viteconf {\n  margin-top: 1rem;\n  margin-bottom: 1rem;\n  border-radius: 14px;\n  padding-top: 0.4rem;\n  padding-bottom: 0.4rem;\n  position: relative;\n  font-size: 0.9rem;\n  font-weight: 700;\n  line-height: 1.1rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 100%;\n  gap: 1rem;\n  background-color: var(--vp-c-bg-alt);\n  border: 2px solid var(--vp-c-bg-alt);\n  transition: border-color 0.5s;\n}\n.viteconf:hover {\n  border: 2px solid var(--vp-c-brand-light);\n}\n.viteconf img {\n  transition: transform 0.5s;\n  transform: scale(1.25);\n}\n.viteconf:hover img {\n  transform: scale(1.75);\n}\n.viteconf span {\n  display: block;\n}\n.viteconf p {\n  margin: 0;\n  padding: 0;\n  line-height: 1.1rem;\n  color: var(--vp-c-text-1);\n}\n.viteconf .heading {\n  color: var(--vp-c-brand-lighter);\n}\n.viteconf .extra-info {\n  color: var(--vp-c-text-1);\n  opacity: 1;\n  font-size: 0.7rem;\n  padding-left: 0.1rem;\n  transition: opacity 0.5s;\n}\n.viteconf:hover .extra-info {\n  opacity: 0.9;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/BlogIndex.vue",
    "content": "<script setup lang=\"ts\">\nimport { data as posts } from '../../../_data/blog.data'\n\nfunction getDateTime(time: number) {\n  return new Date(time).toISOString()\n}\n</script>\n\n<template>\n  <ul class=\"blog-list\">\n    <li class=\"blog-entry\" v-for=\"post of posts\">\n      <article>\n        <time :datetime=\"getDateTime(post.date.time)\">{{\n          post.date.string\n        }}</time>\n        <h2 class=\"title\">\n          <a :href=\"post.url\">{{ post.title }}</a>\n        </h2>\n      </article>\n    </li>\n  </ul>\n</template>\n\n<style scoped>\n.blog-list {\n  list-style-type: none;\n  padding: 0;\n}\n.blog-entry {\n  margin-top: 3em;\n  border-bottom: 1px solid var(--vp-c-divider);\n}\n.blog-entry time {\n  font-size: 14px;\n}\n.title {\n  border: none;\n  margin-top: 0;\n  padding-top: 0;\n  font-size: 22px;\n}\n.title a {\n  font-weight: 600;\n  text-decoration: none;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/NonInheritBadge.vue",
    "content": "<template>\n  <a\n    href=\"/guide/api-environment#environments-configuration\"\n    class=\"ignore-header\"\n  >\n    <Badge type=\"info\" text=\"non-inherit\" />\n  </a>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/ScrimbaLink.vue",
    "content": "<script setup lang=\"ts\">\ndefineProps<{\n  href: string\n  title: string\n}>()\n</script>\n\n<template>\n  <div class=\"scrimba\">\n    <span class=\"play-button\">\n      <span class=\"play-icon\"></span>\n    </span>\n    <a :href=\"href\" target=\"_blank\" rel=\"sponsored noopener\" :title=\"title\">\n      <slot>Watch an interactive lesson on Scrimba</slot>\n    </a>\n  </div>\n</template>\n\n<style scoped>\n.scrimba {\n  margin: 16px 0;\n  color: var(--vp-custom-block-info-text);\n  background-color: var(--vp-custom-block-info-bg);\n  border: 1px solid var(--vp-custom-block-info-border);\n  padding: 16px 20px;\n  border-radius: 8px;\n  display: flex;\n  align-items: center;\n  gap: 12px;\n}\n.play-button {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 26px;\n  height: 26px;\n  min-width: 26px;\n  border-radius: 50%;\n  background-color: var(--vp-c-brand-1);\n}\n.play-icon {\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  border-style: solid;\n  border-width: 5px 0 5px 8px;\n  border-color: transparent transparent transparent #fff;\n}\n.scrimba a {\n  color: var(--vp-c-brand-1);\n  text-decoration: underline;\n}\n.scrimba a:hover {\n  color: var(--vp-c-brand-2);\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/SponsorBanner.vue",
    "content": "<script setup lang=\"ts\">\n/**\n * Adding a new banner:\n * 1. uncomment the banner slot in ../index.ts\n * 2. uncomment and update BANNER_ID in ../../inlined-scripts/restorePreferences.ts\n * 3. update --vp-layout-top-height if necessary\n */\nimport { ref } from 'vue'\n\nconst open = ref(true)\n\n/**\n * Call this if the banner is dismissible\n */\nfunction dismiss() {\n  open.value = false\n  document.documentElement.classList.add('banner-dismissed')\n  localStorage.setItem(`vite-docs-banner-${window.__VITE_BANNER_ID__}`, 'true')\n}\n</script>\n\n<template>\n  <div class=\"banner\" v-if=\"open\">\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      height=\"12\"\n      fill=\"none\"\n      viewBox=\"0 0 103 15\"\n    >\n      <path\n        d=\"M9.137 10.691 12.907.249h5.16l-5.72 14.503h-6.63L0 .249h5.304zm15.622 4.06h-4.973V.25h4.973zM42.817 3.813h-5.573v10.94h-4.971V3.812h-5.574V.25h16.118zm16.257-.04h-9.343v1.946h9.199v3.418h-9.2v2.093h9.614v3.523H44.759V.249h14.315zm10.934 1.946h5.573v3.418h-5.573v5.616h-3.564V9.136h-5.573V5.718h5.573V.248h3.564z\"\n        fill=\"#ffffff\"\n      />\n      <path\n        d=\"M91.184 14.654a.363.363 0 0 1-.648-.224v-3.303c0-.4-.324-.725-.725-.725h-3.647c-.295 0-.467-.334-.295-.573l2.398-3.357a.725.725 0 0 0-.59-1.147h-4.414c-.295 0-.467-.334-.295-.574L86.076.4a.36.36 0 0 1 .295-.152h9.263c.295 0 .467.334.295.573l-2.398 3.358a.725.725 0 0 0 .59 1.147h3.648c.302 0 .472.348.285.587z\"\n        fill=\"#6254fe\"\n      />\n      <mask\n        id=\"a\"\n        width=\"17\"\n        height=\"15\"\n        x=\"82\"\n        y=\"0\"\n        maskUnits=\"userSpaceOnUse\"\n        style=\"mask-type: alpha\"\n      >\n        <path\n          fill=\"#833bff\"\n          d=\"M91.184 14.654a.363.363 0 0 1-.648-.224v-3.303c0-.4-.324-.725-.725-.725h-3.647c-.295 0-.467-.334-.295-.573l2.398-3.357a.725.725 0 0 0-.59-1.147h-4.414c-.295 0-.467-.334-.295-.574L86.076.4a.36.36 0 0 1 .295-.152h9.263c.295 0 .467.334.295.573l-2.398 3.358a.725.725 0 0 0 .59 1.147h3.648c.302 0 .472.348.285.587z\"\n        />\n      </mask>\n      <g mask=\"url(#a)\">\n        <g filter=\"url(#b)\">\n          <ellipse\n            cx=\"1.766\"\n            cy=\"4.714\"\n            fill=\"#ede6ff\"\n            rx=\"1.766\"\n            ry=\"4.714\"\n            transform=\"rotate(89.814 35.524 46.024)scale(1 -1)\"\n          />\n        </g>\n        <g filter=\"url(#c)\">\n          <ellipse\n            cx=\"3.334\"\n            cy=\"9.57\"\n            fill=\"#ede6ff\"\n            rx=\"3.334\"\n            ry=\"9.57\"\n            transform=\"rotate(89.814 33.737 36.63)scale(1 -1)\"\n          />\n        </g>\n        <g filter=\"url(#d)\">\n          <ellipse\n            cx=\"1.766\"\n            cy=\"9.774\"\n            fill=\"#4e14ff\"\n            rx=\"1.766\"\n            ry=\"9.774\"\n            transform=\"rotate(89.814 33.002 36.998)scale(1 -1)\"\n          />\n        </g>\n        <g filter=\"url(#e)\">\n          <ellipse\n            cx=\"1.766\"\n            cy=\"9.81\"\n            fill=\"#4e14ff\"\n            rx=\"1.766\"\n            ry=\"9.81\"\n            transform=\"rotate(89.814 30.844 40.622)scale(1 -1)\"\n          />\n        </g>\n        <g filter=\"url(#f)\">\n          <ellipse\n            cx=\"1.766\"\n            cy=\"9.81\"\n            fill=\"#4e14ff\"\n            rx=\"1.766\"\n            ry=\"9.81\"\n            transform=\"rotate(89.814 30.904 41.053)scale(1 -1)\"\n          />\n        </g>\n        <g filter=\"url(#g)\">\n          <ellipse\n            cx=\"4.511\"\n            cy=\"7.078\"\n            fill=\"#ede6ff\"\n            rx=\"4.511\"\n            ry=\"7.078\"\n            transform=\"rotate(93.35 49.173 54.748)scale(-1 1)\"\n          />\n        </g>\n        <g filter=\"url(#h)\">\n          <ellipse\n            cx=\"1.113\"\n            cy=\"6.893\"\n            fill=\"#4e14ff\"\n            rx=\"1.113\"\n            ry=\"6.893\"\n            transform=\"rotate(89.009 50.51 57.537)scale(-1 1)\"\n          />\n        </g>\n        <g filter=\"url(#i)\">\n          <ellipse\n            cx=\"1.113\"\n            cy=\"6.893\"\n            fill=\"#4e14ff\"\n            rx=\"1.113\"\n            ry=\"6.893\"\n            transform=\"rotate(89.009 50.51 57.537)scale(-1 1)\"\n          />\n        </g>\n        <g filter=\"url(#j)\">\n          <ellipse\n            cx=\"82.99\"\n            cy=\"3.123\"\n            fill=\"#4e14ff\"\n            rx=\"1.413\"\n            ry=\"9.332\"\n            transform=\"rotate(39.51 82.99 3.123)\"\n          />\n        </g>\n        <g filter=\"url(#k)\">\n          <ellipse\n            cx=\"98.102\"\n            cy=\"-1.706\"\n            fill=\"#4e14ff\"\n            rx=\"1.413\"\n            ry=\"9.332\"\n            transform=\"rotate(37.892 98.102 -1.706)\"\n          />\n        </g>\n        <g filter=\"url(#l)\">\n          <ellipse\n            cx=\"95.97\"\n            cy=\"3.395\"\n            fill=\"#2bfdd2\"\n            rx=\"2.655\"\n            ry=\"4.005\"\n            transform=\"rotate(37.892 95.97 3.395)\"\n          />\n        </g>\n        <g filter=\"url(#m)\">\n          <ellipse\n            cx=\"82.264\"\n            cy=\"12.536\"\n            fill=\"#4e14ff\"\n            rx=\"1.413\"\n            ry=\"9.332\"\n            transform=\"rotate(37.892 82.264 12.536)\"\n          />\n        </g>\n        <g filter=\"url(#n)\">\n          <ellipse\n            cx=\"82.264\"\n            cy=\"12.536\"\n            fill=\"#4e14ff\"\n            rx=\"1.413\"\n            ry=\"9.332\"\n            transform=\"rotate(37.892 82.264 12.536)\"\n          />\n        </g>\n        <g filter=\"url(#o)\">\n          <ellipse\n            cx=\"94.226\"\n            cy=\"9.781\"\n            fill=\"#4e14ff\"\n            rx=\"1.501\"\n            ry=\"9.332\"\n            transform=\"rotate(37.892 94.226 9.78)\"\n          />\n        </g>\n        <g filter=\"url(#p)\">\n          <ellipse\n            cx=\"95.66\"\n            cy=\"10.827\"\n            fill=\"#2bfdd2\"\n            rx=\"2.578\"\n            ry=\"6.754\"\n            transform=\"rotate(37.892 95.66 10.827)\"\n          />\n        </g>\n      </g>\n      <path\n        d=\"M80.53 0c-2.949 4.221-2.966 10.764 0 15h1.993c-2.966-4.236-2.949-10.779 0-15zM100.543 0H98.55c2.949 4.221 2.966 10.764 0 15h1.993c2.965-4.236 2.948-10.779 0-15\"\n        fill=\"#ffffff\"\n      />\n      <defs>\n        <filter\n          id=\"b\"\n          width=\"19.25\"\n          height=\"13.354\"\n          x=\"76.528\"\n          y=\"5.425\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"2.455\"\n          />\n        </filter>\n        <filter\n          id=\"c\"\n          width=\"28.962\"\n          height=\"16.49\"\n          x=\"65.358\"\n          y=\"-2.168\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"2.455\"\n          />\n        </filter>\n        <filter\n          id=\"d\"\n          width=\"25.441\"\n          height=\"9.425\"\n          x=\"66.952\"\n          y=\".898\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"e\"\n          width=\"25.513\"\n          height=\"9.425\"\n          x=\"68.425\"\n          y=\"6.668\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"f\"\n          width=\"25.513\"\n          height=\"9.425\"\n          x=\"68.916\"\n          y=\"7.037\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"g\"\n          width=\"23.964\"\n          height=\"18.867\"\n          x=\"87.917\"\n          y=\"-5.492\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"2.455\"\n          />\n        </filter>\n        <filter\n          id=\"h\"\n          width=\"19.677\"\n          height=\"8.131\"\n          x=\"90.415\"\n          y=\".979\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"i\"\n          width=\"19.677\"\n          height=\"8.131\"\n          x=\"90.415\"\n          y=\".979\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"j\"\n          width=\"17.968\"\n          height=\"20.405\"\n          x=\"74.006\"\n          y=\"-7.079\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"k\"\n          width=\"17.573\"\n          height=\"20.725\"\n          x=\"89.315\"\n          y=\"-12.068\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"l\"\n          width=\"12.356\"\n          height=\"13.008\"\n          x=\"89.792\"\n          y=\"-3.109\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"m\"\n          width=\"17.573\"\n          height=\"20.725\"\n          x=\"73.477\"\n          y=\"2.174\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"n\"\n          width=\"17.573\"\n          height=\"20.725\"\n          x=\"73.477\"\n          y=\"2.174\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"o\"\n          width=\"17.601\"\n          height=\"20.738\"\n          x=\"85.425\"\n          y=\"-.588\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n        <filter\n          id=\"p\"\n          width=\"15.135\"\n          height=\"17.016\"\n          x=\"88.092\"\n          y=\"2.319\"\n          color-interpolation-filters=\"sRGB\"\n          filterUnits=\"userSpaceOnUse\"\n        >\n          <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\" />\n          <feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\" />\n          <feGaussianBlur\n            result=\"effect1_foregroundBlur_318_41192\"\n            stdDeviation=\"1.473\"\n          />\n        </filter>\n      </defs>\n    </svg>\n    <div class=\"vt-banner-text\">\n      <p style=\"display: inline-block\">The Unified Toolchain for the Web</p>\n      <a\n        target=\"_blank\"\n        class=\"vt-primary-action\"\n        href=\"https://voidzero.dev/posts/announcing-vite-plus?utm_source=vite&utm_content=top_banner\"\n      >\n        Learn more\n      </a>\n    </div>\n    <button aria-label=\"close\" @click=\"dismiss\">\n      <svg\n        class=\"close\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n        aria-hidden=\"true\"\n        focusable=\"false\"\n        viewBox=\"0 0 24 24\"\n      >\n        <path\n          d=\"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z\"\n        />\n      </svg>\n    </button>\n    <div class=\"glow glow--purple\"></div>\n    <div class=\"glow glow--blue\"></div>\n  </div>\n</template>\n\n<style>\nhtml:not(.banner-dismissed) {\n  --vp-layout-top-height: 30px;\n}\n</style>\n\n<style scoped>\n.banner {\n  position: fixed;\n  z-index: 10;\n  box-sizing: border-box;\n  top: 0;\n  left: 0;\n  right: 0;\n  height: var(--vp-layout-top-height);\n  line-height: var(--vp-layout-top-height);\n  text-align: center;\n  font-size: 12px;\n  font-weight: 600;\n  color: white;\n  background: #262626;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  overflow: hidden;\n}\n\n.glow.glow--purple {\n  position: absolute;\n  bottom: -15%;\n  left: -75%;\n  width: 80%;\n  aspect-ratio: 1.5;\n  pointer-events: none;\n  border-radius: 100%;\n  background: linear-gradient(270deg, #7a23a1, #715ebde6 60% 80%, #bd34fe00);\n  filter: blur(15vw);\n  transform: none;\n  opacity: 0.6;\n}\n\n.glow.glow--blue {\n  position: absolute;\n  bottom: -15%;\n  right: -40%;\n  width: 80%;\n  aspect-ratio: 1.5;\n  pointer-events: none;\n  border-radius: 100%;\n  background: linear-gradient(180deg, #61d9ff, #0000);\n  filter: blur(15vw);\n  transform: none;\n  opacity: 0.3;\n}\n\n@media (min-width: 768px) {\n  .glow.glow--blue {\n    top: -15%;\n    right: -40%;\n    width: 80%;\n  }\n\n  .glow.glow--purple {\n    bottom: -15%;\n    left: -40%;\n    width: 80%;\n  }\n}\n\n@media (min-width: 1025px) {\n  .glow.glow--blue {\n    top: -15%;\n    right: -40%;\n    width: 80%;\n  }\n\n  .glow.glow--purple {\n    bottom: -15%;\n    left: -40%;\n    width: 80%;\n  }\n}\n\n.banner-dismissed .banner {\n  display: none;\n}\n\nbutton {\n  position: absolute;\n  right: 0;\n  top: 0;\n  padding: 5px 5px;\n}\n\n.close {\n  width: 20px;\n  height: 20px;\n  fill: #fff;\n  transform: rotate(45deg);\n}\n\n.vt-banner-text {\n  color: #fff;\n  font-size: 14px;\n  margin-left: 0.75rem;\n}\n\n.vt-main {\n  color: transparent;\n  background-image: linear-gradient(120deg, #858487 16%, #9499ff, #9499ff);\n  background-clip: text;\n}\n\n.vt-primary-action {\n  background:\n    radial-gradient(140.35% 140.35% at 175% 94.74%, #2bfdd2, #bd34fe00),\n    radial-gradient(89.94% 89.94% at 18.42% 15.79%, #603cff, #41d1ff00);\n  color: #fff;\n  padding: 4px 8px;\n  border-radius: 5px;\n  font-size: 12px;\n  text-decoration: none;\n  margin: 0 0.75rem;\n  transition: all 0.2s ease-in-out;\n}\n\n@media (max-width: 1280px) {\n  .banner .vt-banner-text,\n  .banner .vt-primary-action {\n    font-size: 10px;\n  }\n\n  .vt-tagline {\n    display: none;\n  }\n}\n\n@media (max-width: 780px) {\n  .vt-tagline {\n    display: none;\n  }\n\n  .vt-coupon {\n    display: none;\n  }\n\n  .vt-primary-action {\n    margin: 0 10px;\n    padding: 4px 8px;\n  }\n\n  .vt-time-now {\n    display: none;\n  }\n}\n\n@media (max-width: 560px) {\n  .vt-place {\n    display: none;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/SupportedVersions.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref, computed } from 'vue'\n\ndeclare const __VITE_VERSION__: string\n\n// Constants\nconst supportedVersionMessage = {\n  color: 'var(--vp-c-brand-1)',\n  text: 'supported',\n}\nconst notSupportedVersionMessage = {\n  color: 'var(--vp-c-danger-1)',\n  text: 'not supported',\n}\nconst previousMajorLatestMinors: Record<string, string> = {\n  '2': '2.9',\n  '3': '3.2',\n  '4': '4.5',\n  '5': '5.4',\n  '6': '6.4',\n  '7': '7.3',\n}\n\n// Current latest Vite version and support info\nconst parsedViteVersion = parseVersion(__VITE_VERSION__)!\nconst supportInfo = computeSupportInfo(parsedViteVersion)\n\n// Check supported version input\nconst checkedVersion = ref(`${Math.max(parsedViteVersion.major - 3, 2)}.0.0`)\nconst checkedResult = computed(() => {\n  const version = checkedVersion.value\n  if (!isValidViteVersion(version)) return notSupportedVersionMessage\n\n  const parsedVersion = parseVersion(checkedVersion.value)\n  if (!parsedVersion) return notSupportedVersionMessage\n\n  const satisfies = (targetVersion: string) => {\n    const compared = parseVersion(targetVersion)!\n    return (\n      parsedVersion.major === compared.major &&\n      parsedVersion.minor >= compared.minor\n    )\n  }\n  const satisfiesOneSupportedVersion =\n    parsedVersion.major >= parsedViteVersion.major || // Treat future major versions as supported\n    supportInfo.regularPatches.some(satisfies) ||\n    supportInfo.importantFixes.some(satisfies) ||\n    supportInfo.securityPatches.some(satisfies)\n\n  return satisfiesOneSupportedVersion\n    ? supportedVersionMessage\n    : notSupportedVersionMessage\n})\n\nfunction parseVersion(version: string) {\n  let [major, minor, patch] = version.split('.').map((v) => {\n    const num = /^\\d+$/.exec(v)?.[0]\n    return num ? parseInt(num) : null\n  })\n  if (!major) return null\n  minor ??= 0\n  patch ??= 0\n\n  return { major, minor, patch }\n}\n\nfunction computeSupportInfo(\n  version: NonNullable<ReturnType<typeof parseVersion>>,\n) {\n  const { major, minor } = version\n  const f = (versions: string[]) => {\n    return versions\n      .map((v) => previousMajorLatestMinors[v] ?? v)\n      .filter((version) => {\n        if (!isValidViteVersion(version)) return false\n        // Negative versions are invalid\n        if (/-\\d/.test(version)) return false\n        return true\n      })\n  }\n\n  return {\n    regularPatches: f([`${major}.${minor}`]),\n    importantFixes: f([`${major - 1}`, `${major}.${minor - 1}`]),\n    securityPatches: f([`${major - 2}`, `${major}.${minor - 2}`]),\n  }\n}\n\nfunction versionsToText(versions: string[]) {\n  versions = versions.map((v) => `<code>vite@${v}</code>`)\n  if (versions.length === 0) return ''\n  if (versions.length === 1) return versions[0]\n  return (\n    versions.slice(0, -1).join(', ') + ' and ' + versions[versions.length - 1]\n  )\n}\n\nfunction isValidViteVersion(version: string) {\n  if (version.length === 1) version += '.'\n  // Vite 0.x shouldn't be mentioned, and Vite 1.x was never released\n  if (version.startsWith('0.') || version.startsWith('1.')) return false\n  return true\n}\n</script>\n\n<template>\n  <div>\n    <ul>\n      <li v-if=\"supportInfo.regularPatches.length\">\n        Regular patches are released for\n        <span v-html=\"versionsToText(supportInfo.regularPatches)\"></span>.\n      </li>\n      <li v-if=\"supportInfo.importantFixes.length\">\n        Important fixes and security patches are backported to\n        <span v-html=\"versionsToText(supportInfo.importantFixes)\"></span>.\n      </li>\n      <li v-if=\"supportInfo.securityPatches.length\">\n        Security patches are also backported to\n        <span v-html=\"versionsToText(supportInfo.securityPatches)\"></span>.\n      </li>\n      <li>\n        All versions before these are no longer supported. Users should upgrade\n        to receive updates.\n      </li>\n    </ul>\n    <p>\n      If you're using Vite\n      <input\n        class=\"checked-input\"\n        type=\"text\"\n        v-model=\"checkedVersion\"\n        placeholder=\"0.0.0\"\n      />, it is\n      <strong :style=\"{ color: checkedResult.color }\">{{\n        checkedResult.text\n      }}</strong\n      >.\n    </p>\n  </div>\n</template>\n\n<style scoped>\n.checked-input {\n  display: inline-block;\n  padding: 0px 5px;\n  width: 100px;\n  color: var(--vp-c-text-1);\n  background: var(--vp-c-bg-soft);\n  font-size: var(--vp-code-font-size);\n  font-family: var(--vp-font-family-mono);\n  border: 1px solid var(--vp-c-divider);\n  border-radius: 5px;\n  transition: border-color 0.1s;\n}\n\n.checked-input:focus,\n.checked-input:hover {\n  border-color: var(--vp-c-brand);\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/SvgImage.vue",
    "content": "<script setup lang=\"ts\">\ndefineProps<{ svg: string }>()\n</script>\n\n<template>\n  <figure class=\"svg-image-root\" v-html=\"svg\" />\n</template>\n\n<style>\n.svg-image-root {\n  background-color: #eee;\n  border-radius: 8px;\n  padding: 1ch;\n  margin: 1ch 0;\n}\nhtml.dark .svg-image-root {\n  background-color: #313641;\n}\n.svg-image-root svg text {\n  font-family: var(--vp-font-family-base);\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/components/YouTubeVideo.vue",
    "content": "<script setup lang=\"ts\">\ndefineProps({\n  videoId: String,\n})\n</script>\n\n<template>\n  <div class=\"full-width-youtube-video\">\n    <iframe\n      width=\"560\"\n      height=\"315\"\n      :src=\"`https://www.youtube.com/embed/${videoId}`\"\n      title=\"YouTube video player\"\n      frameborder=\"0\"\n      allow=\"\n        accelerometer;\n        autoplay;\n        clipboard-write;\n        encrypted-media;\n        gyroscope;\n        picture-in-picture;\n      \"\n      allowfullscreen\n    ></iframe>\n  </div>\n</template>\n\n<style scoped>\n.full-width-youtube-video {\n  position: relative;\n  padding-bottom: 56.25%;\n  height: 0;\n}\n\n.full-width-youtube-video iframe {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: none;\n  border-radius: 0.5rem;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/composables/sponsor.ts",
    "content": "import { onMounted, onUnmounted, ref } from 'vue'\nimport type {\n  Sponsor,\n  SponsorTier,\n} from '@voidzero-dev/vitepress-theme/src/types/sponsors'\nimport voidZeroSvg from './images/voidzero.svg'\nimport boltSvg from './images/bolt.svg'\nimport nuxtLabsSvg from './images/nuxtlabs.svg'\n\ninterface Sponsors {\n  special: Sponsor[]\n  platinum: Sponsor[]\n  platinum_china: Sponsor[]\n  gold: Sponsor[]\n  silver: Sponsor[]\n  bronze: Sponsor[]\n}\n\n// shared data across instances so we load only once.\nconst data = ref<SponsorTier[]>()\n\nconst dataHost = 'https://sponsors.vuejs.org'\nconst dataUrl = `${dataHost}/vite.json`\n\nexport const voidZero = {\n  name: 'VoidZero',\n  url: 'https://voidzero.dev',\n  img: voidZeroSvg,\n} satisfies Sponsor\n\nconst viteSponsors: Pick<Sponsors, 'special' | 'gold'> = {\n  special: [\n    // sponsors patak-dev\n    {\n      name: 'Bolt',\n      url: 'https://bolt.new',\n      img: boltSvg,\n    },\n    // sponsors antfu\n    {\n      name: 'NuxtLabs',\n      url: 'https://nuxtlabs.com',\n      img: nuxtLabsSvg,\n    },\n  ],\n  gold: [\n    // now automated via sponsors.vuejs.org too\n  ],\n}\n\nfunction toggleDarkLogos() {\n  if (data.value) {\n    const isDark = document.documentElement.classList.contains('dark')\n    data.value.forEach(({ items }) => {\n      items.forEach((s: Sponsor) => {\n        if (s.hasDark) {\n          s.img = isDark\n            ? s.img.replace(/(\\.\\w+)$/, '-dark$1')\n            : s.img.replace(/-dark(\\.\\w+)$/, '$1')\n        }\n      })\n    })\n  }\n}\n\nexport function useSponsor() {\n  onMounted(async () => {\n    const ob = new MutationObserver((list) => {\n      for (const m of list) {\n        if (m.attributeName === 'class') {\n          toggleDarkLogos()\n        }\n      }\n    })\n    ob.observe(document.documentElement, { attributes: true })\n    onUnmounted(() => {\n      ob.disconnect()\n    })\n\n    if (data.value) {\n      return\n    }\n\n    const result = await fetch(dataUrl)\n    const json = await result.json()\n\n    data.value = mapSponsors(json)\n    toggleDarkLogos()\n  })\n\n  return {\n    data,\n  }\n}\n\nfunction mapSponsors(sponsors: Sponsors): SponsorTier[] {\n  return [\n    {\n      tier: 'in partnership with',\n      size: 'big' as const,\n      items: viteSponsors['special'],\n    },\n    {\n      tier: 'Platinum Sponsors',\n      size: 'big' as const,\n      items: mapImgPath(sponsors['platinum']),\n    },\n    {\n      tier: 'Gold Sponsors',\n      size: 'medium' as const,\n      items: [...mapImgPath(sponsors['gold']), ...viteSponsors['gold']],\n    },\n  ]\n}\n\nconst viteSponsorNames = new Set(\n  Object.values(viteSponsors).flatMap((sponsors) =>\n    sponsors.map((s) => s.name),\n  ),\n)\n\n/**\n * Map Vue/Vite sponsors data to objects and filter out Vite-specific sponsors\n */\nfunction mapImgPath(sponsors: Sponsor[]) {\n  return sponsors\n    .filter((sponsor) => !viteSponsorNames.has(sponsor.name))\n    .map((sponsor) => ({\n      ...sponsor,\n      img: `${dataHost}/images/${sponsor.img}`,\n    }))\n}\n"
  },
  {
    "path": "docs/.vitepress/theme/index.ts",
    "content": "import { h } from 'vue'\nimport TwoslashFloatingVue from '@shikijs/vitepress-twoslash/client'\nimport '@shikijs/vitepress-twoslash/style.css'\nimport 'virtual:group-icons.css'\nimport 'vitepress-plugin-graphviz/style.css'\nimport Theme from '@voidzero-dev/vitepress-theme/src/vite'\nimport './styles.css'\n\n// components\nimport SvgImage from './components/SvgImage.vue'\nimport YouTubeVideo from './components/YouTubeVideo.vue'\nimport NonInheritBadge from './components/NonInheritBadge.vue'\nimport AsideSponsors from './components/AsideSponsors.vue'\nimport ScrimbaLink from './components/ScrimbaLink.vue'\n\nexport default {\n  Layout() {\n    return h((Theme as any).Layout, null, {\n      'aside-ads-before': () => h(AsideSponsors),\n    })\n  },\n  enhanceApp(ctx: any) {\n    const { app } = ctx\n\n    app.component('SvgImage', SvgImage)\n    app.component('YouTubeVideo', YouTubeVideo)\n    app.component('NonInheritBadge', NonInheritBadge)\n    app.component('ScrimbaLink', ScrimbaLink)\n    app.use(TwoslashFloatingVue)\n\n    Theme.enhanceApp(ctx)\n  },\n}\n"
  },
  {
    "path": "docs/.vitepress/theme/landing/Community.vue",
    "content": "<script setup lang=\"ts\">\nimport { Icon } from '@iconify/vue'\n\ninterface Testimonial {\n  name: string\n  handle: string\n  avatar: string\n  comment: string[]\n}\n\nconst testimonials: Testimonial[] = [\n  {\n    name: 'Ryan Carniato',\n    handle: '@RyanCarniato',\n    avatar:\n      'https://pbs.twimg.com/profile_images/1810837163447308292/8Piov0f6_400x400.jpg',\n    comment: [\n      `I'm loving what Vite enables. We've found building SolidStart that it is less a metaframework but a system of symbiotic Vite plugins. While built with SolidJS in mind, they should scale from our simplest template to opinionated starter. We're building an ecosystem on Vite.`,\n    ],\n  },\n  {\n    name: 'Rich Harris',\n    handle: '@Rich_Harris',\n    avatar:\n      'https://pbs.twimg.com/profile_images/557940120184041473/bFyXy8Pu_400x400.jpeg',\n    comment: [\n      `Vite is basically the united nations of JavaScript at this point. I'll be there as a representative of Sveltelandia`,\n    ],\n  },\n  {\n    name: 'David East',\n    handle: '@_davideast',\n    avatar:\n      'https://pbs.twimg.com/profile_images/1691627325794725888/voQFcYjY_400x400.jpg',\n    comment: [\n      'Each and every time I use Vite, I feel a true sense of pure and unbridled joy.',\n    ],\n  },\n  {\n    name: 'Mark Dalgleish',\n    handle: '@markdalgleish',\n    avatar:\n      'https://pbs.twimg.com/profile_images/754886061872979968/BzaOWhs1_400x400.jpg',\n    comment: [\n      `It's also a great platform to build a framework on since it provides a pluggable dev environment.`,\n      `Community is amazing too.`,\n    ],\n  },\n  {\n    name: 'Jason Miller',\n    handle: '@_developit',\n    avatar:\n      'https://pbs.twimg.com/profile_images/1374778373239681025/Sc9ehtAr_400x400.jpg',\n    comment: [\n      `Every time I suspect I've hit the bounds of what Vite can do, I end up being wrong.`,\n    ],\n  },\n  {\n    name: 'David Cramer',\n    handle: '@zeeg',\n    avatar:\n      'https://pbs.twimg.com/profile_images/1911613315765133312/HVkULegC_400x400.jpg',\n    comment: ['Vite has been a game changer for the industry.'],\n  },\n  {\n    name: 'Dion Almaer',\n    handle: '@dalmaer',\n    avatar:\n      'https://pbs.twimg.com/profile_images/3380865881/f73b3687ff39b795db05fcaf35972270_400x400.jpeg',\n    comment: [\n      'I am so excited to see so many great frameworks teaming up on top of vite. So many will benefit. ❤️ to the vite team.',\n    ],\n  },\n  {\n    name: 'Christoph Nakazawa',\n    handle: '@cpojer',\n    avatar:\n      'https://pbs.twimg.com/profile_images/1910252462126313472/gXgT-jxL_400x400.jpg',\n    comment: ['Vite is gonna eat the (JavaScript) world.'],\n  },\n  {\n    name: 'Nikolaj',\n    handle: '@lopugit',\n    avatar: 'https://avatars.githubusercontent.com/u/13629190?v=4',\n    comment: [\n      'Wow, wow, wow, wow, wow, wow, Vite is..... Vite is.... Wow 🤤🤯🙏',\n    ],\n  },\n]\n</script>\n\n<template>\n  <div class=\"wrapper wrapper--ticks border-t pt-14 sm:pt-30 px-5 sm:px-10\">\n    <div\n      class=\"flex flex-col sm:flex-row justify-between items-center gap-8 sm:gap-20 text-center sm:text-left\"\n    >\n      <div class=\"flex flex-col gap-3\">\n        <h3 class=\"text-white max-w-xl text-balance\">Loved by the community</h3>\n        <p class=\"max-w-md text-white/70 text-balance\">\n          Don't take our word for it - listen to what Vite community members\n          have to say.\n        </p>\n      </div>\n      <div\n        class=\"flex gap-8 sm:gap-12 items-start justify-center sm:justify-start sm:pr-20\"\n      >\n        <!-- GitHub Stars -->\n        <div class=\"flex flex-col gap-3\">\n          <h2 class=\"text-white\">75k+</h2>\n          <p class=\"text-grey flex items-center gap-2\">\n            <Icon icon=\"simple-icons:github\" width=\"20px\" height=\"20px\" />\n            Github Stars\n          </p>\n        </div>\n\n        <!-- NPM Downloads -->\n        <div class=\"flex flex-col gap-3\">\n          <h2 class=\"text-white\">40m+</h2>\n          <p class=\"text-grey\">Weekly NPM downloads</p>\n        </div>\n      </div>\n    </div>\n    <div\n      class=\"pt-14 sm:pt-30 h-[50rem] overflow-clip [mask-image:linear-gradient(to_bottom,black_70%,transparent_100%)]\"\n    >\n      <!-- Masonry Grid -->\n      <div class=\"columns-1 sm:columns-2 lg:columns-3 gap-5\">\n        <div\n          v-for=\"(testimonial, index) in testimonials\"\n          :key=\"index\"\n          class=\"break-inside-avoid mb-5\"\n        >\n          <div\n            class=\"testimonial-card relative overflow-clip isolate rounded-lg p-6 sm:px-8 sm:py-10 flex flex-col gap-6 before:content-[''] before:absolute before:inset-0 before:opacity-0 before:z-0 before:pointer-events-none before:transition-opacity before:duration-100 before:ease-in-out after:content-[''] after:absolute after:inset-px after:z-[1] after:rounded-lg after:bg-slate after:border after:border-nickel after:transition-[border-color,background] after:duration-100 after:ease-in-out hover:before:opacity-100 hover:after:border-transparent\"\n          >\n            <!-- Comment -->\n            <div class=\"relative z-[2] flex flex-col gap-4\">\n              <p\n                v-for=\"(paragraph, pIndex) in testimonial.comment\"\n                :key=\"pIndex\"\n                class=\"text-white/70 leading-relaxed text-sm sm:text-base\"\n              >\n                {{ paragraph }}\n              </p>\n            </div>\n\n            <!-- Author -->\n            <div class=\"relative z-[2] flex items-center gap-5 mt-auto\">\n              <!-- Avatar -->\n              <img\n                :src=\"testimonial.avatar\"\n                :alt=\"testimonial.name\"\n                class=\"w-12 h-12 rounded-sm object-cover flex-shrink-0\"\n                loading=\"lazy\"\n              />\n\n              <!-- Author info -->\n              <div class=\"flex flex-col\">\n                <span class=\"text-grey text-sm font-mono\">{{\n                  testimonial.name\n                }}</span>\n                <span class=\"text-biege text-sm font-mono\">{{\n                  testimonial.handle\n                }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<style scoped>\n/* Background image and animation for ::before pseudo-element */\n.testimonial-card::before {\n  background-image: url('@assets/vite/vite-featurepanel-4-background.jpg');\n  background-size: 150% 150%;\n  background-position: center;\n  animation: move-background 16s ease-in-out infinite;\n}\n\n/* Randomize animation timing for organic feel */\n.testimonial-card:nth-child(2)::before {\n  animation-duration: 18s;\n  animation-delay: -3s;\n}\n\n.testimonial-card:nth-child(3)::before {\n  animation-duration: 14s;\n  animation-delay: -7s;\n}\n\n.testimonial-card:nth-child(4)::before {\n  animation-duration: 20s;\n  animation-delay: -5s;\n}\n\n.testimonial-card:nth-child(5)::before {\n  animation-duration: 15s;\n  animation-delay: -9s;\n}\n\n.testimonial-card:nth-child(6)::before {\n  animation-duration: 19s;\n  animation-delay: -2s;\n}\n\n.testimonial-card:nth-child(7)::before {\n  animation-duration: 17s;\n  animation-delay: -11s;\n}\n\n.testimonial-card:nth-child(8)::before {\n  animation-duration: 16s;\n  animation-delay: -6s;\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/landing/FeatureGrid1.vue",
    "content": "<script setup>\nimport RiveAnimation from '@components/shared/RiveAnimation.vue'\nimport viteAnimation from '@assets/vite/animations/563_x_420_rich_features.riv'\n</script>\n\n<template>\n  <section\n    class=\"wrapper wrapper--ticks border-t grid lg:grid-cols-2 divide-x divide-y divide-nickel\"\n  >\n    <div class=\"flex flex-col gap-3 justify-between\">\n      <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n        <h5 class=\"text-balance sm:text-pretty text-white\">\n          Instant Server Start\n        </h5>\n        <p class=\"sm:max-w-[28rem] text-pretty\">\n          On demand source file serving over native ESM, with blazing fast\n          dependency pre-bundling.\n        </p>\n      </div>\n      <div class=\"relative p-10 sm:p-15 flex justify-center bg-[#370a7f]\">\n        <img\n          class=\"absolute inset-0 h-full w-full object-cover\"\n          src=\"@assets/vite/vite-featurepanel-1-background.jpg\"\n          alt=\"\"\n          inert\n          loading=\"lazy\"\n        />\n        <img\n          class=\"z-1\"\n          src=\"@assets/vite/vite-featurepanel-1-terminal.svg\"\n          width=\"493\"\n          height=\"230\"\n          alt=\"Terminal\"\n          inert\n          loading=\"lazy\"\n        />\n      </div>\n    </div>\n\n    <div class=\"flex flex-col gap-3 justify-between border-r-0\">\n      <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n        <h5 class=\"text-white\">Lightning Fast HMR</h5>\n        <p class=\"max-w-[26rem] text-pretty\">\n          Instantly reflect changes as you save, no matter how big your app is.\n        </p>\n      </div>\n      <div class=\"flex justify-end\">\n        <img\n          src=\"@assets/vite/vite-featurepanel-2-terminal.png\"\n          width=\"1126\"\n          height=\"734\"\n          class=\"md:max-w-[80%]\"\n          inert\n          loading=\"lazy\"\n          alt=\"lightning fast hot module replacement\"\n        />\n      </div>\n    </div>\n\n    <div class=\"p-5 sm:p-10 pb-0 sm:pb-0 flex flex-col gap-3 lg:border-b-0\">\n      <h5 class=\"text-white\">Rich Features Out of the Box</h5>\n      <p class=\"sm:max-w-[28rem] text-pretty\">\n        TypeScript, JSX, CSS, Workers, WebAssembly... and more just a plugin\n        away.\n      </p>\n      <RiveAnimation\n        :desktop-src=\"viteAnimation\"\n        :mobile-src=\"viteAnimation\"\n        :desktop-width=\"563\"\n        :desktop-height=\"300\"\n        :mobile-width=\"563\"\n        :mobile-height=\"420\"\n        canvas-class=\"w-full\"\n      />\n    </div>\n\n    <div class=\"flex flex-col gap-3 justify-between border-r-0 border-b-0\">\n      <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n        <h5 class=\"text-white\">Optimized Build</h5>\n        <p class=\"max-w-[25rem] text-pretty\">\n          Advanced tree-shaking, built-in minification, fine-grained chunking\n          control powered by Rolldown.\n        </p>\n      </div>\n      <div class=\"relative p-10 sm:p-15 flex justify-center bg-[#370a7f]\">\n        <img\n          class=\"absolute inset-0 h-full w-full object-cover\"\n          src=\"@assets/vite/vite-featurepanel-4-background.jpg\"\n          alt=\"\"\n          inert\n          loading=\"lazy\"\n        />\n        <img\n          class=\"z-1\"\n          src=\"@assets/vite/vite-featurepanel-4-terminal.svg\"\n          width=\"436\"\n          height=\"209\"\n          inert\n          loading=\"lazy\"\n          alt=\"optimized build\"\n        />\n      </div>\n    </div>\n  </section>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/landing/FeatureGrid2.vue",
    "content": "<script setup>\nimport RiveAnimation from '@components/shared/RiveAnimation.vue'\nimport flexiblePluginAnimation from '@assets/vite/animations/640_x_300_flexible_plugin.riv'\n</script>\n\n<template>\n  <section\n    class=\"wrapper wrapper--ticks border-t grid lg:grid-cols-2 divide-x divide-y divide-nickel\"\n  >\n    <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n      <h5 class=\"text-balance sm:text-pretty text-white\">\n        Flexible Plugin System\n      </h5>\n      <p class=\"sm:max-w-[28rem] text-pretty\">\n        Vite plugins extends Rollup's well-designed plugin interface with a few\n        extra Vite-specific options.\n      </p>\n      <RiveAnimation\n        :desktop-src=\"flexiblePluginAnimation\"\n        :desktop-width=\"640\"\n        :desktop-height=\"300\"\n        canvas-class=\"w-[calc(100%_+_2.5rem)] mt-5 -mx-5\"\n      />\n    </div>\n\n    <div class=\"flex flex-col gap-3 border-r-0 justify-between\">\n      <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n        <h5 class=\"text-white\">Fully Typed API</h5>\n        <p class=\"max-w-[26rem] text-pretty\">Designed to be built on top of.</p>\n      </div>\n      <div class=\"relative p-5 sm:p-10 flex justify-center bg-[#370a7f]\">\n        <img\n          class=\"absolute inset-0 h-full w-full object-cover\"\n          src=\"@assets/vite/vite-featurepanel-4-background.jpg\"\n          alt=\"\"\n          inert\n          loading=\"lazy\"\n        />\n        <img\n          class=\"z-1\"\n          src=\"@assets/vite/vite-typed-api.svg\"\n          width=\"454\"\n          height=\"252\"\n          inert\n          loading=\"lazy\"\n          alt=\"typed api\"\n        />\n      </div>\n    </div>\n\n    <div class=\"p-5 sm:p-10 flex flex-col gap-3 lg:border-b-0\">\n      <h5 class=\"text-white\">First class SSR Support</h5>\n      <p class=\"sm:max-w-[28rem] text-pretty mb-12 sm:mb-16\">\n        It's never been easier to setup custom SSR (Server-Side Rendering), or\n        build your own SSR framework.\n      </p>\n      <img\n        src=\"@assets/vite/vite-ssr-support.png\"\n        width=\"1008\"\n        height=\"466\"\n        alt=\"SSR Support\"\n        loading=\"lazy\"\n        class=\"w-full px-5\"\n      />\n    </div>\n\n    <div class=\"flex flex-col gap-3 justify-between\">\n      <div class=\"p-5 sm:p-10 flex flex-col gap-3\">\n        <h5 class=\"text-white\">Continuous ecosystem integration</h5>\n        <p class=\"max-w-[25rem] text-pretty\">\n          Our CI continuously tests Vite changes against downstream projects,\n          allowing us to improve Vite with stability and confidence.\n        </p>\n      </div>\n      <div class=\"px-5 sm:px-10 flex justify-center\">\n        <img\n          src=\"@assets/vite/vite-ci.svg\"\n          width=\"476\"\n          height=\"272\"\n          inert\n          loading=\"lazy\"\n          alt=\"continuous ecosystem integration\"\n        />\n      </div>\n    </div>\n  </section>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/landing/Frameworks.vue",
    "content": "<template>\n  <section class=\"wrapper wrapper--ticks border-t py-8 sm:py-16 px-5 sm:px-10\">\n    <img\n      src=\"@assets/vite/vite-frameworks-mobile.png\"\n      alt=\"Frameworks powered by Vite\"\n      loading=\"lazy\"\n      class=\"w-full block sm:hidden\"\n    />\n    <img\n      src=\"@assets/vite/vite-frameworks.png\"\n      alt=\"Frameworks powered by Vite\"\n      loading=\"lazy\"\n      class=\"w-full hidden sm:block\"\n    />\n  </section>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/landing/Hero.vue",
    "content": "<script setup>\nimport RiveAnimation from '@components/shared/RiveAnimation.vue'\nimport CodeGroup from '@components/shared/CodeGroup.vue'\n\nimport viteAnimation from '@assets/vite/animations/641_x_629_vite_masthead.riv'\n\nif (typeof document !== 'undefined') {\n  const preloadLink = document.createElement('link')\n  preloadLink.rel = 'preload'\n  preloadLink.href = viteAnimation\n  preloadLink.as = 'fetch'\n  preloadLink.crossOrigin = 'anonymous'\n  document.head.appendChild(preloadLink)\n}\n\nconst installTabs = [\n  { label: 'npm', code: 'npm create vite@latest', prefix: '$ ' },\n  { label: 'Yarn', code: 'yarn create vite', prefix: '$ ' },\n  { label: 'pnpm', code: 'pnpm create vite', prefix: '$ ' },\n  { label: 'Bun', code: 'bun create vite', prefix: '$ ' },\n  { label: 'Deno', code: 'deno init --npm vite', prefix: '$ ' },\n]\n</script>\n\n<template>\n  <div\n    class=\"wrapper wrapper--ticks grid md:grid-cols-2 w-full border-nickel md:divide-x\"\n  >\n    <div\n      class=\"flex flex-col p-10 justify-between gap-20 items-center md:items-start\"\n    >\n      <div\n        class=\"flex flex-col gap-5 items-center md:items-start text-center md:text-left\"\n      >\n        <a\n          class=\"flex items-center gap-2\"\n          href=\"https://voidzero.dev\"\n          target=\"_blank\"\n        >\n          <span class=\"text-grey text-xs font-mono uppercase tracking-wide\"\n            >By</span\n          >\n          <img\n            src=\"@assets/logos/voidzero-light.svg\"\n            alt=\"VoidZero\"\n            class=\"h-2.5\"\n          />\n        </a>\n        <h1 class=\"text-white text-pretty max-w-[25rem]\">\n          The Build Tool for the Web\n        </h1>\n        <p class=\"text-white/70 md:text-lg max-w-[27rem] text-pretty\">\n          Vite is a blazing fast frontend build tool powering the next\n          generation of web applications.\n        </p>\n        <div class=\"flex items-center gap-5 mt-8\">\n          <a href=\"/guide/\" class=\"button button--primary inline-block w-fit\">\n            Get Started\n          </a>\n          <a\n            href=\"https://github.com/vitejs/vite\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            class=\"button inline-block w-fit\"\n          >\n            View on GitHub\n          </a>\n        </div>\n      </div>\n      <CodeGroup\n        :tabs=\"installTabs\"\n        class=\"hidden md:block w-full -mb-[16px]\"\n        style=\"\n          --vp-code-tab-bg: var(--color-slate);\n          --vp-code-block-bg: var(--color-slate);\n          --vp-code-tab-divider: #000;\n        \"\n      />\n    </div>\n    <div class=\"flex flex-col sm:min-h-[30rem]\">\n      <div\n        class=\"relative px-10 pb-10 md:pt-10 h-full flex flex-col justify-center overflow-clip\"\n      >\n        <RiveAnimation\n          :desktop-src=\"viteAnimation\"\n          :mobile-src=\"viteAnimation\"\n          :desktop-width=\"641\"\n          :desktop-height=\"629\"\n          :mobile-width=\"641\"\n          :mobile-height=\"629\"\n          canvas-class=\"w-full\"\n        />\n      </div>\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/landing/Layout.vue",
    "content": "<script setup>\n// these components live in @voidzero-dev/vitepress-theme\nimport Hero from './Hero.vue'\nimport ViteFeatureGrid1 from './FeatureGrid1.vue'\nimport ViteFeatureGrid2 from './FeatureGrid2.vue'\nimport ViteFrameworks from './Frameworks.vue'\nimport ViteCommunity from './Community.vue'\nimport TrustedBy from '@components/oss/TrustedBy.vue'\nimport HeadingSection from '@components/oss/HeadingSection.vue'\nimport Sponsors from '@components/oss/Sponsors.vue'\nimport Spacer from '@components/shared/Spacer.vue'\nimport Footer from '@components/oss/Footer.vue'\nimport { useSponsor } from '../composables/sponsor'\n\nconst { data: sponsors } = useSponsor()\n</script>\n\n<template>\n  <Hero />\n  <TrustedBy\n    :logos=\"['openai', 'shopify', 'stripe', 'linear', 'clickup', 'wiz']\"\n  />\n  <HeadingSection\n    heading=\"Redefining developer experience\"\n    subheading=\"Vite makes web development enjoyable again\"\n  />\n  <ViteFeatureGrid1 />\n  <HeadingSection heading=\"A shared foundation to build upon\" />\n  <ViteFeatureGrid2 />\n  <HeadingSection heading=\"Powering your favorite frameworks and tools\" />\n  <ViteFrameworks />\n  <ViteCommunity />\n  <Sponsors :sponsors=\"sponsors\" />\n  <Spacer />\n  <Footer\n    heading=\"Start building with Vite\"\n    subheading=\"Prepare for a development environment that can finally keep pace with the speed of your mind.\"\n    button-text=\"Get Started\"\n    button-link=\"/guide/\"\n  />\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/Events.vue",
    "content": "<script setup lang=\"ts\">\nimport background from '@voidzero-dev/vitepress-theme/src/assets/vite/footer-background.jpg'\nimport event1 from '../../../images/events/viteconf_2022.jpg'\nimport event2 from '../../../images/events/viteconf_2023.jpg'\nimport event3 from '../../../images/events/viteconf_2024.jpg'\nimport event4 from '../../../images/events/viteconf_2025.jpg'\n\nconst EVENTS = [\n  {\n    date: '2025',\n    title: 'ViteConf 2025',\n    image: event4,\n    url: 'https://www.youtube.com/watch?v=x7Jsmt_o9ek&list=PLqGQbXn_GDmkJaoykvHCUmXUPjhgH2bVr',\n  },\n  {\n    date: '2024',\n    title: 'ViteConf 2024',\n    image: event3,\n    url: 'https://www.youtube.com/watch?v=mWK3Y_1kmaM&list=PLqGQbXn_GDmnObDzgjUF4Krsfl6OUKxtp',\n  },\n  {\n    date: '2023',\n    title: 'ViteConf 2023',\n    image: event2,\n    url: 'https://www.youtube.com/watch?v=veCxKeLl35A&list=PLqGQbXn_GDmkOsHI7-Wrbv1GgAA4tJZhg',\n  },\n  {\n    date: '2022',\n    title: 'ViteConf 2022',\n    image: event1,\n    url: 'https://www.youtube.com/watch?v=Znd11rVHQOE&list=PLqGQbXn_GDmkI_lwbq5LsVYMEoX2ilKfI',\n  },\n]\n</script>\n\n<template>\n  <div class=\"wrapper wrapper--ticks w-full text-center md:text-left\">\n    <h2\n      class=\"text-white text-2xl px-10 py-5 text-pretty border-nickel border-y\"\n    >\n      Previous events\n    </h2>\n    <div class=\"relative grid md:grid-cols-2 xl:grid-cols-4 wrapper--ticks\">\n      <a\n        v-for=\"event in EVENTS\"\n        :key=\"event.date\"\n        class=\"group event-card block p-0.5\"\n        :style=\"`background-image: url(${background});`\"\n        :href=\"event.url\"\n        target=\"_blank\"\n        rel=\"noopener noreferrer\"\n      >\n        <img\n          :src=\"event.image\"\n          :alt=\"event.title\"\n          class=\"w-full aspect-video object-cover\"\n        />\n        <div class=\"bg-primary group-hover:bg-primary/95 bg-blur-lg\">\n          <h3 class=\"text-white text-xl px-10 py-3 text-pretty\">\n            {{ event.title }}\n          </h3>\n        </div>\n      </a>\n    </div>\n  </div>\n</template>\n\n<style>\n.event-card {\n  background-size: 200% 200%;\n  background-position: 100% 200%;\n  background-blend-mode: overlay;\n  background-color: rgba(0, 0, 0, 0.5);\n}\n.event-card:hover {\n  animation: event-card-hover 10s ease-in-out infinite;\n  background-color: transparent;\n}\n@keyframes event-card-hover {\n  0% {\n    background-position: 100% 200%;\n  }\n  50% {\n    background-position: -100% 200%;\n  }\n  100% {\n    background-position: 100% 200%;\n  }\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/Hero.vue",
    "content": "<template>\n  <div\n    class=\"wrapper wrapper--ticks grid md:grid-cols-2 w-full border-nickel md:divide-x\"\n  >\n    <div\n      class=\"flex flex-col items-center text-center md:text-left md:items-start p-10 gap-5 justify-center\"\n    >\n      <h1 class=\"text-white text-pretty max-w-[35rem]\">\n        5th anniversary of the Vite Team Creation\n      </h1>\n      <p class=\"text-white text-3xl text-pretty max-w-[35rem]\">\n        Vite: The Documentary re-premiere\n      </p>\n      <p class=\"text-white/70 md:text-lg max-w-[35rem] text-pretty\">\n        Join the ecosystem this March 19th at 3 PM UTC to remember the story we\n        wrote together. And participate in the live stage to discuss our past,\n        present, and future. We'll be waiting for you!\n      </p>\n      <div class=\"flex items-start justify-between w-full gap-5 mt-8\">\n        <div class=\"flex items-center gap-5\">\n          <a\n            href=\"https://calendar.google.com/calendar/render?action=TEMPLATE&text=Vite.%20The%20documentary&dates=20260319T150000/20260319T160000&ctz=Europe/London&details=5th%20anniversary%20Community%20time%0A%0AJoin%20on%20Discord:%20https%3A%2F%2Fdiscord.gg%2FPsQ3SfhhDQ\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            class=\"button button--primary inline-block w-fit\"\n          >\n            Add to Calendar\n          </a>\n          <a\n            href=\"https://chat.vite.dev\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            class=\"button inline-block w-fit\"\n          >\n            Join Community\n          </a>\n        </div>\n        <a\n          href=\"https://www.cultrepo.com/\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          class=\"inline-block w-fit grayscale hover:grayscale-0 hover:scale-105 transition-all duration-100\"\n        >\n          <img\n            src=\"../../../images/cultrepo-tv.svg\"\n            width=\"60\"\n            height=\"44\"\n            class=\"block\"\n            inert\n            loading=\"lazy\"\n            alt=\"Cult.Repo\"\n          />\n        </a>\n      </div>\n    </div>\n    <div class=\"flex items-center justify-center p-10 md:min-h-[30rem]\">\n      <img\n        src=\"../../../images/vite-live-community.webp\"\n        width=\"1832\"\n        height=\"1388\"\n        class=\"block sm:max-w-[80%] lg:max-w-[70%]\"\n        inert\n        loading=\"lazy\"\n        alt=\"Vite community: Evan You, Matias Capeletto, Bjorn Lu, Anthony Fu, Sapphi Red, Dominik Göpel, Vladimir Sheremet, Ryan Carniato, Pedro Cattori, Mark Dalgleish, Rich Harris, Fred Schott, Eric Simons, Theo Browne, David Cramer, Misko Hevery\"\n      />\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/Layout.vue",
    "content": "<script setup>\nimport Hero from './Hero.vue'\nimport Timer from './Timer.vue'\nimport TimeoutSwitcher from './TimeoutSwitcher.vue'\nimport VideoIframe from './VideoIframe.vue'\nimport Events from './Events.vue'\nimport Footer from '@components/oss/Footer.vue'\nconst startTime = '2026-03-19T15:00:00.000Z'\n</script>\n\n<template>\n  <TimeoutSwitcher :at=\"startTime\">\n    <template #default>\n      <Hero />\n      <Timer :at=\"startTime\" />\n    </template>\n    <template #timeout>\n      <VideoIframe :at=\"startTime\" />\n    </template>\n  </TimeoutSwitcher>\n  <TimeoutSwitcher :at=\"startTime\">\n    <template #default>\n      <Events />\n    </template>\n  </TimeoutSwitcher>\n  <Footer\n    heading=\"Start building with Vite\"\n    subheading=\"Prepare for a development environment that can finally keep pace with the speed of your mind.\"\n    button-text=\"Get Started\"\n    button-link=\"/guide/\"\n  />\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/TimeoutSwitcher.vue",
    "content": "<script setup>\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nconst props = defineProps({\n  at: {\n    type: String,\n    required: true,\n  },\n})\n\nconst timeoutTimestamp = computed(() => new Date(props.at).getTime())\nconst now = ref(0)\nlet intervalId\n\nconst isTimedOut = computed(() => {\n  return now.value >= timeoutTimestamp.value\n})\n\nonMounted(() => {\n  now.value = Date.now()\n  intervalId = window.setInterval(() => {\n    now.value = Date.now()\n  }, 1000)\n})\n\nonUnmounted(() => {\n  if (intervalId) {\n    window.clearInterval(intervalId)\n  }\n})\n</script>\n\n<template>\n  <slot v-if=\"isTimedOut\" name=\"timeout\" />\n  <slot v-else />\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/Timer.vue",
    "content": "<script setup>\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nconst props = defineProps({\n  at: {\n    type: String,\n    required: true,\n  },\n})\n\nconst targetTimestamp = computed(() => new Date(props.at).getTime())\n\nconst getRemainingMs = () => Math.max(0, targetTimestamp.value - Date.now())\n\nconst remainingMs = ref(0)\nlet intervalId\n\nconst pad = (value) => String(value).padStart(2, '0')\n\nconst formattedCountdown = computed(() => {\n  if (typeof window === 'undefined' || !remainingMs.value) return '00:00:00:00'\n\n  const totalSeconds = Math.floor(remainingMs.value / 1000)\n  const days = Math.floor(totalSeconds / (24 * 60 * 60))\n  const hours = Math.floor((totalSeconds % (24 * 60 * 60)) / (60 * 60))\n  const minutes = Math.floor((totalSeconds % (60 * 60)) / 60)\n  const seconds = totalSeconds % 60\n\n  return `${days}:${pad(hours)}:${pad(minutes)}:${pad(seconds)}`\n})\n\nonMounted(() => {\n  remainingMs.value = getRemainingMs()\n  intervalId = window.setInterval(() => {\n    remainingMs.value = getRemainingMs()\n  }, 1000)\n})\n\nonUnmounted(() => {\n  if (intervalId) {\n    window.clearInterval(intervalId)\n  }\n})\n</script>\n\n<template>\n  <div\n    class=\"wrapper wrapper--ticks grid md:grid-cols-3 w-full border-nickel border-t md:divide-x\"\n  >\n    <div\n      class=\"flex flex-col md:col-span-2 p-10 gap-5 justify-center text-center md:text-left\"\n    >\n      <h2\n        class=\"text-white text-[10vw] md:text-[min(8vw,7rem)] xxl:text-8xl font-semibold font-mono tracking-tight\"\n      >\n        {{ formattedCountdown }}\n      </h2>\n    </div>\n    <div class=\"flex items-center justify-center md:min-h-[30rem] p-10\">\n      <img\n        src=\"../../../images/vite-play.webp\"\n        width=\"600\"\n        height=\"660\"\n        class=\"block max-w-[40%] md:max-w-[60%]\"\n        inert\n        loading=\"lazy\"\n        alt=\"\"\n      />\n    </div>\n  </div>\n</template>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/VideoIframe.vue",
    "content": "<script setup>\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport Header from '@components/oss/Header.vue'\nimport { useYoutubePlayer } from './useYoutubePlayer'\n\nconst props = defineProps({\n  at: {\n    type: String,\n    required: true,\n  },\n})\n\nconst containerEl = ref(null)\nconst iframeEl = ref(null)\nconst isFullscreen = ref(false)\nconst actionsVisible = ref(false)\nconst playButtonEl = ref(null)\nlet hideActionsTimeout = null\n\nconst { player, initPlayer, togglePlayback, seekTo } =\n  useYoutubePlayer(iframeEl)\n\nconst checkVideoPassed = (startAt) => {\n  const totalLength = 39 * 60 + 15 // 39 minutes and 15 seconds\n  const atTime = new Date(startAt).getTime()\n  const now = Date.now()\n  const elapsedSeconds = Math.max(0, Math.floor((now - atTime) / 1000))\n  const isPassed = elapsedSeconds > totalLength\n  return { isPassed, elapsedSeconds }\n}\n\nconst iframeSrc = computed(() => {\n  const { isPassed, elapsedSeconds } = checkVideoPassed(props.at)\n\n  const params = new URLSearchParams({\n    si: 'hhgR4fwkRw9zQ0yx',\n    controls: '0',\n    start: isPassed ? 0 : String(elapsedSeconds),\n    disablekb: '1',\n    rel: '0',\n    autoplay: '1',\n    enablejsapi: '1',\n    origin: typeof window === 'undefined' ? '' : window.location.origin,\n  })\n\n  return `https://www.youtube-nocookie.com/embed/bmWQqAKLgT4?${params.toString()}`\n})\n\nconst pausedState = ref(true)\n\nwatch(\n  () => player.value.state,\n  (newVal, oldVal) => {\n    if (newVal === 'pause') {\n      pausedState.value = true\n    }\n    if (newVal === 'play' && pausedState.value) {\n      const { isPassed, elapsedSeconds } = checkVideoPassed(props.at)\n      if (!isPassed) {\n        pausedState.value = false\n        seekTo(elapsedSeconds)\n      }\n    }\n  },\n)\n\nwatch(\n  () => player.value.state,\n  (newVal) => {\n    if (newVal === 'play' || newVal === 'pause') {\n      playButtonEl.value?.focus()\n    }\n  },\n  { immediate: true },\n)\n\nconst syncFullscreenState = () => {\n  const container = containerEl.value\n  isFullscreen.value = Boolean(\n    container && document.fullscreenElement === container,\n  )\n}\n\nconst toggleFullscreen = () => {\n  const container = containerEl.value\n  if (!container) return\n\n  if (document.fullscreenElement === container) {\n    return document.exitFullscreen()\n  }\n\n  return container.requestFullscreen()\n}\n\nconst clearHideActionsTimeout = () => {\n  if (hideActionsTimeout) {\n    clearTimeout(hideActionsTimeout)\n    hideActionsTimeout = null\n  }\n}\n\nconst scheduleHideActions = () => {\n  clearHideActionsTimeout()\n  hideActionsTimeout = setTimeout(() => {\n    actionsVisible.value = false\n  }, 2000)\n}\n\nconst showActionsOnTouch = () => {\n  actionsVisible.value = true\n  scheduleHideActions()\n}\n\nconst showActions = () => {\n  actionsVisible.value = true\n  scheduleHideActions()\n}\n\nconst hideActions = () => {\n  clearHideActionsTimeout()\n  actionsVisible.value = false\n}\n\nonMounted(() => {\n  document.addEventListener('fullscreenchange', syncFullscreenState)\n})\n\nonBeforeUnmount(() => {\n  document.removeEventListener('fullscreenchange', syncFullscreenState)\n  clearHideActionsTimeout()\n})\n</script>\n\n<template>\n  <div\n    ref=\"containerEl\"\n    class=\"wrapper wrapper--ticks relative w-full border-nickel border-t md:divide-x\"\n  >\n    <Header v-if=\"isFullscreen\" class=\"video-iframe-header\" />\n    <div\n      class=\"relative\"\n      @mouseenter=\"showActions\"\n      @mousemove=\"showActions\"\n      @mouseleave=\"hideActions\"\n      @touchstart=\"showActionsOnTouch\"\n    >\n      <div\n        class=\"video-iframe-mask absolute inset-0 bg-black/50 backdrop-blur-2xl transition-opacity duration-50\"\n        :class=\"\n          player.state === 'pause' ? 'opacity-100' : 'opacity-0 delay-400'\n        \"\n        @click=\"togglePlayback\"\n      />\n      <div class=\"absolute top-0 right-0 z-10 flex gap-2 p-4\">\n        <a\n          href=\"https://discord.gg/spmbbvPb9Q\"\n          target=\"_blank\"\n          rel=\"noopener noreferrer\"\n          class=\"button block w-fit backdrop-blur transition-opacity\"\n          :class=\"\n            actionsVisible || player.state !== 'play'\n              ? 'opacity-100'\n              : 'opacity-0 delay-100 pointer-events-none'\n          \"\n          @focus=\"showActions\"\n        >\n          Chat with us\n        </a>\n        <button\n          type=\"button\"\n          class=\"button block py-1.5 px-2.25 backdrop-blur transition-opacity\"\n          @click=\"toggleFullscreen\"\n          :aria-label=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n          :class=\"\n            actionsVisible || player.state !== 'play'\n              ? 'opacity-100'\n              : 'opacity-0 delay-100 pointer-events-none'\n          \"\n          @focus=\"showActions\"\n        >\n          <svg\n            xmlns=\"http://www.w3.org/2000/svg\"\n            width=\"20\"\n            height=\"20\"\n            viewBox=\"0 0 24 24\"\n            fill=\"none\"\n            stroke=\"currentColor\"\n            stroke-width=\"2\"\n            stroke-linecap=\"round\"\n            stroke-linejoin=\"round\"\n            class=\"block\"\n          >\n            <g v-if=\"isFullscreen\">\n              <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n              <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n              <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\n              <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n            </g>\n            <g v-else>\n              <path d=\"M3 7V5a2 2 0 0 1 2-2h2\" />\n              <path d=\"M17 3h2a2 2 0 0 1 2 2v2\" />\n              <path d=\"M21 17v2a2 2 0 0 1-2 2h-2\" />\n              <path d=\"M7 21H5a2 2 0 0 1-2-2v-2\" />\n              <rect width=\"10\" height=\"8\" x=\"7\" y=\"8\" rx=\"1\" />\n            </g>\n          </svg>\n        </button>\n      </div>\n      <button\n        type=\"button\"\n        class=\"absolute button block left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 p-4 backdrop-blur transition\"\n        @click=\"togglePlayback\"\n        :aria-label=\"player.state === 'play' ? 'Pause video' : 'Play video'\"\n        :class=\"\n          actionsVisible || player.state !== 'play'\n            ? 'opacity-100'\n            : 'opacity-0 delay-100 pointer-events-none'\n        \"\n        @focus=\"showActions\"\n        ref=\"playButtonEl\"\n      >\n        <svg\n          xmlns=\"http://www.w3.org/2000/svg\"\n          width=\"40\"\n          height=\"40\"\n          viewBox=\"0 0 24 24\"\n          fill=\"none\"\n          stroke=\"currentColor\"\n          stroke-width=\"2\"\n          stroke-linecap=\"round\"\n          stroke-linejoin=\"round\"\n        >\n          <g v-if=\"player.state === 'play'\">\n            <line x1=\"10\" x2=\"10\" y1=\"15\" y2=\"9\" />\n            <line x1=\"14\" x2=\"14\" y1=\"15\" y2=\"9\" />\n          </g>\n          <path\n            v-else\n            d=\"M9 9.003a1 1 0 0 1 1.517-.859l4.997 2.997a1 1 0 0 1 0 1.718l-4.997 2.997A1 1 0 0 1 9 14.996z\"\n          />\n          <circle cx=\"12\" cy=\"12\" r=\"10\" />\n        </svg>\n      </button>\n      <iframe\n        ref=\"iframeEl\"\n        @load=\"initPlayer\"\n        width=\"560\"\n        height=\"315\"\n        class=\"w-full h-auto max-h-[calc(100vh-5rem-var(--vp-banner-height,0px))] aspect-video pointer-events-none\"\n        :src=\"iframeSrc\"\n        title=\"YouTube video player\"\n        frameborder=\"0\"\n        allow=\"\n          accelerometer;\n          autoplay;\n          clipboard-write;\n          encrypted-media;\n          gyroscope;\n          picture-in-picture;\n          web-share;\n        \"\n        referrerpolicy=\"strict-origin-when-cross-origin\"\n        allowfullscreen\n        tabindex=\"-1\"\n      />\n    </div>\n  </div>\n</template>\n\n<style scoped>\n.video-iframe-header :deep(.wrapper) {\n  border-color: transparent !important;\n}\n\n.video-iframe-header :deep(.wrapper::before),\n.video-iframe-header :deep(.wrapper::after) {\n  display: none;\n}\n\n.video-iframe-mask {\n  -webkit-mask-image: linear-gradient(\n    to bottom,\n    #000 0%,\n    #000 72px,\n    transparent 100px\n  );\n  mask-image: linear-gradient(to bottom, #000 0%, #000 72px, transparent 100px);\n}\n</style>\n"
  },
  {
    "path": "docs/.vitepress/theme/live/useYoutubePlayer.ts",
    "content": "import { type Ref, onBeforeUnmount, onMounted, ref } from 'vue'\n\ntype YoutubeState = 'play' | 'pause' | 'end' | 'buffer' | 'unstarted' | 'cued'\n\ninterface YoutubePlayerState {\n  state: YoutubeState\n}\n\nconst STATE_BY_CODE: Record<number, YoutubeState> = {\n  [-1]: 'unstarted',\n  [0]: 'end',\n  [1]: 'play',\n  [2]: 'pause',\n  [3]: 'buffer',\n  [5]: 'cued',\n}\n\nexport const useYoutubePlayer = (iframeEl: Ref<HTMLIFrameElement | null>) => {\n  const player = ref<YoutubePlayerState>({ state: 'pause' })\n\n  const postPlayerCommand = (func: string, args: unknown[] = []) => {\n    const frameWindow = iframeEl.value?.contentWindow\n    if (!frameWindow) return\n\n    frameWindow.postMessage(\n      JSON.stringify({\n        event: 'command',\n        func,\n        args,\n      }),\n      '*',\n    )\n  }\n\n  const setStateByCode = (code: number) => {\n    player.value = { state: STATE_BY_CODE[code] ?? 'pause' }\n  }\n\n  const onMessage = (event: MessageEvent) => {\n    const frameWindow = iframeEl.value?.contentWindow\n    if (!frameWindow || event.source !== frameWindow) return\n\n    let payload: unknown = event.data\n    if (typeof payload === 'string') {\n      try {\n        payload = JSON.parse(payload)\n      } catch {\n        return\n      }\n    }\n\n    if (!payload || typeof payload !== 'object') return\n\n    const data = payload as {\n      event?: string\n      info?: number | { playerState?: number }\n    }\n\n    if (data.event === 'onStateChange' && typeof data.info === 'number') {\n      setStateByCode(data.info)\n      return\n    }\n\n    if (\n      data.event === 'infoDelivery' &&\n      data.info &&\n      typeof data.info === 'object' &&\n      typeof data.info.playerState === 'number'\n    ) {\n      setStateByCode(data.info.playerState)\n    }\n  }\n\n  const initPlayer = () => {\n    const frameWindow = iframeEl.value?.contentWindow\n    if (!frameWindow) return\n\n    frameWindow.postMessage(JSON.stringify({ event: 'listening' }), '*')\n    postPlayerCommand('addEventListener', ['onStateChange'])\n    postPlayerCommand('getPlayerState')\n  }\n\n  const play = () => {\n    player.value = { state: 'play' }\n    postPlayerCommand('playVideo')\n  }\n\n  const pause = () => {\n    player.value = { state: 'pause' }\n    postPlayerCommand('pauseVideo')\n  }\n\n  const seekTo = (seconds: number, allowSeekAhead = true) => {\n    postPlayerCommand('seekTo', [seconds, allowSeekAhead])\n  }\n\n  const togglePlayback = () => {\n    if (player.value.state === 'play') {\n      pause()\n      return\n    }\n\n    play()\n  }\n\n  onMounted(() => {\n    window.addEventListener('message', onMessage)\n  })\n\n  onBeforeUnmount(() => {\n    window.removeEventListener('message', onMessage)\n  })\n\n  return {\n    player,\n    initPlayer,\n    play,\n    pause,\n    seekTo,\n    togglePlayback,\n  }\n}\n"
  },
  {
    "path": "docs/.vitepress/theme/styles.css",
    "content": "@import '@voidzero-dev/vitepress-theme/src/styles/index.css';\n\n@source \"./**/*.vue\";\n\n/* Vite */\n:root[data-variant='vite'] {\n  --color-brand: #6b1eb9;\n}\n\n:root.dark:not([data-theme])[data-variant='vite'],\n:root[data-theme='dark'][data-variant='vite'] {\n  --color-brand: var(--color-vite);\n}\n\n/* Forced light mode brand for Vite */\n:root[data-theme='light'][data-variant='vite'] {\n  --color-brand: #6b1eb9;\n}\n"
  },
  {
    "path": "docs/_data/acknowledgements.data.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\n\n// Notable dependencies to highlight (by package name)\nconst notableDependencies = [\n  'rolldown',\n  'postcss',\n  'lightningcss',\n  'chokidar',\n  'magic-string',\n]\n\n// Dev tools used for development\nconst devToolNames = [\n  'eslint',\n  'prettier',\n  'typescript',\n  'vitest',\n  'playwright-chromium',\n]\n\n// Past notable dependencies that Vite used previously\nconst pastNotableDependencies: PastDependency[] = [\n  {\n    name: 'esbuild',\n    description:\n      'JavaScript/TypeScript bundler and minifier (now using Rolldown, Oxc, and LightningCSS)',\n    repository: 'https://github.com/evanw/esbuild',\n  },\n  {\n    name: 'rollup',\n    description: 'ES module bundler (now using Rolldown)',\n    repository: 'https://github.com/rollup/rollup',\n  },\n  {\n    name: 'http-proxy',\n    description: 'HTTP proxying (now using http-proxy-3)',\n    repository: 'https://github.com/http-party/node-http-proxy',\n  },\n  {\n    name: 'acorn',\n    description: 'JavaScript parser',\n    repository: 'https://github.com/acornjs/acorn',\n  },\n  {\n    name: 'fast-glob',\n    description: 'Fast glob matching (now using tinyglobby/fdir)',\n    repository: 'https://github.com/mrmlnc/fast-glob',\n  },\n  {\n    name: 'debug',\n    description: 'Debug logging (now using obug)',\n    repository: 'https://github.com/debug-js/debug',\n  },\n]\n\nconst vitePackageDir = path.resolve(import.meta.dirname, '../../packages/vite')\n\ninterface PackageJson {\n  name: string\n  version: string\n  description?: string\n  author?: string | { name: string; email?: string; url?: string }\n  repository?: string | { type?: string; url?: string }\n  funding?:\n    | string\n    | { url: string; type?: string }\n    | Array<string | { url: string; type?: string }>\n  dependencies?: Record<string, string>\n  devDependencies?: Record<string, string>\n  optionalDependencies?: Record<string, string>\n}\n\nexport interface Dependency {\n  name: string\n  version: string\n  description?: string\n  author?: string\n  authorUrl?: string\n  repository?: string\n  funding?: string\n}\n\nexport interface PastDependency {\n  name: string\n  description: string\n  repository: string\n}\n\nexport interface AuthorPackage {\n  name: string\n  funding?: string\n}\n\nexport interface Author {\n  name: string\n  url?: string\n  funding?: string\n  packages: AuthorPackage[]\n}\n\nexport interface AcknowledgementsData {\n  bundledDependencies: Dependency[]\n  notableDependencies: Dependency[]\n  devTools: Dependency[]\n  pastNotableDependencies: PastDependency[]\n  authors: Author[]\n}\n\n/**\n * Parse the LICENSE.md file to extract bundled dependency names.\n */\nfunction parseBundledDependenciesFromLicense(licensePath: string): string[] {\n  const content = fs.readFileSync(licensePath, 'utf-8')\n\n  // Find the \"# Bundled dependencies:\" section and parse package names from ## headers\n  const bundledSection = content.split('# Bundled dependencies:\\n')[1]\n  if (!bundledSection) return []\n\n  // Match all ## headers which contain package names (comma-separated for grouped packages)\n  const deps = [...bundledSection.matchAll(/^## (.+)$/gm)].flatMap((m) =>\n    // Package names can be comma-separated (e.g., \"## pkg1, pkg2, pkg3\")\n    m[1].split(',').map((n) => n.trim()),\n  )\n  return [...new Set(deps)]\n}\n\nfunction normalizeRepository(\n  repo: PackageJson['repository'],\n): string | undefined {\n  if (!repo) return undefined\n\n  let url: string\n  if (typeof repo === 'string') {\n    url = repo\n  } else if (repo.url) {\n    url = repo.url\n  } else {\n    return undefined\n  }\n  url = url\n    .replace(/^git\\+/, '')\n    .replace(/\\.git$/, '')\n    .replace(/(^|\\/)[^/]+?@/, '$1') // remove \"user@\" from \"ssh://user@host.com:...\"\n    .replace(/(\\.[^.]+?):/, '$1/') // change \".com:\" to \".com/\" from \"ssh://user@host.com:...\"\n    .replace(/^git:\\/\\//, 'https://')\n    .replace(/^ssh:\\/\\//, 'https://')\n  if (url.startsWith('github:')) {\n    return `https://github.com/${url.slice(7)}`\n  } else if (url.startsWith('gitlab:')) {\n    return `https://gitlab.com/${url.slice(7)}`\n  } else if (url.startsWith('bitbucket:')) {\n    return `https://bitbucket.org/${url.slice(10)}`\n  } else if (!url.includes(':') && url.split('/').length === 2) {\n    return `https://github.com/${url}`\n  } else {\n    return url.includes('://') ? url : `https://${url}`\n  }\n}\n\nfunction normalizeFunding(funding: PackageJson['funding']): string | undefined {\n  if (!funding) return undefined\n  if (typeof funding === 'string') return funding\n  if (Array.isArray(funding)) {\n    const first = funding[0]\n    if (typeof first === 'string') return first\n    return first?.url\n  }\n  return funding.url\n}\n\nfunction parseAuthor(author: PackageJson['author']): {\n  name?: string\n  url?: string\n} {\n  if (!author) return {}\n  if (typeof author === 'object') {\n    return { name: author.name, url: author.url }\n  }\n  // Parse string format: \"Name <email> (url)\" or \"Name (url)\" or \"Name <email>\" or \"Name\"\n  let str = author\n  let url: string | undefined\n  const urlMatch = str.match(/\\(([^)]+)\\)$/)\n  if (urlMatch) {\n    url = urlMatch[1]\n    str = str.slice(0, urlMatch.index).trim()\n  }\n  const emailIndex = str.indexOf('<')\n  if (emailIndex !== -1) {\n    str = str.slice(0, emailIndex).trim()\n  }\n  return { name: str || author, url }\n}\n\nfunction readPackageInfo(\n  packageName: string,\n  nodeModulesDir: string,\n): Dependency | null {\n  const packagePath = path.join(nodeModulesDir, packageName, 'package.json')\n\n  try {\n    const content = fs.readFileSync(packagePath, 'utf-8')\n    const pkg: PackageJson = JSON.parse(content)\n    const authorInfo = parseAuthor(pkg.author)\n\n    return {\n      name: pkg.name,\n      version: pkg.version,\n      description: pkg.description,\n      author: authorInfo.name,\n      authorUrl: authorInfo.url,\n      repository: normalizeRepository(pkg.repository),\n      funding: normalizeFunding(pkg.funding),\n    }\n  } catch {\n    // Package might not exist in node_modules (optional peer dep, etc.)\n    return null\n  }\n}\n\nfunction groupByAuthor(dependencies: Dependency[]): Author[] {\n  const authorMap = new Map<\n    string,\n    { url?: string; packages: AuthorPackage[] }\n  >()\n\n  for (const dep of dependencies) {\n    if (dep.author) {\n      const existing = authorMap.get(dep.author)\n      if (existing) {\n        existing.packages.push({ name: dep.name, funding: dep.funding })\n        if (!existing.url && dep.authorUrl) {\n          existing.url = dep.authorUrl\n        }\n      } else {\n        authorMap.set(dep.author, {\n          url: dep.authorUrl,\n          packages: [{ name: dep.name, funding: dep.funding }],\n        })\n      }\n    }\n  }\n\n  return Array.from(authorMap.entries())\n    .map(([name, info]) => {\n      const sortedPackages = info.packages.sort((a, b) =>\n        a.name.localeCompare(b.name),\n      )\n      const fundingUrls = new Set(\n        sortedPackages.map((p) => p.funding).filter(Boolean),\n      )\n      const sharedFunding =\n        fundingUrls.size === 1 ? [...fundingUrls][0] : undefined\n      return {\n        name,\n        url: info.url,\n        funding: sharedFunding,\n        packages: sharedFunding\n          ? sortedPackages.map((p) => ({ name: p.name }))\n          : sortedPackages,\n      }\n    })\n    .sort((a, b) => a.name.localeCompare(b.name))\n}\n\nfunction loadData(): AcknowledgementsData {\n  const licensePath = path.join(vitePackageDir, 'LICENSE.md')\n  const nodeModulesDir = path.join(vitePackageDir, 'node_modules')\n  const rootNodeModulesDir = path.resolve(\n    import.meta.dirname,\n    '../../node_modules',\n  )\n\n  const bundledDepNames = parseBundledDependenciesFromLicense(licensePath)\n  const bundledDependencies = bundledDepNames\n    .map(\n      (name) =>\n        readPackageInfo(name, nodeModulesDir) ||\n        readPackageInfo(name, rootNodeModulesDir),\n    )\n    .filter((dep) => dep != null)\n    .sort((a, b) => a.name.localeCompare(b.name))\n\n  const devTools = devToolNames\n    .map((name) => readPackageInfo(name, rootNodeModulesDir))\n    .filter((dep) => dep != null)\n    .sort((a, b) => a.name.localeCompare(b.name))\n\n  const notableDeps = notableDependencies\n    .map(\n      (name) =>\n        readPackageInfo(name, nodeModulesDir) ||\n        readPackageInfo(name, rootNodeModulesDir),\n    )\n    .filter((dep) => dep != null)\n\n  const nonNotableDeps = bundledDependencies.filter(\n    (d) => !notableDependencies.includes(d.name),\n  )\n\n  return {\n    bundledDependencies,\n    notableDependencies: notableDeps,\n    devTools,\n    pastNotableDependencies,\n    authors: groupByAuthor(nonNotableDeps),\n  }\n}\n\n// Export data for VitePress\ndeclare const data: AcknowledgementsData\nexport { data }\n\nexport default {\n  watch: ['../../packages/vite/LICENSE.md'],\n  load(): AcknowledgementsData {\n    return loadData()\n  },\n}\n"
  },
  {
    "path": "docs/_data/blog.data.ts",
    "content": "import { createContentLoader } from 'vitepress'\n\ninterface Post {\n  title: string\n  url: string\n  date: {\n    time: number\n    string: string\n  }\n}\n\ndeclare const data: Post[]\nexport { data }\n\nexport default createContentLoader('blog/*.md', {\n  // excerpt: true,\n  transform(raw): Post[] {\n    return raw\n      .map(({ url, frontmatter }) => ({\n        title: frontmatter.head.find(\n          (e: any) => e[1].property === 'og:title',\n        )[1].content,\n        url,\n        date: formatDate(frontmatter.date),\n      }))\n      .sort((a, b) => b.date.time - a.date.time)\n  },\n})\n\nfunction formatDate(raw: string): Post['date'] {\n  const date = new Date(raw)\n  date.setUTCHours(12)\n  return {\n    time: +date,\n    string: date.toLocaleDateString('en-US', {\n      year: 'numeric',\n      month: 'long',\n      day: 'numeric',\n    }),\n  }\n}\n"
  },
  {
    "path": "docs/_data/team.js",
    "content": "export const core = [\n  {\n    avatar: 'https://www.github.com/yyx990803.png',\n    name: 'Evan You',\n    title: 'Creator',\n    org: 'Vue.js',\n    orgLink: 'https://vuejs.org/',\n    desc: 'Independent open source developer, creator of Vue.js and Vite.',\n    links: [\n      { icon: 'github', link: 'https://github.com/yyx990803' },\n      { icon: 'x', link: 'https://x.com/youyuxi' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/evanyou.me' },\n    ],\n    sponsor: 'https://github.com/sponsors/yyx990803',\n  },\n  {\n    avatar: 'https://www.github.com/patak-dev.png',\n    name: 'Patak',\n    title: 'A collaborative being',\n    org: 'StackBlitz',\n    orgLink: 'https://stackblitz.com/',\n    desc: 'Core team member of Vite. Team member of Vue.',\n    links: [\n      { icon: 'github', link: 'https://github.com/patak-dev' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/patak.dev' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@patak' },\n    ],\n    sponsor: 'https://github.com/sponsors/patak-dev',\n  },\n  {\n    avatar: 'https://www.github.com/antfu.png',\n    name: 'Anthony Fu',\n    title: 'A fanatical open sourceror',\n    org: 'NuxtLabs',\n    orgLink: 'https://nuxtlabs.com/',\n    desc: 'Core team member of Vite & Vue. Working at NuxtLabs.',\n    links: [\n      { icon: 'github', link: 'https://github.com/antfu' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/antfu.me' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@antfu' },\n    ],\n    sponsor: 'https://github.com/sponsors/antfu',\n  },\n  {\n    avatar: 'https://github.com/bluwy.png',\n    name: 'Bjorn Lu',\n    title: 'Open Source Developer',\n    desc: 'Building tools for fun.',\n    links: [\n      { icon: 'github', link: 'https://github.com/bluwy' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/bluwy.me' },\n      { icon: 'twitter', link: 'https://twitter.com/bluwyoo' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@bluwy' },\n    ],\n    sponsor: 'https://bjornlu.com/sponsor',\n  },\n  {\n    avatar: 'https://github.com/sapphi-red.png',\n    name: 'green',\n    title: 'Web Developer',\n    desc: 'Vite core team member. Call me sapphi or green or midori ;)',\n    links: [\n      { icon: 'github', link: 'https://github.com/sapphi-red' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/sapphi.red' },\n      { icon: 'twitter', link: 'https://twitter.com/sapphi_red' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@sapphi_red' },\n    ],\n    sponsor: 'https://github.com/sponsors/sapphi-red',\n  },\n  {\n    avatar: 'https://github.com/ArnaudBarre.png',\n    name: 'Arnaud Barré',\n    title: 'Frontend Developer',\n    desc: 'Passionate about tooling around TypeScript and React.',\n    links: [\n      { icon: 'github', link: 'https://github.com/ArnaudBarre' },\n      {\n        icon: 'bluesky',\n        link: 'https://bsky.app/profile/arnaud-barre.bsky.social',\n      },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@ArnaudBarre' },\n    ],\n    sponsor: 'https://github.com/sponsors/ArnaudBarre',\n  },\n  {\n    avatar: 'https://github.com/dominikg.png',\n    name: 'Dominik G.',\n    title: 'Resident CI Expert',\n    desc: 'Team Member of Vite and Svelte',\n    links: [\n      { icon: 'github', link: 'https://github.com/dominikg' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@dominikg' },\n    ],\n    sponsor: 'https://github.com/sponsors/dominikg',\n  },\n  {\n    avatar: 'https://github.com/sheremet-va.png',\n    name: 'Vladimir',\n    title: 'Core team member of Vitest & Vite',\n    desc: 'An open source fullstack developer',\n    links: [\n      { icon: 'github', link: 'https://github.com/sheremet-va' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/erus.dev' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@sheremet_va' },\n    ],\n    sponsor: 'https://github.com/sponsors/sheremet-va',\n  },\n  {\n    avatar: 'https://github.com/hi-ogawa.png',\n    name: 'Hiroshi Ogawa',\n    title: 'Team Member of Vitest & Vite',\n    desc: 'Open source enthusiast',\n    links: [\n      { icon: 'github', link: 'https://github.com/hi-ogawa' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/hiogawa.bsky.social' },\n    ],\n    sponsor: 'https://github.com/sponsors/hi-ogawa',\n  },\n  {\n    avatar: 'https://github.com/btea.png',\n    name: 'btea',\n    title: 'Web Developer',\n    links: [{ icon: 'github', link: 'https://github.com/btea' }],\n  },\n]\n\nexport const emeriti = [\n  {\n    avatar: 'https://i.imgur.com/KMed6rQ.jpeg',\n    name: 'Alec Larson',\n    title: 'Entrepreneur',\n    desc: 'Dabbling in social ecommerce, meta frameworks, and board games',\n    links: [\n      { icon: 'github', link: 'https://github.com/aleclarson' },\n      { icon: 'x', link: 'https://x.com/retropragma' },\n      {\n        icon: 'bluesky',\n        link: 'https://bsky.app/profile/retropragma.bsky.social',\n      },\n    ],\n  },\n  {\n    avatar: 'https://github.com/poyoho.png',\n    name: 'yoho',\n    title: 'Frontend Developer',\n    desc: 'Frontend. Vite team member.',\n    links: [\n      { icon: 'github', link: 'https://github.com/poyoho' },\n      { icon: 'x', link: 'https://x.com/yoho_po' },\n    ],\n  },\n  {\n    avatar: 'https://github.com/ygj6.png',\n    name: 'ygj6',\n    title: 'Developer',\n    desc: 'Web Developer. Vue & Vite team member',\n    links: [\n      { icon: 'github', link: 'https://github.com/ygj6' },\n      { icon: 'x', link: 'https://x.com/ygj_66' },\n    ],\n  },\n  {\n    avatar: 'https://github.com/Niputi.png',\n    name: 'Niputi',\n    title: 'Developer',\n    org: 'Computershare Denmark',\n    desc: 'weeb/JavaScript lover.',\n    links: [\n      { icon: 'github', link: 'https://github.com/Niputi' },\n      { icon: 'x', link: 'https://x.com/Niputi_' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/niputi.bsky.social' },\n    ],\n  },\n  {\n    avatar: 'https://github.com/underfin.png',\n    name: 'underfin',\n    title: 'Developer',\n    links: [{ icon: 'github', link: 'https://github.com/underfin' }],\n  },\n  {\n    avatar: 'https://github.com/GrygrFlzr.png',\n    name: 'GrygrFlzr',\n    title: 'Developer',\n    links: [\n      { icon: 'github', link: 'https://github.com/GrygrFlzr' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/bsky.cybeast.dev' },\n    ],\n  },\n  {\n    avatar: 'https://github.com/nihalgonsalves.png',\n    name: 'Nihal Gonsalves',\n    title: 'Senior Software Engineer',\n    links: [{ icon: 'github', link: 'https://github.com/nihalgonsalves' }],\n  },\n  {\n    avatar: 'https://github.com/Shinigami92.png',\n    name: 'Shinigami',\n    title: 'Senior Frontend Engineer',\n    org: 'Faker',\n    orgLink: 'https://fakerjs.dev',\n    desc: 'Passionate TypeScript enthusiast working extensively with Vue SPA.',\n    links: [\n      { icon: 'github', link: 'https://github.com/Shinigami92' },\n      { icon: 'mastodon', link: 'https://elk.zone/mas.to/@Shini92' },\n    ],\n  },\n  {\n    avatar: 'https://github.com/haoqunjiang.png',\n    name: 'Haoqun Jiang',\n    title: 'Core Team Member',\n    org: 'Vue.js',\n    orgLink: 'https://vuejs.org/',\n    desc: 'Curator of best practices for Vue.js tooling',\n    links: [\n      { icon: 'github', link: 'https://github.com/haoqunjiang' },\n      { icon: 'bluesky', link: 'https://bsky.app/profile/haoqun.dev' },\n      { icon: 'mastodon', link: 'https://elk.zone/m.webtoo.ls/@haoqun' },\n    ],\n    sponsor: 'https://github.com/sponsors/haoqunjiang',\n  },\n]\n"
  },
  {
    "path": "docs/acknowledgements.md",
    "content": "---\ntitle: Acknowledgements\ndescription: Vite is built upon the shoulders of giants. Thank you to all the projects and contributors that make Vite possible.\n---\n\n<script setup>\nimport { computed } from 'vue'\nimport { data } from './_data/acknowledgements.data'\nimport { useSponsor, voidZero } from './.vitepress/theme/composables/sponsor'\nimport VPSponsors from '@components/vitepress-default/VPSponsors.vue'\n\nconst { data: sponsorData } = useSponsor()\n\nconst allSponsors = computed(() => {\n  if (!sponsorData.value) return []\n  return [\n    {\n      tier: 'Brought to you by',\n      size: 'big',\n      items: [voidZero],\n    },\n    ...sponsorData.value,\n  ]\n})\n\nfunction npmUrl(name) {\n  return `https://www.npmjs.com/package/${name}`\n}\n</script>\n\n# Acknowledgements\n\nVite is built upon the shoulders of giants. We would like to express our gratitude to all the projects, contributors, and sponsors that make Vite possible.\n\n## Contributors\n\nVite is developed by an international team of contributors. See the [Team page](/team) to meet the core team members.\n\nWe also thank all the [contributors on GitHub](https://github.com/vitejs/vite/graphs/contributors) who have helped improve Vite through code contributions, bug reports, documentation, and documentation translation.\n\n## Sponsors\n\nVite's development is supported by generous sponsors. You can support Vite through [GitHub Sponsors](https://github.com/sponsors/vitejs) or [Open Collective](https://opencollective.com/vite).\n\n<div class=\"sponsors-container\">\n  <VPSponsors :data=\"allSponsors\" />\n</div>\n\n## Dependencies\n\nVite depends on these amazing open source projects:\n\n### Notable Dependencies\n\n<div class=\"deps-list notable\">\n  <div v-for=\"dep in data.notableDependencies\" :key=\"dep.name\" class=\"dep-item\">\n    <div class=\"dep-header\">\n      <a :href=\"npmUrl(dep.name)\" target=\"_blank\" rel=\"noopener\"><code>{{ dep.name }}</code></a>\n      <span class=\"dep-links\">\n        <a v-if=\"dep.repository\" :href=\"dep.repository\" target=\"_blank\" rel=\"noopener\" class=\"dep-link\">Repo</a>\n        <a v-if=\"dep.funding\" :href=\"dep.funding\" target=\"_blank\" rel=\"noopener\" class=\"dep-link sponsor\">Sponsor</a>\n      </span>\n    </div>\n    <p v-if=\"dep.author\" class=\"dep-author\">\n      by <a v-if=\"dep.authorUrl\" :href=\"dep.authorUrl\" target=\"_blank\" rel=\"noopener\">{{ dep.author }}</a><template v-else>{{ dep.author }}</template>\n    </p>\n    <p v-if=\"dep.description\">{{ dep.description }}</p>\n  </div>\n</div>\n\n### Bundled Dependency Authors\n\n<table class=\"authors-table\">\n  <thead>\n    <tr>\n      <th>Author</th>\n      <th>Packages</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr v-for=\"author in data.authors\" :key=\"author.name\">\n      <td>\n        <a v-if=\"author.url\" :href=\"author.url\" target=\"_blank\" rel=\"noopener\">{{ author.name }}</a>\n        <template v-else>{{ author.name }}</template>\n        <a v-if=\"author.funding\" :href=\"author.funding\" target=\"_blank\" rel=\"noopener\" class=\"sponsor-link\">Sponsor</a>\n      </td>\n      <td>\n        <template v-for=\"(pkg, index) in author.packages\" :key=\"pkg.name\">\n          <span class=\"pkg-item\"><a :href=\"npmUrl(pkg.name)\" target=\"_blank\" rel=\"noopener\"><code>{{ pkg.name }}</code></a><a v-if=\"pkg.funding\" :href=\"pkg.funding\" target=\"_blank\" rel=\"noopener\" class=\"sponsor-link\">Sponsor</a></span><template v-if=\"index < author.packages.length - 1\">, </template>\n        </template>\n      </td>\n    </tr>\n  </tbody>\n</table>\n\n::: tip For package authors\nThis section is automatically generated from the `author` and `funding` fields in each package's `package.json`. If you'd like to update how your package appears here, you can update these fields in your package.\n:::\n\n## Development Tools\n\nVite's development workflow is powered by these tools:\n\n<div class=\"deps-list notable\">\n  <div v-for=\"dep in data.devTools\" :key=\"dep.name\" class=\"dep-item\">\n    <div class=\"dep-header\">\n      <a :href=\"npmUrl(dep.name)\" target=\"_blank\" rel=\"noopener\"><code>{{ dep.name }}</code></a>\n      <span class=\"dep-links\">\n        <a v-if=\"dep.repository\" :href=\"dep.repository\" target=\"_blank\" rel=\"noopener\" class=\"dep-link\">Repo</a>\n        <a v-if=\"dep.funding\" :href=\"dep.funding\" target=\"_blank\" rel=\"noopener\" class=\"dep-link sponsor\">Sponsor</a>\n      </span>\n    </div>\n    <p v-if=\"dep.author\" class=\"dep-author\">\n      by <a v-if=\"dep.authorUrl\" :href=\"dep.authorUrl\" target=\"_blank\" rel=\"noopener\">{{ dep.author }}</a><template v-else>{{ dep.author }}</template>\n    </p>\n    <p v-if=\"dep.description\">{{ dep.description }}</p>\n  </div>\n</div>\n\n## Past Notable Dependencies\n\nWe also thank the maintainers of these projects that Vite used in previous versions:\n\n<table>\n  <thead>\n    <tr>\n      <th>Package</th>\n      <th>Description</th>\n      <th>Links</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr v-for=\"dep in data.pastNotableDependencies\" :key=\"dep.name\">\n      <td><a :href=\"npmUrl(dep.name)\" target=\"_blank\" rel=\"noopener\"><code>{{ dep.name }}</code></a></td>\n      <td>{{ dep.description }}</td>\n      <td><a :href=\"dep.repository\" target=\"_blank\" rel=\"noopener\">Repo</a></td>\n    </tr>\n  </tbody>\n</table>\n\n<style scoped>\n.deps-list {\n  display: grid;\n  gap: 1rem;\n  margin: 1rem 0;\n}\n\n.deps-list.notable {\n  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n}\n\n.dep-item {\n  padding: 1rem;\n  border: 1px solid var(--vp-c-divider);\n  border-radius: 8px;\n  background: var(--vp-c-bg-soft);\n}\n\n.dep-item .dep-header {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  gap: 0.5rem;\n}\n\n.dep-item a {\n  color: var(--vp-c-brand-1);\n  text-decoration: none;\n}\n\n.dep-item a:hover {\n  text-decoration: underline;\n}\n\n.dep-item .dep-links {\n  display: flex;\n  gap: 0.5rem;\n}\n\n.dep-item .dep-link {\n  font-size: 0.75rem;\n  padding: 0.25rem 0.5rem;\n  border-radius: 4px;\n  background: var(--vp-c-default-soft);\n}\n\n.dep-item .dep-author {\n  margin: 0.25rem 0 0;\n  color: var(--vp-c-text-2);\n  font-size: 0.8rem;\n}\n\n.dep-item .dep-link.sponsor {\n  background: var(--vp-c-brand-soft);\n}\n\n.dep-item p {\n  margin: 0.5rem 0 0;\n  color: var(--vp-c-text-2);\n  font-size: 0.875rem;\n}\n\n.authors-table .sponsor-link {\n  margin-left: 0.5rem;\n  font-size: 0.75rem;\n  padding: 0.15rem 0.4rem;\n  border-radius: 4px;\n  background: var(--vp-c-brand-soft);\n  color: var(--vp-c-brand-1);\n  text-decoration: none;\n}\n\n.authors-table .sponsor-link:hover {\n  text-decoration: underline;\n}\n</style>\n"
  },
  {
    "path": "docs/blog/announcing-vite2.md",
    "content": "---\ntitle: Announcing Vite 2.0\nauthor:\n  - name: The Vite Team\nsidebar: false\ndate: 2021-02-16\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 2.0\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite2\n  - - meta\n    - property: og:description\n      content: Vite 2 Release Announcement\n---\n\n# Announcing Vite 2.0\n\n_February 16, 2021_ - Check out the [Vite 3.0 announcement](./announcing-vite3.md)\n\n<p style=\"text-align:center\">\n  <img src=\"/logo.svg\" style=\"height:200px\">\n</p>\n\nToday we are excited to announce the official release of Vite 2.0!\n\nVite (French word for \"fast\", pronounced `/vit/`) is a new kind of build tool for frontend web development. Think a pre-configured dev server + bundler combo, but leaner and faster. It leverages browser's [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) support and tools written in compile-to-native languages like [esbuild](https://esbuild.github.io/) to deliver a snappy and modern development experience.\n\nTo get a sense of how fast Vite is, check out [this video comparison](https://twitter.com/amasad/status/1355379680275128321) of booting up a React application on Repl.it using Vite vs. `create-react-app` (CRA).\n\nIf you've never heard of Vite before and would love to learn more about it, check out [the rationale behind the project](https://vite.dev/guide/why.html). If you are interested in how Vite differs from other similar tools, check out the [comparisons](https://v5.vite.dev/guide/comparisons.html).\n\n## What's New in 2.0\n\nSince we decided to completely refactor the internals before 1.0 got out of RC, this is in fact the first stable release of Vite. That said, Vite 2.0 brings about many big improvements over its previous incarnation:\n\n### Framework Agnostic Core\n\nThe original idea of Vite started as a [hacky prototype that serves Vue single-file components over native ESM](https://github.com/vuejs/vue-dev-server). Vite 1 was a continuation of that idea with HMR implemented on top.\n\nVite 2.0 takes what we learned along the way and is redesigned from scratch with a more robust internal architecture. It is now completely framework agnostic, and all framework-specific support is delegated to plugins. There are now [official templates for Vue, React, Preact, Lit Element](https://github.com/vitejs/vite/tree/main/packages/create-vite), and ongoing community efforts for Svelte integration.\n\n### New Plugin Format and API\n\nInspired by [WMR](https://github.com/preactjs/wmr), the new plugin system extends Rollup's plugin interface and is [compatible with many Rollup plugins](https://vite-rollup-plugins.patak.dev/) out of the box. Plugins can use Rollup-compatible hooks, with additional Vite-specific hooks and properties to adjust Vite-only behavior (e.g. differentiating dev vs. build or custom handling of HMR).\n\nThe [programmatic API](https://vite.dev/guide/api-javascript.html) has also been greatly improved to facilitate higher level tools / frameworks built on top of Vite.\n\n### esbuild Powered Dep Pre-Bundling\n\nSince Vite is a native ESM dev server, it pre-bundles dependencies to reduce the number browser requests and handle CommonJS to ESM conversion. Previously Vite did this using Rollup, and in 2.0 it now uses `esbuild` which results in 10-100x faster dependency pre-bundling. As a reference, cold-booting a test app with heavy dependencies like React Material UI previously took 28 seconds on an M1-powered MacBook Pro and now takes ~1.5 seconds. Expect similar improvements if you are switching from a traditional bundler based setup.\n\n### First-class CSS Support\n\nVite treats CSS as a first-class citizen of the module graph and supports the following out of the box:\n\n- **Resolver enhancement**: `@import` and `url()` paths in CSS are enhanced with Vite's resolver to respect aliases and npm dependencies.\n- **URL rebasing**: `url()` paths are automatically rebased regardless of where the file is imported from.\n- **CSS code splitting**: a code-split JS chunk also emits a corresponding CSS file, which is automatically loaded in parallel with the JS chunk when requested.\n\n### Server-Side Rendering (SSR) Support\n\nVite 2.0 ships with [experimental SSR support](https://vite.dev/guide/ssr.html). Vite provides APIs to efficiently load and update ESM-based source code in Node.js during development (almost like server-side HMR), and automatically externalizes CommonJS-compatible dependencies to improve development and SSR build speed. The production server can be completely decoupled from Vite, and the same setup can be easily adapted to perform pre-rendering / SSG.\n\nVite SSR is provided as a low-level feature and we are expecting to see higher level frameworks leveraging it under the hood.\n\n### Opt-in Legacy Browser Support\n\nVite targets modern browsers with native ESM support by default, but you can also opt-in to support legacy browsers via the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy). The plugin automatically generates dual modern/legacy bundles, and delivers the right bundle based on browser feature detection, ensuring more efficient code in modern browsers that support them.\n\n## Give it a Try!\n\nThat was a lot of features, but getting started with Vite is simple! You can spin up a Vite-powered app literally in a minute, starting with the following command (make sure you have Node.js >=12):\n\n```bash\nnpm init @vitejs/app\n```\n\nThen, check out [the guide](https://vite.dev/guide/) to see what Vite provides out of the box. You can also check out the source code on [GitHub](https://github.com/vitejs/vite), follow updates on [Twitter](https://twitter.com/vite_js), or join discussions with other Vite users on our [Discord chat server](https://chat.vite.dev).\n"
  },
  {
    "path": "docs/blog/announcing-vite3.md",
    "content": "---\ntitle: Vite 3.0 is out!\nauthor:\n  name: The Vite Team\ndate: 2022-07-23\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 3\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite3.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite3\n  - - meta\n    - property: og:description\n      content: Vite 3 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 3.0 is out!\n\n_July 23, 2022_ - Check out the [Vite 4.0 announcement](./announcing-vite4.md)\n\nIn February last year, [Evan You](https://twitter.com/youyuxi) released Vite 2. Since then, its adoption has grown non-stop, reaching more than 1 million npm downloads per week. A sprawling ecosystem rapidly formed after the release. Vite is powering a renewed innovation race in Web frameworks. [Nuxt 3](https://v3.nuxtjs.org/) uses Vite by default. [SvelteKit](https://kit.svelte.dev/), [Astro](https://astro.build/), [Hydrogen](https://hydrogen.shopify.dev/), and [SolidStart](https://docs.solidjs.com/quick-start) are all built with Vite. [Laravel has now decided to use Vite by default](https://laravel.com/docs/9.x/vite). [Vite Ruby](https://vite-ruby.netlify.app/) shows how Vite can improve Rails DX. [Vitest](https://vitest.dev) is making strides as a Vite-native alternative to Jest. Vite is behind [Cypress](https://docs.cypress.io/guides/component-testing/writing-your-first-component-test) and [Playwright](https://playwright.dev/docs/test-components)'s new Component Testing features, Storybook has [Vite as an official builder](https://github.com/storybookjs/builder-vite). And [the list goes on](https://patak.dev/vite/ecosystem.html). Maintainers from most of these projects got involved in improving the Vite core itself, working closely with the Vite [team](https://vite.dev/team) and other contributors.\n\n![Vite 3 Announcement Cover Image](/og-image-announcing-vite3.webp)\n\nToday, 16 months from the v2 launch we are happy to announce the release of Vite 3. We decided to release a new Vite major at least every year to align with [Node.js's EOL](https://nodejs.org/en/about/releases/), and take the opportunity to review Vite's API regularly with a short migration path for projects in the ecosystem.\n\nQuick links:\n\n- [Docs](/)\n- [Migration Guide](https://v3.vite.dev/guide/migration.html)\n- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#300-2022-07-13)\n\nIf you are new to Vite, we recommend reading the [Why Vite Guide](https://vite.dev/guide/why.html). Then check out [the Getting Started](https://vite.dev/guide/) and [Features guide](https://vite.dev/guide/features) to see what Vite provides out of the box. As usual, contributions are welcome at [GitHub](https://github.com/vitejs/vite). More than [600 collaborators](https://github.com/vitejs/vite/graphs/contributors) have helped improve Vite so far. Follow the updates on [Twitter](https://twitter.com/vite_js), or join discussions with other Vite users on our [Discord chat server](https://chat.vite.dev).\n\n## New Documentation\n\nGo to [vite.dev](https://vite.dev) to enjoy the new v3 docs. Vite is now using the new [VitePress](https://vitepress.vuejs.org) default theme, with a stunning dark mode between other features.\n\n[![Vite documentation frontpage](../images/v3-docs.webp)](https://vite.dev)\n\nSeveral projects in the ecosystem have already migrated to it (see [Vitest](https://vitest.dev), [vite-plugin-pwa](https://vite-plugin-pwa.netlify.app/), and [VitePress](https://vitepress.vuejs.org/) itself).\n\nIf you need to access the Vite 2 docs, they will remain online at [v2.vite.dev](https://v2.vite.dev). There is also a new [main.vite.dev](https://main.vite.dev) subdomain, where each commit to Vite’s main branch is auto deployed. This is useful when testing beta versions or contributing to the core’s development.\n\nThere is also now an official Spanish translation, that has been added to the previous Chinese and Japanese translations:\n\n- [简体中文](https://cn.vite.dev/)\n- [日本語](https://ja.vite.dev/)\n- [Español](https://es.vite.dev/)\n\n## Create Vite Starter Templates\n\n[create-vite](/guide/#trying-vite-online) templates have been a great tool to quickly test Vite with your favorite framework. In Vite 3, all of the templates got a new theme in line with the new docs. Open them online and start playing with Vite 3 now:\n\n<div class=\"stackblitz-links\">\n<a target=\"_blank\" href=\"https://vite.new\"><img width=\"75\" height=\"75\" src=\"../images/vite.svg\" alt=\"Vite logo\"></a>\n<a target=\"_blank\" href=\"https://vite.new/vue\"><img width=\"75\" height=\"75\" src=\"../images/vue.svg\" alt=\"Vue logo\"></a>\n<a target=\"_blank\" href=\"https://vite.new/svelte\"><img width=\"60\" height=\"60\" src=\"../images/svelte.svg\" alt=\"Svelte logo\"></a>\n<a target=\"_blank\" href=\"https://vite.new/react\"><img width=\"75\" height=\"75\" src=\"../images/react.svg\" alt=\"React logo\"></a>\n<a target=\"_blank\" href=\"https://vite.new/preact\"><img width=\"65\" height=\"65\" src=\"../images/preact.svg\" alt=\"Preact logo\"></a>\n<a target=\"_blank\" href=\"https://vite.new/lit\"><img width=\"60\" height=\"60\" src=\"../images/lit.svg\" alt=\"Lit logo\"></a>\n</div>\n\n<style>\n.stackblitz-links {\n  display: flex;\n  width: 100%;\n  justify-content: space-around;\n  align-items: center;\n}\n@media screen and (max-width: 550px) {\n  .stackblitz-links {\n    display: grid;\n    grid-template-columns: 1fr 1fr 1fr;\n    width: 100%;\n    gap: 2rem;\n    padding-left: 3rem;\n    padding-right: 3rem;\n  }\n}\n.stackblitz-links > a {\n  width: 70px;\n  height: 70px;\n  display: grid;\n  align-items: center;\n  justify-items: center;\n}\n.stackblitz-links > a:hover {\n  filter: drop-shadow(0 0 0.5em #646cffaa);\n}\n</style>\n\nThe theme is now shared by all templates. This should help better convey the scope for these starters as minimal templates to get started with Vite. For more complete solutions including linting, testing setup, and other features, there are official Vite-powered templates for some frameworks like [create-vue](https://github.com/vuejs/create-vue) and [create-svelte](https://github.com/sveltejs/kit). There is a community-maintained list of templates at [Awesome Vite](https://github.com/vitejs/awesome-vite#templates).\n\n## Dev Improvements\n\n### Vite CLI\n\n<pre style=\"background-color: var(--vp-code-block-bg);padding:2em;border-radius:8px;max-width:100%;overflow-x:auto;\">\n  <span style=\"color:lightgreen\"><b>VITE</b></span> <span style=\"color:lightgreen\">v3.0.0</span>  <span style=\"color:gray\">ready in <b>320</b> ms</span>\n\n  <span style=\"color:lightgreen\"><b>➜</b></span>  <span style=\"color:white\"><b>Local</b>:</span>   <span style=\"color:cyan\">http://127.0.0.1:5173/</span>\n  <span style=\"color:green\"><b>➜</b></span>  <span style=\"color:gray\"><b>Network</b>: use --host to expose</span>\n</pre>\n\nApart from the CLI’s aesthetics improvements, you’ll notice that the default dev server port is now 5173 and the preview server listening at 4173. This change ensures Vite will avoid collisions with other tools.\n\n### Improved WebSocket Connection Strategy\n\nOne of the pain points of Vite 2 was configuring the server when running behind a proxy. Vite 3 changes the default connection scheme so it works out of the box in most scenarios. All these setups are now tested as part of the Vite Ecosystem CI through [`vite-setup-catalogue`](https://github.com/sapphi-red/vite-setup-catalogue).\n\n### Cold Start Improvements\n\nVite now avoids full reload during cold start when imports are injected by plugins while crawling the initial statically imported modules ([#8869](https://github.com/vitejs/vite/issues/8869)).\n\n<details>\n  <summary><b>Click to learn more</b></summary>\n\nIn Vite 2.9, both the scanner and optimizer were run in the background. In the best scenario, where the scanner would find every dependency, no reload was needed in cold start. But if the scanner missed a dependency, a new optimization phase and then a reload were needed. Vite was able to avoid some of these reloads in v2.9, as we detected if the new optimized chunks were compatible with the ones the browser had. But if there was a common dep, the sub-chunks could change and a reload was required to avoid duplicated state. In Vite 3, the optimized deps aren't handed to the browser until the crawling of static imports is done. A quick optimization phase is issued if there is a missing dep (for example, injected by a plugin), and only then, the bundled deps are sent. So, a page reload is no longer needed for these cases.\n\n</details>\n\n<img style=\"background-color: var(--vp-code-block-bg);padding:4%;border-radius:8px;\" width=\"100%\" height=\"auto\" src=\"../images/vite-3-cold-start.svg\" alt=\"Two graphs comparing Vite 2.9 and Vite 3 optimization strategy\">\n\n### import.meta.glob\n\n`import.meta.glob` support was rewritten. Read about the new features in the [Glob Import Guide](/guide/features.html#glob-import):\n\n[Multiple Patterns](/guide/features.html#multiple-patterns) can be passed as an array\n\n```js\nimport.meta.glob(['./dir/*.js', './another/*.js'])\n```\n\n[Negative Patterns](/guide/features.html#negative-patterns) are now supported (prefixed with `!`) to ignore some specific files\n\n```js\nimport.meta.glob(['./dir/*.js', '!**/bar.js'])\n```\n\n[Named Imports](/guide/features.html#named-imports) can be specified to improve tree-shaking\n\n```js\nimport.meta.glob('./dir/*.js', { import: 'setup' })\n```\n\n[Custom Queries](/guide/features.html#custom-queries) can be passed to attach metadata\n\n```js\nimport.meta.glob('./dir/*.js', { query: { custom: 'data' } })\n```\n\n[Eager Imports](/guide/features.html#glob-import) is now passed as a flag\n\n```js\nimport.meta.glob('./dir/*.js', { eager: true })\n```\n\n### Aligning WASM Import with Future Standards\n\nThe WebAssembly import API has been revised to avoid collisions with future standards and to make it more flexible:\n\n```js\nimport init from './example.wasm?init'\n\ninit().then((instance) => {\n  instance.exports.test()\n})\n```\n\nLearn more in the [WebAssembly guide](/guide/features.html#webassembly)\n\n## Build Improvements\n\n### ESM SSR Build by Default\n\nMost SSR frameworks in the ecosystem were already using ESM builds. So, Vite 3 makes ESM the default format for SSR builds. This allows us to streamline previous [SSR externalization heuristics](https://vite.dev/guide/ssr.html#ssr-externals), externalizing dependencies by default.\n\n### Improved Relative Base Support\n\nVite 3 now properly supports relative base (using `base: ''`), allowing built assets to be deployed to different bases without re-building. This is useful when the base isn't known at build time, for example when deploying to content-addressable networks like [IPFS](https://ipfs.io/).\n\n## Experimental Features\n\n### Built Asset Paths fine-grained Control (Experimental)\n\nThere are other deploy scenarios where this isn't enough. For example, if the generated hashed assets need to be deployed to a different CDN from the public files, then finer-grained control is required over path generation at build time. Vite 3 provides an experimental API to modify the built file paths. Check [Build Advanced Base Options](/guide/build.html#advanced-base-options) for more information.\n\n### Esbuild Deps Optimization at Build Time (Experimental)\n\nOne of the main differences between dev and build time is how Vite handles dependencies. During build time, [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is used to allow importing CJS only dependencies (like React). When using the dev server, esbuild is used instead to pre-bundle and optimize dependencies, and an inline interop scheme is applied while transforming user code importing CJS deps. During the development of Vite 3, we introduced the changes needed to also allow the use of [esbuild to optimize dependencies during build time](https://v3.vite.dev/guide/migration.html#using-esbuild-deps-optimization-at-build-time). [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) can then be avoided, making dev and build time work in the same way.\n\nGiven that Rollup v3 will be out in the next months, and we're going to follow up with another Vite major, we've decided to make this mode optional to reduce v3 scope and give Vite and the ecosystem more time to work out possible issues with the new CJS interop approach during build time. Frameworks may switch to using esbuild deps optimization during build time by default at their own pace before Vite 4.\n\n### HMR Partial Accept (Experimental)\n\nThere is opt-in support for [HMR Partial Accept](https://github.com/vitejs/vite/pull/7324). This feature could unlock finer-grained HMR for framework components that export several bindings in the same module. You can learn more at [the discussion for this proposal](https://github.com/vitejs/vite/discussions/7309).\n\n## Bundle Size Reduction\n\nVite cares about its publish and install footprint; a fast installation of a new app is a feature. Vite bundles most of its dependencies and tries to use modern lightweight alternatives where possible. Continuing with this ongoing goal, Vite 3 publish size is 30% smaller than v2.\n\n|             | Publish Size | Install Size |\n| ----------- | :----------: | :----------: |\n| Vite 2.9.14 |    4.38MB    |    19.1MB    |\n| Vite 3.0.0  |    3.05MB    |    17.8MB    |\n| Reduction   |     -30%     |     -7%      |\n\nIn part, this reduction was possible by making some dependencies that most users weren't needing optional. First, [Terser](https://github.com/terser/terser) is no longer installed by default. This dependency was no longer needed since we already made esbuild the default minifier for both JS and CSS in Vite 2. If you use `build.minify: 'terser'`, you'll need to install it (`npm add -D terser`). We also moved [node-forge](https://github.com/digitalbazaar/forge) out of the monorepo, implementing support for automatic https certificate generation as a new plugin: [`@vitejs/plugin-basic-ssl`](https://v3.vite.dev/guide/migration.html#automatic-https-certificate-generation). Since this feature only creates untrusted certificates that are not added to the local store, it didn't justify the added size.\n\n## Bug Fixing\n\nA triaging marathon was spearheaded by [@bluwyoo](https://twitter.com/bluwyoo), [@sapphi_red](https://twitter.com/sapphi_red), that recently joined the Vite team. During the past three months, the Vite open issues were reduced from 770 to 400. And this dive was achieved while the newly open PRs were at an all-time high. At the same time, [@haoqunjiang](https://twitter.com/haoqunjiang) had also curated a comprehensive [overview of Vite issues](https://github.com/vitejs/vite/discussions/8232).\n\n[![Graph of open issues and pull requests in Vite](../images/v3-open-issues-and-PRs.webp)](https://www.repotrends.com/vitejs/vite)\n\n[![Graph of new issues and pull requests in Vite](../images/v3-new-open-issues-and-PRs.webp)](https://www.repotrends.com/vitejs/vite)\n\n## Compatibility Notes\n\n- Vite no longer supports Node.js 12 / 13 / 15, which reached its EOL. Node.js 14.18+ / 16+ is now required.\n- Vite is now published as ESM, with a CJS proxy to the ESM entry for compatibility.\n- The Modern Browser Baseline now targets browsers which support the [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta) features.\n- JS file extensions in SSR and library mode now use a valid extension (`js`, `mjs`, or `cjs`) for output JS entries and chunks based on their format and the package type.\n\nLearn more in the [Migration Guide](https://v3.vite.dev/guide/migration.html).\n\n## Upgrades to Vite Core\n\nWhile working towards Vite 3, we also improved the contributing experience for collaborators to [Vite Core](https://github.com/vitejs/vite).\n\n- Unit and E2E tests have been migrated to [Vitest](https://vitest.dev), providing a faster and more stable DX. This move also works as dog fooding for an important infrastructure project in the ecosystem.\n- VitePress build is now tested as part of CI.\n- Vite upgraded to [pnpm 7](https://pnpm.io/), following the rest of the ecosystem.\n- Playgrounds have been moved to [`/playgrounds`](https://github.com/vitejs/vite/tree/main/playground) out of packages directory.\n- The packages and playgrounds are now `\"type\": \"module\"`.\n- Plugins are now bundled using [unbuild](https://github.com/unjs/unbuild), and [plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx) and [plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) were moved to TypeScript.\n\n## The Ecosystem is Ready for v3\n\nWe have worked closely with projects in the ecosystem to ensure that frameworks powered by Vite are ready for Vite 3. [vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci) allows us to run the CI's from the leading players in the ecosystem against Vite's main branch and receive timely reports before introducing a regression. Today's release should soon be compatible with most projects using Vite.\n\n## Acknowledgments\n\nVite 3 is the result of the aggregate effort of members of the [Vite Team](/team) working together with ecosystem project maintainers and other collaborators to Vite core.\n\nWe want to thank everyone who has implemented features, and fixes, given feedback, and have been involved in Vite 3:\n\n- Vite team members [@youyuxi](https://twitter.com/youyuxi), [@patak_dev](https://twitter.com/patak_dev), [@antfu7](https://twitter.com/antfu7), [@bluwyoo](https://twitter.com/bluwyoo), [@sapphi_red](https://twitter.com/sapphi_red), [@haoqunjiang](https://twitter.com/haoqunjiang), [@poyoho](https://github.com/poyoho), [@Shini_92](https://twitter.com/Shini_92), and [@retropragma](https://twitter.com/retropragma).\n- [@benmccann](https://github.com/benmccann), [@danielcroe](https://twitter.com/danielcroe), [@brillout](https://twitter.com/brillout), [@sheremet_va](https://twitter.com/sheremet_va), [@userquin](https://twitter.com/userquin), [@enzoinnocenzi](https://twitter.com/enzoinnocenzi), [@maximomussini](https://twitter.com/maximomussini), [@IanVanSchooten](https://twitter.com/IanVanSchooten), the [Astro team](https://astro.build/), and all other maintainers of frameworks and plugins in the ecosystem in that helped shape v3.\n- [@dominikg](https://github.com/dominikg) for his work on vite-ecosystem-ci.\n- [@ZoltanKochan](https://twitter.com/ZoltanKochan) for his work on [pnpm](https://pnpm.io/), and for his responsiveness when we needed support with it.\n- [@rixo](https://github.com/rixo) for HMR Partial Accept support.\n- [@KiaKing85](https://twitter.com/KiaKing85) for getting the theme ready for the Vite 3 release, and [@\\_brc_dd](https://twitter.com/_brc_dd) for working on the VitePress internals.\n- [@CodingWithCego](https://twitter.com/CodingWithCego) for the new Spanish translation, and [@ShenQingchuan](https://twitter.com/ShenQingchuan), [@hiro-lapis](https://github.com/hiro-lapis) and others in the Chinese and Japanese translations teams for keeping the translated docs up to date.\n\nWe also want to thank individuals and companies sponsoring the Vite team, and companies investing in Vite development: some of [@antfu7](https://twitter.com/antfu7)'s work on Vite and the ecosystem is part of his job at [Nuxt Labs](https://nuxtlabs.com/), and [StackBlitz](https://stackblitz.com/) hired [@patak_dev](https://twitter.com/patak_dev) to work full time on Vite.\n\n## What's Next\n\nWe'll take the following months to ensure a smooth transition for all the projects built on top of Vite. So the first minors will be focused on continuing our triaging efforts with a focus on newly opened issues.\n\nThe Rollup team is [working on its next major](https://twitter.com/lukastaegert/status/1544186847399743488), to be released in the following months. Once the Rollup plugins ecosystem has time to update, we'll follow up with a new Vite major. This will give us another opportunity to introduce more significant changes this year, which we could take to stabilize some of the experimental features introduced in this release.\n\nIf you are interested in helping improve Vite, the best way to get on board is to help with triaging issues. Join [our Discord](https://chat.vite.dev) and look for the `#contributing` channel. Or get involved in our `#docs`, `#help` others, or create plugins. We are just getting started. There are many open ideas to keep improving Vite's DX.\n"
  },
  {
    "path": "docs/blog/announcing-vite4-3.md",
    "content": "---\ntitle: Vite 4.3 is out!\nauthor:\n  name: The Vite Team\ndate: 2023-04-20\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 4.3\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite4-3.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite4-3\n  - - meta\n    - property: og:description\n      content: Vite 4.3 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 4.3 is out!\n\n_April 20, 2023_\n\n![Vite 4.3 Announcement Cover Image](/og-image-announcing-vite4-3.webp)\n\nQuick links:\n\n- Docs: [English](/), [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/)\n- [Vite 4.3 Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#430-2023-04-20)\n\n## Performance Improvements\n\nIn this minor, we focused on improving the dev server performance. The resolve logic got streamlined, improving hot paths and implementing smarter caching for finding `package.json`, TS config files, and resolved URL in general.\n\nYou can read a detailed walkthrough of the performance work done in this blog post by one of Vite Contributors: [How we made Vite 4.3 faaaaster 🚀](https://sun0day.github.io/blog/vite/why-vite4_3-is-faster.html).\n\nThis sprint resulted in speed improvements across the board compared to Vite 4.2.\n\nThese are the performance improvements as measured by [sapphi-red/performance-compare](https://github.com/sapphi-red/performance-compare), which tests an app with 1000 React Components cold and warm dev server startup time as well as HMR times for a root and a leaf component:\n\n| **Vite (babel)**   |  Vite 4.2 | Vite 4.3 | Improvement |\n| :----------------- | --------: | -------: | ----------: |\n| **dev cold start** | 17249.0ms | 5132.4ms |      -70.2% |\n| **dev warm start** |  6027.8ms | 4536.1ms |      -24.7% |\n| **Root HMR**       |    46.8ms |   26.7ms |      -42.9% |\n| **Leaf HMR**       |    27.0ms |   12.9ms |      -52.2% |\n\n| **Vite (swc)**     |  Vite 4.2 | Vite 4.3 | Improvement |\n| :----------------- | --------: | -------: | ----------: |\n| **dev cold start** | 13552.5ms | 3201.0ms |      -76.4% |\n| **dev warm start** |  4625.5ms | 2834.4ms |      -38.7% |\n| **Root HMR**       |    30.5ms |   24.0ms |      -21.3% |\n| **Leaf HMR**       |    16.9ms |   10.0ms |      -40.8% |\n\n![Vite 4.3 vs 4.2 startup time comparison](../images/vite4-3-startup-time.webp)\n\n![Vite 4.3 vs 4.2 HMR time comparison](../images/vite4-3-hmr-time.webp)\n\nYou can read more information about the benchmark [here](https://gist.github.com/sapphi-red/25be97327ee64a3c1dce793444afdf6e). Specs and Versions for this performance run:\n\n- CPU: Ryzen 9 5900X, Memory: DDR4-3600 32GB, SSD: WD Blue SN550 NVME SSD\n- Windows 10 Pro 21H2 19044.2846\n- Node.js 18.16.0\n- Vite and React Plugin versions\n  - Vite 4.2 (babel): Vite 4.2.1 + plugin-react 3.1.0\n  - Vite 4.3 (babel): Vite 4.3.0 + plugin-react 4.0.0-beta.1\n  - Vite 4.2 (swc): Vite 4.2.1 + plugin-react-swc 3.2.0\n  - Vite 4.3 (swc): Vite 4.3.0 + plugin-react-swc 3.3.0\n\nEarly adopters have also reported seeing 1.5x-2x dev startup time improvement on real apps while testing the Vite 4.3 beta. We'd love to know the results for your apps.\n\n## Profiling\n\nWe'll continue to work on Vite's performance. We're working on an official [Benchmark tool](https://github.com/vitejs/vite-benchmark) for Vite that let us get performance metrics for each Pull Request.\n\nAnd [vite-plugin-inspect](https://github.com/antfu/vite-plugin-inspect) now has more performance-related features to help you identify which plugins or middlewares are the bottleneck for your applications.\n\nUsing `vite --profile` (and then pressing `p`) once the page loads will save a CPU profile of the dev server startup. You can open them in an app as [speedscope](https://www.speedscope.app/) to identify performance issues. And you can share your findings with the Vite Team in a [Discussion](https://github.com/vitejs/vite/discussions) or in [Vite's Discord](https://chat.vite.dev).\n\n## Next Steps\n\nWe decided to do a single Vite Major this year aligning with the [EOL of Node.js 16](https://endoflife.date/nodejs) in September, dropping support for both Node.js 14 and 16 in it. If you would like to get involved, we started a [Vite 5 Discussion](https://github.com/vitejs/vite/discussions/12466) to gather early feedback.\n"
  },
  {
    "path": "docs/blog/announcing-vite4.md",
    "content": "---\ntitle: Vite 4.0 is out!\nauthor:\n  name: The Vite Team\ndate: 2022-12-09\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 4\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite4.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite4\n  - - meta\n    - property: og:description\n      content: Vite 4 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 4.0 is out!\n\n_December 9, 2022_ - Check out the [Vite 5.0 announcement](./announcing-vite5.md)\n\nVite 3 [was released](./announcing-vite3.md) five months ago. npm downloads per week have gone from 1 million to 2.5 million since then. The ecosystem has matured too, and continues to grow. In this year's [Jamstack Conf survey](https://twitter.com/vite_js/status/1589665610119585793), usage among the community jumped from 14% to 32% while keeping a high 9.7 satisfaction score. We saw the stable releases of [Astro 1.0](https://astro.build/), [Nuxt 3](https://v3.nuxtjs.org/), and other Vite-powered frameworks that are innovating and collaborating: [SvelteKit](https://kit.svelte.dev/), [Solid Start](https://www.solidjs.com/blog/introducing-solidstart), [Qwik City](https://qwik.builder.io/qwikcity/overview/). Storybook announced first-class support for Vite as one of its main features for [Storybook 7.0](https://storybook.js.org/blog/first-class-vite-support-in-storybook/). Deno now [supports Vite](https://www.youtube.com/watch?v=Zjojo9wdvmY). [Vitest](https://vitest.dev) adoption is exploding, it will soon represent half of Vite's npm downloads. Nx is also investing in the ecosystem, and [officially supports Vite](https://nx.dev/packages/vite).\n\n[![Vite 4 Ecosystem](../images/ecosystem-vite4.webp)](https://viteconf.org/2022/replay)\n\nAs a showcase of the growth Vite and related projects have experienced, the Vite ecosystem gathered on October 11th at [ViteConf 2022](https://viteconf.org/2022/replay). We saw representatives from the main web framework and tools tell stories of innovation and collaboration. And in a symbolic move, the Rollup team choose that exact day to release [Rollup 3](https://rollupjs.org).\n\nToday, the Vite [team](https://vite.dev/team) with the help of our ecosystem partners, is happy to announce the release of Vite 4, powered during build time by Rollup 3. We've worked with the ecosystem to ensure a smooth upgrade path for this new major. Vite is now using [Rollup 3](https://github.com/vitejs/vite/issues/9870), which allowed us to simplify Vite's internal asset handling and has many improvements. See the [Rollup 3 release notes here](https://github.com/rollup/rollup/releases/tag/v3.0.0).\n\n![Vite 4 Announcement Cover Image](/og-image-announcing-vite4.webp)\n\nQuick links:\n\n- [Docs](/)\n- [Migration Guide](https://v4.vite.dev/guide/migration.html)\n- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#400-2022-12-09)\n\nDocs in other languages:\n\n- [简体中文](https://cn.vite.dev/)\n- [日本語](https://ja.vite.dev/)\n- [Español](https://es.vite.dev/)\n\nIf you recently started using Vite, we suggest reading the [Why Vite Guide](https://vite.dev/guide/why.html) and checking out [the Getting Started](https://vite.dev/guide/) and [Features guide](https://vite.dev/guide/features). If you want to get involved, contributions are welcome at [GitHub](https://github.com/vitejs/vite). Almost [700 collaborators](https://github.com/vitejs/vite/graphs/contributors) have contributed to Vite. Follow the updates on [Twitter](https://twitter.com/vite_js) and [Mastodon](https://webtoo.ls/@vite), or collaborate with others on our [Discord community](https://chat.vite.dev).\n\n## Start playing with Vite 4\n\nUse `pnpm create vite` to scaffold a Vite project with your preferred framework, or open a started template online to play with Vite 4 using [vite.new](https://vite.new).\n\nYou can also run `pnpm create vite-extra` to get access to templates from other frameworks and runtimes (Solid, Deno, SSR, and library starters). `create vite-extra` templates are also available when you run `create vite` under the `Others` option.\n\nNote that Vite starter templates are intended to be used as a playground to test Vite with different frameworks. When building your next project, we recommend reaching out to the starters recommended by each framework. Some frameworks now redirect in `create vite` to their starters too (`create-vue` and `Nuxt 3` for Vue, and `SvelteKit` for Svelte).\n\n## New React plugin using SWC during development\n\n[SWC](https://swc.rs/) is now a mature replacement for [Babel](https://babeljs.io/), especially in the context of React projects. SWC's React Fast Refresh implementation is a lot faster than Babel, and for some projects, it is now a better alternative. From Vite 4, two plugins are available for React projects with different tradeoffs. We believe that both approaches are worth supporting at this point, and we'll continue to explore improvements to both plugins in the future.\n\n### @vitejs/plugin-react\n\n[@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react) is a plugin that uses esbuild and Babel, achieving fast HMR with a small package footprint and the flexibility of being able to use the Babel transform pipeline.\n\n### @vitejs/plugin-react-swc (new)\n\n[@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) is a new plugin that uses esbuild during build, but replaces Babel with SWC during development. For big projects that don't require non-standard React extensions, cold start and Hot Module Replacement (HMR) can be significantly faster.\n\n## Browser Compatibility\n\nThe modern browser build now targets `safari14` by default for wider ES2020 compatibility. This means that modern builds can now use [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) and that the [nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) isn't transpiled anymore. If you need to support older browsers, you can add [`@vitejs/plugin-legacy`](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) as usual.\n\n## Importing CSS as a String\n\nIn Vite 3, importing the default export of a `.css` file could introduce a double loading of CSS.\n\n```ts\nimport cssString from './global.css'\n```\n\nThis double loading could occur since a `.css` file will be emitted and it's likely that the CSS string will also be used by the application code — for example, injected by the framework runtime. From Vite 4, the `.css` default export [has been deprecated](https://github.com/vitejs/vite/issues/11094). The `?inline` query suffix modifier needs to be used in this case, as that doesn't emit the imported `.css` styles.\n\n```ts\nimport stuff from './global.css?inline'\n```\n\nLearn more in the [Migration Guide](https://v4.vite.dev/guide/migration.html).\n\n## Environment Variables\n\nVite now uses `dotenv` 16 and `dotenv-expand` 9 (previously `dotenv` 14 and `dotenv-expand` 5). If you have a value including `#` or `` ` ``, you will need to wrap them with quotes.\n\n```diff\n-VITE_APP=ab#cd`ef\n+VITE_APP=\"ab#cd`ef\"\n```\n\nFor more details, see the [`dotenv`](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md) and [`dotenv-expand` changelog](https://github.com/motdotla/dotenv-expand/blob/master/CHANGELOG.md).\n\n## Other Features\n\n- CLI Shortcuts (press `h` during dev to see them all) ([#11228](https://github.com/vitejs/vite/pull/11228))\n- Support for patch-package when pre bundling dependencies ([#10286](https://github.com/vitejs/vite/issues/10286))\n- Cleaner build logs output ([#10895](https://github.com/vitejs/vite/issues/10895)) and switch to `kB` to align with browser dev tools ([#10982](https://github.com/vitejs/vite/issues/10982))\n- Improved error messages during SSR ([#11156](https://github.com/vitejs/vite/issues/11156))\n\n## Reduced Package Size\n\nVite cares about its footprint, to speed up installation, especially in the use case of playgrounds for documentation and reproductions. And once more, this major brings improvements in Vite's package size. Vite 4 install size is 23% smaller compared to vite 3.2.5 (14.1 MB vs 18.3 MB).\n\n## Upgrades to Vite Core\n\n[Vite Core](https://github.com/vitejs/vite) and [vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci) continue to evolve to provide a better experience to maintainers and collaborators and to ensure that Vite development scales to cope with the growth in the ecosystem.\n\n### Framework plugins out of core\n\n[`@vitejs/plugin-vue`](https://github.com/vitejs/vite-plugin-vue) and [`@vitejs/plugin-react`](https://github.com/vitejs/vite-plugin-react) have been part of Vite core monorepo since the first versions of Vite. This helped us to get a close feedback loop when making changes as we were getting both Core and the plugins tested and released together. With [vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci) we can get this feedback with these plugins developed on independent repositories, so from Vite 4, [they have been moved out of the Vite core monorepo](https://github.com/vitejs/vite/pull/11158). This is meaningful for Vite's framework-agnostic story and will allow us to build independent teams to maintain each of the plugins. If you have bugs to report or features to request, please create issues on the new repositories moving forward: [`vitejs/vite-plugin-vue`](https://github.com/vitejs/vite-plugin-vue) and [`vitejs/vite-plugin-react`](https://github.com/vitejs/vite-plugin-react).\n\n### vite-ecosystem-ci improvements\n\n[vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci) extends Vite's CI by providing on-demand status reports on the state of the CIs of [most major downstream projects](https://github.com/vitejs/vite-ecosystem-ci/tree/main/tests). We run vite-ecosystem-ci three times a week against Vite's main branch and receive timely reports before introducing a regression. Vite 4 will soon be compatible with most projects using Vite, which already prepared branches with the needed changes and will be releasing them in the next few days. We are also able to run vite-ecosystem-ci on-demand on PRs using `/ecosystem-ci run` in a comment, allowing us to know [the effect of changes](https://github.com/vitejs/vite/pull/11269#issuecomment-1343365064) before they hit main.\n\n## Acknowledgments\n\nVite 4 wouldn't be possible without uncountable hours of work by Vite contributors, many of them maintainers of downstream projects and plugins, and the efforts of the [Vite Team](/team). All of us have worked together to improve Vite's DX once more, for every framework and app using it. We're grateful to be able to improve a common base for such a vibrant ecosystem.\n\nWe're also thankful to individuals and companies sponsoring the Vite team, and companies investing directly in Vite's future: [@antfu7](https://twitter.com/antfu7)'s work on Vite and the ecosystem is part of his job at [Nuxt Labs](https://nuxtlabs.com/), [Astro](https://astro.build) is funding [@bluwyoo](https://twitter.com/bluwyoo)'s Vite core work, and [StackBlitz](https://stackblitz.com/) hires [@patak_dev](https://twitter.com/patak_dev) to work full time on Vite.\n\n## Next steps\n\nOur immediate focus would be on triaging newly opened issues to avoid disruption by possible regressions. If you would like to get involved and help us improve Vite, we suggest starting with issues triaging. Join [our Discord](https://chat.vite.dev) and reach out on the `#contributing` channel. Polish our `#docs` story, and `#help` others. We need to continue to build a helpful and welcoming community for the next wave of users, as Vite's adoption continues to grow.\n\nThere are a lot of open fronts to keep improving the DX of everyone that has chosen Vite to power their frameworks and develop their apps. Onwards!\n"
  },
  {
    "path": "docs/blog/announcing-vite5-1.md",
    "content": "---\ntitle: Vite 5.1 is out!\nauthor:\n  name: The Vite Team\ndate: 2024-02-08\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 5.1\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite5-1.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite5-1\n  - - meta\n    - property: og:description\n      content: Vite 5.1 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 5.1 is out!\n\n_February 8, 2024_\n\n![Vite 5.1 Announcement Cover Image](/og-image-announcing-vite5-1.webp)\n\nVite 5 [was released](./announcing-vite5.md) last November, and it represented another big leap for Vite and the ecosystem. A few weeks ago we celebrated 10 million weekly npm downloads and 900 contributors to the Vite repo. Today, we're excited to announce the release of Vite 5.1.\n\nQuick links: [Docs](/), [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#510-2024-02-08)\n\nDocs in other languages: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/)\n\nTry Vite 5.1 online in StackBlitz: [vanilla](https://vite.new/vanilla-ts), [vue](https://vite.new/vue-ts), [react](https://vite.new/react-ts), [preact](https://vite.new/preact-ts), [lit](https://vite.new/lit-ts), [svelte](https://vite.new/svelte-ts), [solid](https://vite.new/solid-ts), [qwik](https://vite.new/qwik-ts).\n\nIf you're new to Vite, we suggest reading first the [Getting Started](/guide/) and [Features](/guide/features) guides.\n\nTo stay up to date, follow us on [X](https://x.com/vite_js) or [Mastodon](https://webtoo.ls/@vite).\n\n## Vite Runtime API\n\nVite 5.1 adds experimental support for a new Vite Runtime API. It allows running any code by processing it with Vite plugins first. It is different from `server.ssrLoadModule` because the runtime implementation is decoupled from the server. This lets library and framework authors implement their own layer of communication between the server and the runtime. This new API is intended to replace Vite's current SSR primitives once it is stable.\n\nThe new API brings many benefits:\n\n- Support for HMR during SSR.\n- It is decoupled from the server, so there is no limit on how many clients can use a single server - every client has its own module cache (you can even communicate with it how you want - using message channel/fetch call/direct function call/websocket).\n- It doesn't depend on any node/bun/deno built-in APIs, so it can run in any environment.\n- It's easy to integrate with tools that have their own mechanism to run code (you can provide a runner to use `eval` instead of `new AsyncFunction` for example).\n\nThe initial idea [was proposed by Pooya Parsa](https://github.com/nuxt/vite/pull/201) and implemented by [Anthony Fu](https://github.com/antfu) as the [vite-node](https://github.com/vitest-dev/vitest/tree/main/packages/vite-node#readme) package to [power Nuxt 3 Dev SSR](https://antfu.me/posts/dev-ssr-on-nuxt) and later also used as the base for [Vitest](https://vitest.dev). So the general idea of vite-node has been battle-tested for quite some time now. This is a new iteration of the API by [Vladimir Sheremet](https://github.com/sheremet-va), who had already re-implemented vite-node in Vitest and took the learnings to make the API even more powerful and flexible when adding it to Vite Core. The PR was one year in the makings, you can see the evolution and discussions with ecosystem maintainers [here](https://github.com/vitejs/vite/issues/12165).\n\n::: info\nThe Vite Runtime API evolved into the Module Runner API, released in Vite 6 as part of the [Environment API](/guide/api-environment).\n:::\n\n## Features\n\n### Improved support for `.css?url`\n\nImport CSS files as URLs now works reliably and correctly. This was the last remaining hurdle in Remix's move to Vite. See ([#15259](https://github.com/vitejs/vite/issues/15259)).\n\n### `build.assetsInlineLimit` now supports a callback\n\nUsers can now [provide a callback](/config/build-options.html#build-assetsinlinelimit) that returns a boolean to opt-in or opt-out of inlining for specific assets. If `undefined` is returned, the default logic applies. See ([#15366](https://github.com/vitejs/vite/issues/15366)).\n\n### Improved HMR for circular import\n\nIn Vite 5.0, accepted modules within circular imports always triggered a full page reload even if they can be handled fine in the client. This is now relaxed to allow HMR to apply without a full page reload, but if any error happens during HMR, the page will be reloaded. See ([#15118](https://github.com/vitejs/vite/issues/15118)).\n\n### Support `ssr.external: true` to externalize all SSR packages\n\nHistorically, Vite externalizes all packages except for linked packages. This new option can be used to force externalize all packages including linked packages too. This is handy in tests within monorepos where we want to emulate the usual case of all packages externalized, or when using `ssrLoadModule` to load an arbitrary file and we want to always external packages as we don't care about HMR. See ([#10939](https://github.com/vitejs/vite/issues/10939)).\n\n### Expose `close` method in the preview server\n\nThe preview server now exposes a `close` method, which will properly teardown the server including all opened socket connections. See ([#15630](https://github.com/vitejs/vite/issues/15630)).\n\n## Performance improvements\n\nVite keeps getting faster with each release, and Vite 5.1 is packed with performance improvements. We measured the loading time for 10K modules (25 level deep tree) using [vite-dev-server-perf](https://github.com/yyx990803/vite-dev-server-perf) for all minor versions from Vite 4.0. This is a good benchmark to measure the effect of Vite's bundle-less approach. Each module is a small TypeScript file with a counter and imports to other files in the tree, so this mostly measuring the time it takes to do the requests a separate modules. In Vite 4.0, loading 10K modules took 8 seconds on a M1 MAX. We had a breakthrough in [Vite 4.3 were we focused on performance](./announcing-vite4-3.md), and we were able to load them in 6.35 seconds. In Vite 5.1, we managed to do another performance leap. Vite is now serving the 10K modules in 5.35 seconds.\n\n![Vite 10K Modules Loading time progression](../images/vite5-1-10K-modules-loading-time.webp)\n\nThe results of this benchmark run on Headless Puppeteer and are a good way to compare versions. They don't represent the time as experienced by users though. When running the same 10K modules in an Incognito window is Chrome, we have:\n\n| 10K Modules           | Vite 5.0 | Vite 5.1 |\n| --------------------- | :------: | :------: |\n| Loading time          |  2892ms  |  2765ms  |\n| Loading time (cached) |  2778ms  |  2477ms  |\n| Full reload           |  2003ms  |  1878ms  |\n| Full reload (cached)  |  1682ms  |  1604ms  |\n\n### Run CSS preprocessors in threads\n\nVite now has opt-in support for running CSS preprocessors in threads. You can enable it using [`css.preprocessorMaxWorkers: true`](/config/shared-options.html#css-preprocessormaxworkers). For a Vuetify 2 project, dev startup time was reduced by 40% with this feature enabled. There is [performance comparison for others setups in the PR](https://github.com/vitejs/vite/pull/13584#issuecomment-1678827918). See ([#13584](https://github.com/vitejs/vite/issues/13584)). [Give Feedback](https://github.com/vitejs/vite/discussions/15835).\n\n### New options to improve server cold starts\n\nYou can set `optimizeDeps.holdUntilCrawlEnd: false` to switch to a new strategy for deps optimization that may help in big projects. We're considering switching to this strategy by default in the future. [Give Feedback](https://github.com/vitejs/vite/discussions/15834). ([#15244](https://github.com/vitejs/vite/issues/15244))\n\n### Faster resolving with cached checks\n\nThe `fs.cachedChecks` optimization is now enabled by default. In Windows, `tryFsResolve` was ~14x faster with it, and resolving ids overall got a ~5x speed up in the triangle benchmark. ([#15704](https://github.com/vitejs/vite/issues/15704))\n\n### Internal performance improvements\n\nThe dev server had several incremental performance gains. A new middleware to short-circuit on 304 ([#15586](https://github.com/vitejs/vite/issues/15586)). We avoided `parseRequest` in hot paths ([#15617](https://github.com/vitejs/vite/issues/15617)). Rollup is now properly lazy loaded ([#15621](https://github.com/vitejs/vite/issues/15621))\n\n## Deprecations\n\nWe continue to reduce Vite's API surface where possible to make the project maintainable long term.\n\n### Deprecated `as` option in `import.meta.glob`\n\nThe standard moved to [Import Attributes](https://github.com/tc39/proposal-import-attributes), but we don't plan to replace `as` with a new option at this point. Instead, it is recommended that the user switches to `query`. See ([#14420](https://github.com/vitejs/vite/issues/14420)).\n\n### Removed experimental build-time pre-bundling\n\nBuild-time pre-bundling, an experimental feature added in Vite 3, is removed. With Rollup 4 switching its parser to native, and Rolldown being worked on, both the performance and the dev-vs-build inconsistency story for this feature are no longer valid. We want to continue improving dev/build consistency, and have concluded that using Rolldown for \"prebundling during dev\" and \"production builds\" is the better bet moving forward. Rolldown may also implement caching in a way that is a lot more efficient during build than deps prebundling. See ([#15184](https://github.com/vitejs/vite/issues/15184)).\n\n## Get Involved\n\nWe are grateful to the [900 contributors to Vite Core](https://github.com/vitejs/vite/graphs/contributors), and the maintainers of plugins, integrations, tools, and translations that keeps pushing the ecosystem forward. If you're enjoying Vite, we invite you to participate and help us. Check out our [Contributing Guide](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md), and jump into [triaging issues](https://github.com/vitejs/vite/issues), [reviewing PRs](https://github.com/vitejs/vite/pulls), answering questions at [GitHub Discussions](https://github.com/vitejs/vite/discussions) and helping others in the community in [Vite Land](https://chat.vite.dev).\n\n## Acknowledgments\n\nVite 5.1 is possible thanks to our community of contributors, maintainers in the ecosystem, and the [Vite Team](/team). A shout out to the individuals and companies sponsoring Vite development. [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build) for hiring Vite team members. And also to the sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs), [Vite's Open Collective](https://opencollective.com/vite), and [Evan You's GitHub Sponsors](https://github.com/sponsors/yyx990803).\n"
  },
  {
    "path": "docs/blog/announcing-vite5.md",
    "content": "---\ntitle: Vite 5.0 is out!\nauthor:\n  name: The Vite Team\ndate: 2023-11-16\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 5\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite5.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite5\n  - - meta\n    - property: og:description\n      content: Vite 5 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 5.0 is out!\n\n_November 16, 2023_\n\n![Vite 5 Announcement Cover Image](/og-image-announcing-vite5.webp)\n\nVite 4 [was released](./announcing-vite4.md) almost a year ago, and it served as a solid base for the ecosystem. npm downloads per week jumped from 2.5 million to 7.5 million, as projects keep building on a shared infrastructure. Frameworks continued to innovate, and on top of [Astro](https://astro.build/), [Nuxt](https://nuxt.com/), [SvelteKit](https://kit.svelte.dev/), [Solid Start](https://www.solidjs.com/blog/introducing-solidstart), [Qwik City](https://qwik.builder.io/qwikcity/overview/), between others, we saw new frameworks joining and making the ecosystem stronger. [RedwoodJS](https://redwoodjs.com/) and [Remix](https://remix.run/) switching to Vite paves the way for further adoption in the React ecosystem. [Vitest](https://vitest.dev) kept growing at an even faster pace than Vite. Its team has been hard at work and will soon [release Vitest 1.0](https://github.com/vitest-dev/vitest/issues/3596). The story of Vite when used with other tools such as [Storybook](https://storybook.js.org), [Nx](https://nx.dev), and [Playwright](https://playwright.dev) kept improving, and the same goes for environments, with Vite dev working both in [Deno](https://deno.com) and [Bun](https://bun.sh).\n\nWe had the second edition of [ViteConf](https://viteconf.org/23/replay) a month ago, hosted by [StackBlitz](https://stackblitz.com). Like last year, most of the projects in the ecosystem got together to share ideas and connect to keep expanding the commons. We're also seeing new pieces complement the meta-framework tool belt like [Volar](https://volarjs.dev/) and [Nitro](https://nitro.build/). The Rollup team released [Rollup 4](https://rollupjs.org) that same day, a tradition Lukas started last year.\n\nSix months ago, Vite 4.3 [was released](./announcing-vite4.md). This release significantly improved the dev server performance. However, there is still ample room for improvement. At ViteConf, [Evan You unveiled Vite's long-term plan to work on Rolldown](https://www.youtube.com/watch?v=hrdwQHoAp0M), a Rust-port of Rollup with compatible APIs. Once it is ready, we intend to use it in Vite Core to take on the tasks of both Rollup and esbuild. This will mean a boost in build performance (and later on in dev performance too as we move perf-sensitive parts of Vite itself to Rust), and a big reduction of inconsistencies between dev and build. Rolldown is currently in early stages and the team is preparing to open source the codebase before the end of the year. Stay tuned!\n\nToday, we mark another big milestone in Vite's path. The Vite [team](/team), [contributors](https://github.com/vitejs/vite/graphs/contributors), and ecosystem partners, are excited to announce the release of Vite 5. Vite is now using [Rollup 4](https://github.com/vitejs/vite/pull/14508), which already represents a big boost in build performance. And there are also new options to improve your dev server performance profile.\n\nVite 5 focuses on cleaning up the API (removing deprecated features) and streamlines several features closing long-standing issues, for example switching `define` to use proper AST replacements instead of regexes. We also continue to take steps to future-proof Vite (Node.js 18+ is now required, and [the CJS Node API has been deprecated](/guide/migration#deprecate-cjs-node-api)).\n\nQuick links:\n\n- [Docs](/)\n- [Migration Guide](/guide/migration)\n- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#500-2023-11-16)\n\nDocs in other languages:\n\n- [简体中文](https://cn.vite.dev/)\n- [日本語](https://ja.vite.dev/)\n- [Español](https://es.vite.dev/)\n- [Português](https://pt.vite.dev/)\n- [한국어](https://ko.vite.dev/)\n- [Deutsch](https://de.vite.dev/) (new translation!)\n\nIf you're new to Vite, we suggest reading first the [Getting Started](/guide/) and [Features](/guide/features) guides.\n\nWe appreciate the more than [850 contributors to Vite Core](https://github.com/vitejs/vite/graphs/contributors), and the maintainers and contributors of Vite plugins, integrations, tools, and translations that have helped us reach here. We encourage you to get involved and continue to improve Vite with us. You can learn more at our [Contributing Guide](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md). To get started, we recommend [triaging issues](https://github.com/vitejs/vite/issues), [reviewing PRs](https://github.com/vitejs/vite/pulls), sending failing tests PRs based on open issues, and helping others in [Discussions](https://github.com/vitejs/vite/discussions) and Vite Land's [help forum](https://discord.com/channels/804011606160703521/1019670660856942652). You'll learn a lot along the way and have a smooth path to further contributions to the project. If you have doubts, join us on our [Discord community](https://chat.vite.dev) and say hi on the [#contributing channel](https://discord.com/channels/804011606160703521/804439875226173480).\n\nTo stay up to date, follow us on [X](https://twitter.com/vite_js) or [Mastodon](https://webtoo.ls/@vite).\n\n## Quick start with Vite 5\n\nUse `pnpm create vite` to scaffold a Vite project with your preferred framework, or open a started template online to play with Vite 5 using [vite.new](https://vite.new). You can also run `pnpm create vite-extra` to get access to templates from other frameworks and runtimes (Solid, Deno, SSR, and library starters). `create vite-extra` templates are also available when you run `create vite` under the `Others` option.\n\nNote that Vite starter templates are intended to be used as a playground to test Vite with different frameworks. When building your next project, we recommend reaching out to the starters recommended by each framework. Some frameworks now redirect in `create vite` to their starters too (`create-vue` and `Nuxt 3` for Vue, and `SvelteKit` for Svelte).\n\n## Node.js Support\n\nVite no longer supports Node.js 14 / 16 / 17 / 19, which reached its EOL. Node.js 18 / 20+ is now required.\n\n## Performance\n\nOn top of Rollup 4's build performance improvements, there is a new guide to help you identify and fix common performance issues at [https://vite.dev/guide/performance](/guide/performance).\n\nVite 5 also introduces [server.warmup](/guide/performance.html#warm-up-frequently-used-files), a new feature to improve startup time. It lets you define a list of modules that should be pre-transformed as soon as the server starts. When using [`--open` or `server.open`](/config/server-options.html#server-open), Vite will also automatically warm up the entry point of your app or the provided URL to open.\n\n## Main Changes\n\n- [Vite is now powered by Rollup 4](/guide/migration#rollup-4)\n- [The CJS Node API has been deprecated](/guide/migration#deprecate-cjs-node-api)\n- [Rework `define` and `import.meta.env.*` replacement strategy](/guide/migration#rework-define-and-import-meta-env-replacement-strategy)\n- [SSR externalized modules value now matches production](/guide/migration#ssr-externalized-modules-value-now-matches-production)\n- [`worker.plugins` is now a function](/guide/migration#worker-plugins-is-now-a-function)\n- [Allow path containing `.` to fallback to index.html](/guide/migration#allow-path-containing-to-fallback-to-index-html)\n- [Align dev and preview HTML serving behavior](/guide/migration#align-dev-and-preview-html-serving-behaviour)\n- [Manifest files are now generated in `.vite` directory by default](/guide/migration#manifest-files-are-now-generated-in-vite-directory-by-default)\n- [CLI shortcuts require an additional `Enter` press](/guide/migration#cli-shortcuts-require-an-additional-enter-press)\n- [Update `experimentalDecorators` and `useDefineForClassFields` TypeScript behavior](/guide/migration#update-experimentaldecorators-and-usedefineforclassfields-typescript-behaviour)\n- [Remove `--https` flag and `https: true`](/guide/migration#remove-https-flag-and-https-true)\n- [Remove `resolvePackageEntry` and `resolvePackageData` APIs](/guide/migration#remove-resolvepackageentry-and-resolvepackagedata-apis)\n- [Removes previously deprecated APIs](/guide/migration#removed-deprecated-apis)\n- [Read more about advanced changes affecting plugin and tool authors](/guide/migration#advanced)\n\n## Migrating to Vite 5\n\nWe have worked with ecosystem partners to ensure a smooth migration to this new major. Once again, [vite-ecosystem-ci](https://www.youtube.com/watch?v=7L4I4lDzO48) has been crucial to help us make bolder changes while avoiding regressions. We're thrilled to see other ecosystems adopt similar schemes to improve the collaboration between their projects and downstream maintainers.\n\nFor most projects, the update to Vite 5 should be straight forward. But we advise reviewing the [detailed Migration Guide](/guide/migration) before upgrading.\n\nA low level breakdown with the full list of changes to Vite core can be found at the [Vite 5 Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#500-2023-11-16).\n\n## Acknowledgments\n\nVite 5 is the result of long hours of work by our community of contributors, downstream maintainers, plugins authors, and the [Vite Team](/team). A big shout out to [Bjorn Lu](https://twitter.com/bluwyoo) for leading the release process for this major.\n\nWe're also thankful to individuals and companies sponsoring Vite development. [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build) continue to invest in Vite by hiring Vite team members. A shout out to sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs), [Vite's Open Collective](https://opencollective.com/vite), and [Evan You's GitHub Sponsors](https://github.com/sponsors/yyx990803). A special mention to [Remix](https://remix.run/) for becoming a Gold sponsor and contributing back after switching to Vite.\n"
  },
  {
    "path": "docs/blog/announcing-vite6.md",
    "content": "---\ntitle: Vite 6.0 is out!\nauthor:\n  name: The Vite Team\ndate: 2024-11-26\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 6\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite6.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite6\n  - - meta\n    - property: og:description\n      content: Vite 6 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 6.0 is out!\n\n_November 26, 2024_\n\n![Vite 6 Announcement Cover Image](/og-image-announcing-vite6.webp)\n\nToday, we're taking another big step in Vite's story. The Vite [team](/team), [contributors](https://github.com/vitejs/vite/graphs/contributors), and ecosystem partners are excited to announce the release of Vite 6.\n\nIt has been an eventful year. Vite adoption keeps growing, with npm downloads per week jumping from 7.5 million to 17 million since the release of Vite 5 a year ago. [Vitest](https://vitest.dev) is not only being favored more by users but is also starting to form an ecosystem of its own. For example, [Storybook](https://storybook.js.org) has new testing capabilities powered by Vitest.\n\nNew frameworks have also joined the Vite ecosystem, including [TanStack Start](https://tanstack.com/start), [One](https://onestack.dev/), [Ember](https://emberjs.com/), and others. Web frameworks are innovating at an increasingly faster pace. You can check out the improvements folks have been doing at [Astro](https://astro.build/), [Nuxt](https://nuxt.com/), [SvelteKit](https://kit.svelte.dev/), [Solid Start](https://www.solidjs.com/blog/introducing-solidstart), [Qwik City](https://qwik.builder.io/qwikcity/overview/), [RedwoodJS](https://redwoodjs.com/), [React Router](https://reactrouter.com/), and the list goes on.\n\nVite is used by OpenAI, Google, Apple, Microsoft, NASA, Shopify, Cloudflare, GitLab, Reddit, Linear, among many others. Two months ago, we started a list of [companies using Vite](https://github.com/vitejs/companies-using-vite). We're happy to see many developers sending us a PR to add their companies to the list. It's hard to believe how much the ecosystem we built together has grown since Vite gave its first steps.\n\n![Vite weekly npm downloads](../images/vite6-npm-weekly-downloads.webp)\n\n## Speeding up the Vite ecosystem\n\nLast month, the community gathered for the third edition of [ViteConf](https://viteconf.org/24/replay), hosted once more by [StackBlitz](https://stackblitz.com). It was the biggest Vite conference, with a broad representation of builders from the ecosystem. Among other announcements, Evan You announced [VoidZero](https://staging.voidzero.dev/posts/announcing-voidzero-inc), a company dedicated to building an open-source, high-performance, and unified development toolchain for the JavaScript ecosystem. VoidZero is behind [Rolldown](https://rolldown.rs) and [Oxc](https://oxc.rs), and their team is making significant strides, getting them rapidly ready for being adopted by Vite. Watch Evan's keynote to learn more about the next steps for Vite's rust-powered future.\n\n<YouTubeVideo videoId=\"EKvvptbTx6k?si=EZ-rFJn4pDW3tUvp\" />\n\n[Stackblitz](https://stackblitz.com) unveiled [bolt.new](https://bolt.new), a Remix app that combines Claude and WebContainers and lets you prompt, edit, run, and deploy full-stack apps. Nate Weiner announced [One](https://onestack.dev/), a new Vite-powered React framework for web and native. Storybook showcased their latest Vitest-powered [testing features](https://youtu.be/8t5wxrFpCQY?si=PYZoWKf-45goQYDt). And so much more. We encourage you to watch [all 43 talks](https://www.youtube.com/playlist?list=PLqGQbXn_GDmnObDzgjUF4Krsfl6OUKxtp). The speakers made a significant effort to share with us what each project has been up to.\n\nVite also got a refreshed landing page and a clean domain. You should update your URLs to point to the new [vite.dev](https://vite.dev) domain moving forward. The new design and implementation was done by VoidZero, by the same folks that made their website. Shoutout to [Vicente Rodriguez](https://bento.me/rmoon) and [Simon Le Marchant](https://marchantweb.com/).\n\n## The next Vite major is here\n\nVite 6 is the most significant major release since Vite 2. We're eager to partner with the ecosystem to keep expanding our shared commons through new APIs and, as usual, a more polished base upon which to build.\n\nQuick links:\n\n- [Docs](/)\n- Translations: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/)\n- [Migration Guide](/guide/migration)\n- [GitHub Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#600-2024-11-26)\n\nIf you're new to Vite, we suggest reading the [Getting Started](/guide/) and [Features](/guide/features) guides first.\n\nWe want to thank the more than [1K contributors to Vite Core](https://github.com/vitejs/vite/graphs/contributors) and the maintainers and contributors of Vite plugins, integrations, tools, and translations that have helped us craft this new major. We invite you to get involved and help us improve Vite for the whole ecosystem. Learn more at our [Contributing Guide](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md).\n\nTo get started, we suggest helping [triage issues](https://github.com/vitejs/vite/issues), [review PRs](https://github.com/vitejs/vite/pulls), send failing tests PRs based on open issues, and support others in [Discussions](https://github.com/vitejs/vite/discussions) and Vite Land's [help forum](https://discord.com/channels/804011606160703521/1019670660856942652). If you'd like to talk to us, join our [Discord community](https://chat.vite.dev) and say hi on the [#contributing channel](https://discord.com/channels/804011606160703521/804439875226173480).\n\nFor the latest news about the Vite ecosystem and Vite core, follow us on [Bluesky](https://bsky.app/profile/vite.dev), [X](https://twitter.com/vite_js), or [Mastodon](https://webtoo.ls/@vite).\n\n## Getting started with Vite 6\n\nYou can use `pnpm create vite` to quickly scaffold a Vite app with your preferred framework or play online with Vite 6 using [vite.new](https://vite.new). You can also run `pnpm create vite-extra` to get access to templates from other frameworks and runtimes (Solid, Deno, SSR, and library starters). `create vite-extra` templates are also available when you run `create vite` under the `Others` option.\n\nThe Vite starter templates are intended to be used as a playground to test Vite with different frameworks. When building your next project, you should reach out to the starter recommended by each framework. `create vite` also provides a shortcut to setup proper starters by some frameworks, like `create-vue`, `Nuxt 3`, `SvelteKit`, `Remix`, `Analog`, and `Angular`.\n\n## Node.js Support\n\nVite 6 supports Node.js 18, 20, and 22+, similar to Vite 5. Node.js 21 support has been dropped. Vite drops Node.js support for older versions after their [EOL](https://endoflife.date/nodejs). The Node.js 18 EOL is at the end of April 2025, after which we may release a new major to bump the required Node.js version.\n\n## Experimental Environment API\n\nVite is getting more flexible with the new Environment API. These new APIs will allow framework authors to offer a dev experience closer to production and for the Ecosystem to share new building blocks. Nothing changes if you're building a SPA; when you use Vite with a single client environment, everything works as before. And even for custom SSR apps, Vite 6 is backward compatible. The primary target audience for Environment API is framework authors.\n\nFor end users who are curious, [Sapphi](https://github.com/sapphi-red) wrote a great [Introduction to Environment API](https://green.sapphi.red/blog/increasing-vites-potential-with-the-environment-api) guide. It is a great place to start and understand why we're trying to make Vite even more flexible.\n\nIf you are a framework author or Vite plugin maintainer and would like to leverage the new APIs, you can learn more at the [Environment API Guides](https://main.vite.dev/guide/api-environment).\n\nWe want to thank everyone involved in defining and implementing the new APIs. The story begins with Vite 2 adopting the unbundled SSR dev scheme pioneered by [Rich Harris](https://github.com/Rich-Harris) and the [SvelteKit](https://svelte.dev/docs/kit) team. Vite's SSR transform then unlocked [Anthony Fu](https://github.com/antfu/) and [Pooya Parsa](https://github.com/pi0) to create vite-node and improve [Nuxt's Dev SSR story](https://antfu.me/posts/dev-ssr-on-nuxt). Anthony went to use vite-node to power [Vitest](https://vitest.dev), and [Vladimir Sheremet](https://github.com/sheremet-va) kept improving it as part of his work maintaining Vitest. At the beginning of 2023, Vladimir started working to upstream vite-node to Vite Core, and we released it as Runtime API in Vite 5.1 a year later. Feedback from ecosystem partners (special shout-out to the Cloudflare team) pushed us to do a more ambitious rework of Vite's environments. You can learn more about the story at [Patak's ViteConf 24 talk](https://www.youtube.com/watch?v=WImor3HDyqU?si=EZ-rFJn4pDW3tUvp).\n\nEveryone on the Vite team participated in defining the new API, which was co-designed with feedback from many projects in the Ecosystem. Thanks to everyone involved! We encourage you to get involved if you're building a framework, plugin, or tool on top of Vite. The new APIs are experimental. We will work with the Ecosystem to review how the new APIs will be used and stabilize them for the next major. If you'd like to ask questions or give feedback, there is an [open GitHub discussion here](https://github.com/vitejs/vite/discussions/16358).\n\n## Main Changes\n\n- [Default value for `resolve.conditions`](/guide/migration#default-value-for-resolve-conditions)\n- [JSON stringify](/guide/migration#json-stringify)\n- [Extended support of asset references in HTML elements](/guide/migration#extended-support-of-asset-references-in-html-elements)\n- [postcss-load-config](/guide/migration#postcss-load-config)\n- [Sass now uses modern API by default](/guide/migration#sass-now-uses-modern-api-by-default)\n- [Customize CSS output file name in library mode](/guide/migration#customize-css-output-file-name-in-library-mode)\n- [And more changes that should only affect a few users](/guide/migration#advanced)\n\nThere is also a new [Breaking Changes](/changes/) page that lists all planned, considering, and past changes in Vite.\n\n## Migrating to Vite 6\n\nFor most projects, the update to Vite 6 should be straightforward, but we advise reviewing the [detailed Migration Guide](/guide/migration) before upgrading.\n\nThe complete list of changes is at the [Vite 6 Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#500-2024-11-26).\n\n## Acknowledgments\n\nVite 6 results from long work hours by our community of contributors, downstream maintainers, plugin authors, and the [Vite Team](/team). We appreciate the individuals and companies sponsoring Vite development. Vite is brought to you by [VoidZero](https://voidzero.dev), in partnership with [StackBlitz](https://stackblitz.com/), [Nuxt Labs](https://nuxtlabs.com/), and [Astro](https://astro.build). A shout-out to sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs) and [Vite's Open Collective](https://opencollective.com/vite).\n"
  },
  {
    "path": "docs/blog/announcing-vite7.md",
    "content": "---\ntitle: Vite 7.0 is out!\nauthor:\n  name: The Vite Team\ndate: 2025-06-24\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 7\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite7.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite7\n  - - meta\n    - property: og:description\n      content: Vite 7 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 7.0 is out!\n\n_June 24, 2025_\n\n![Vite 7 Announcement Cover Image](/og-image-announcing-vite7.webp)\n\nWe're happy to share the release of Vite 7! It has been 5 years since Evan You sent the first commit to the Vite repo, and nobody could have predicted how much the frontend ecosystem would change since then. Most modern frontend frameworks and tools are now working together, building on top of Vite's shared infrastructure. And they can innovate at a faster pace by sharing at a higher level. Vite is now being downloaded 31 million times a week, with a 14 million increase in the last seven months since the previous major release.\n\nThis year, we're making several big steps. To start with, [ViteConf](https://viteconf.org) is going to be in person! The Vite Ecosystem will gather in Amsterdam on October 9-10! Organized by [JSWorld](https://jsworldconference.com/) in partnership with [Bolt](https://bolt.new), [VoidZero](https://voidzero.dev), and the Vite Core Team! We had three incredible [ViteConf online editions](https://www.youtube.com/@viteconf/playlists), and we can't wait to meet in real life. Check out the speakers and get your ticket at the [ViteConf site](https://viteconf.org)!\n\nAnd [VoidZero](https://voidzero.dev/posts/announcing-voidzero-inc) continues to make significant strides in its mission to build an open source unified development toolchain for the JavaScript ecosystem. Over the last year, the VoidZero team has been working on [Rolldown](https://rolldown.rs/), a Rust-based next-generation bundler, as part of a broader effort to modernize Vite's core. You can try out the Rolldown-powered Vite today by using the `rolldown-vite` package instead of the default `vite` package. It is a drop-in replacement, as Rolldown will become the default bundler for Vite in the future. Switching should reduce your build time, especially for larger projects. Read more at the [Rolldown-vite announcement blog post](https://voidzero.dev/posts/announcing-rolldown-vite) and our [migration guide](https://vite.dev/rolldown).\n\nThrough a partnership between VoidZero and [NuxtLabs](https://nuxtlabs.com/), Anthony Fu is working on creating Vite DevTools. They will offer deeper and more insightful debugging and analysis for all Vite-based projects and frameworks. You can read more on the [VoidZero and NuxtLabs join forces on Vite Devtools blog post](https://voidzero.dev/posts/voidzero-nuxtlabs-vite-devtools).\n\nQuick links:\n\n- [Docs](/)\n- New Translation: [فارسی](https://fa.vite.dev/)\n- Other Translations: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/)\n- [Migration Guide](/guide/migration)\n- [GitHub Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)\n\nPlay online with Vite 7 using [vite.new](https://vite.new) or scaffold a Vite app locally with your preferred framework running `pnpm create vite`. Check out the [Getting Started Guide](/guide/) for more information.\n\nWe invite you to help us improve Vite (joining the more than [1.1K contributors to Vite Core](https://github.com/vitejs/vite/graphs/contributors)), our dependencies, or plugins and projects in the ecosystem. Learn more at our [Contributing Guide](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md). A good way to get started is by [triaging issues](https://github.com/vitejs/vite/issues), [reviewing PRs](https://github.com/vitejs/vite/pulls), sending tests PRs based on open issues, and supporting others in [Discussions](https://github.com/vitejs/vite/discussions) or Vite Land's [help forum](https://discord.com/channels/804011606160703521/1019670660856942652). If you have questions, join our [Discord community](https://chat.vite.dev) and talk to us in the [#contributing channel](https://discord.com/channels/804011606160703521/804439875226173480).\n\nStay updated and connect with others building on top of Vite by following us on [Bluesky](https://bsky.app/profile/vite.dev), [X](https://twitter.com/vite_js), or [Mastodon](https://webtoo.ls/@vite).\n\n## Node.js Support\n\nVite now requires Node.js 20.19+, 22.12+. We have dropped Node.js 18, now that it has reached its [EOL](https://endoflife.date/nodejs) at the end of April 2025.\n\nWe require these new ranges so Node.js supports `require(esm)` without a flag. This allows us to distribute Vite 7.0 as ESM only without preventing the Vite JavaScript API from being required by CJS modules. Check out Anthony Fu's [Move on to ESM-only](https://antfu.me/posts/move-on-to-esm-only) for a detailed review of the current state of ESM in the ecosystem.\n\n## Default Browser Target Changed to Baseline Widely Available\n\n[Baseline](https://web-platform-dx.github.io/web-features/) gives us clear information about which web platform features work across their core browser set today. Baseline Widely Available indicates the feature is well-established and works across many devices and browser versions, being available across browsers for at least 30 months.\n\nIn Vite 7, the default browser target is changing from `'modules'` to a new default: `'baseline-widely-available'`. The set of browsers will be updated on each major to match the list of minimum browser versions compatible with Baseline Widely available features. The default browser value of `build.target` is changing in Vite 7.0:\n\n- Chrome 87 → 107\n- Edge 88 → 107\n- Firefox 78 → 104\n- Safari 14.0 → 16.0\n\nThis change adds predictability to the default browser target for future releases.\n\n## Vitest\n\nFor Vitest users, Vite 7.0 is supported from Vitest 3.2. You can read more about how the Vitest team keeps improving Vite testing story in the [Vitest 3.2 release blog post](https://vitest.dev/blog/vitest-3-2.html).\n\n## Environment API\n\nVite 6 was the most significant major release since Vite 2, adding new capabilities with the [new experimental Environment API](https://vite.dev/blog/announcing-vite6.html#experimental-environment-api). We are keeping the new APIs as experimental while the ecosystem reviews how the new APIs fit on their projects and provide feedback. If you're building on top of Vite, we encourage you to test the new APIs and reach out to us in the [open Feedback discussion here](https://github.com/vitejs/vite/discussions/16358).\n\nIn Vite 7, we added a new `buildApp` hook to let plugins coordinate the building of environments. Read more in the [Environment API for Frameworks guide](/guide/api-environment-frameworks.html#environments-during-build).\n\nWe want to thank the teams that have been testing the new APIs and helping us stabilize the new features. The Cloudflare team, for example, announced the 1.0 release of their Cloudflare Vite plugin, as well as official support for React Router v7. Their plugin shows the potential of Environment API for runtime providers. Learn more about their approach and future steps at [\"Just use Vite”… with the Workers runtime](https://blog.cloudflare.com/introducing-the-cloudflare-vite-plugin/).\n\n## Migrating to Vite 7\n\nVite 7 should be a smooth update from Vite 6. We're removing already deprecated features, like Sass legacy API support and the `splitVendorChunkPlugin` that shouldn't affect your projects. We still suggest you review the [detailed Migration Guide](/guide/migration) before upgrading.\n\nThe complete list of changes is at the [Vite 7 Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md).\n\n## Acknowledgments\n\nVite 7 was crafted by the [Vite Team](/team) with the help of the wide community of contributors, downstream maintainers, plugin authors. A special shout-out to [sapphi-red](https://github.com/sapphi-red) for his remarkable work on `rolldown-vite` and this release. Vite is brought to you by [VoidZero](https://voidzero.dev), in partnership with [Bolt](https://bolt.new/) and [Nuxt Labs](https://nuxtlabs.com/). We also want to thank our sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs) and [Vite's Open Collective](https://opencollective.com/vite).\n"
  },
  {
    "path": "docs/blog/announcing-vite8-beta.md",
    "content": "---\ntitle: 'Vite 8 Beta: The Rolldown-powered Vite'\nauthor:\n  name: The Vite Team\ndate: 2025-12-03\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 8 Beta\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite8-beta.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite8-beta\n  - - meta\n    - property: og:description\n      content: Vite 8 Beta Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 8 Beta: The Rolldown-powered Vite\n\n_December 3, 2025_\n\n![Vite 8 Beta Announcement Cover Image](/og-image-announcing-vite8-beta.webp)\n\nTL;DR: The first beta of Vite 8, powered by [Rolldown](https://rolldown.rs/), is now available. Vite 8 ships significantly faster production builds and unlocks future improvement possibilities. You can try the new release by upgrading `vite` to version `8.0.0-beta.0` and reading the [migration guide](/guide/migration).\n\n---\n\nWe're excited to release the first beta of Vite 8. This release unifies the underlying toolchain and brings better consistent behaviors, alongside significant build performance improvements. Vite now uses [Rolldown](https://rolldown.rs/) as its bundler, replacing the previous combination of esbuild and Rollup.\n\n## A new bundler for the web\n\nVite previously relied on two bundlers to meet differing requirements for development and production builds:\n\n1. esbuild for fast compilation during development\n2. Rollup for bundling, chunking, and optimizing production builds\n\nThis approach lets Vite focus on developer experience and orchestration instead of reinventing parsing and bundling. However, maintaining two separate bundling pipelines introduced inconsistencies: separate transformation pipelines, different plugin systems and a growing amount of glue code to keep bundling behavior aligned between development and production.\n\nTo solve this, [VoidZero team](https://voidzero.dev) has built **Rolldown**, the next-generation bundler with the goal to be used in Vite. It is designed for:\n\n- **Performance**: Rolldown is written in Rust and operates at native speed. It matches esbuild’s performance level and is [**10–30× faster than Rollup**](https://github.com/rolldown/benchmarks).\n- **Compatibility**: Rolldown supports the same plugin API as Rollup and Vite. Most Vite plugins work out of the box with Vite 8.\n- **More Features**: Rolldown unlocks more advanced features for Vite, including full bundle mode, more flexible chunk split control, module-level persistent cache, Module Federation, and more.\n\n## Unifying the toolchain\n\nThe impact of Vite’s bundler swap goes beyond performance. Bundlers leverage parsers, resolvers, transformers, and minifiers. Rolldown uses Oxc, another project led by VoidZero, for these purposes.\n\n**That makes Vite the entry point to an end-to-end toolchain maintained by the same team: The build tool (Vite), the bundler (Rolldown) and the compiler (Oxc).**\n\nThis alignment ensures behavior consistency across the stack, and allows us to rapidly adopt and align with new language specifications as JavaScript continues to evolve. It also unlocks a wide range of improvements that previously couldn’t be done by Vite alone. For example, we can leverage Oxc’s semantic analysis to perform better tree-shaking in Rolldown.\n\n## How Vite migrated to Rolldown\n\nThe migration to a Rolldown-powered Vite is a foundational change. Therefore, our team took deliberate steps to implement it without sacrificing stability or ecosystem compatibility.\n\nFirst, a separate `rolldown-vite` package was [released as a technical preview](https://voidzero.dev/posts/announcing-rolldown-vite). This allowed us to work with early adopters without affecting the stable version of Vite. Early adopters benefited from Rolldown’s performance gains while providing valuable feedback. Highlights:\n\n- Linear's production build times were reduced from 46s to 6s\n- Ramp reduced their build time by 57%\n- Mercedes-Benz.io cut their build time down by up to 38%\n- Beehiiv reduced their build time by 64%\n\nNext, we set up a test suite for validating key Vite plugins against `rolldown-vite`. This CI job helped us catch regressions and compatibility issues early, especially for frameworks and meta-frameworks such as SvelteKit, react-router and Storybook.\n\nLastly, we built a compatibility layer to help migrate developers from Rollup and esbuild options to the corresponding Rolldown options.\n\nAs a result, there is a smooth migration path to Vite 8 for everyone.\n\n## Migrating to Vite 8 Beta\n\nSince Vite 8 touches the core build behavior, we focused on keeping the configuration API and plugin hooks unchanged. We created a [migration guide](/guide/migration) to help you upgrade.\n\nThere are two available upgrade paths:\n\n1. **Direct Upgrade:** Update `vite` in `package.json` and run the usual dev and build commands.\n2. **Gradual Migration:** Migrate from Vite 7 to the `rolldown-vite` package, and then to Vite 8. This allows you to identify incompatibilities or issues isolated to Rolldown without other changes to Vite. (Recommended for larger or complex projects)\n\n> [!IMPORTANT]\n> If you are relying on specific Rollup or esbuild options, you might need to make some adjustments to your Vite config. Please refer to the [migration guide](/guide/migration) for detailed instructions and examples.\n> As with all non-stable, major releases, thorough testing is recommended after upgrading to ensure everything works as expected. Please make sure to report any [issues](https://github.com/vitejs/rolldown-vite/issues).\n\nIf you use a framework or tool that uses Vite as dependency, for example Astro, Nuxt, or Vitest, you have to override the `vite` dependency in your `package.json`, which works slightly different depending on your package manager:\n\n:::code-group\n\n```json [npm]\n{\n  \"overrides\": {\n    \"vite\": \"8.0.0-beta.0\"\n  }\n}\n```\n\n```json [Yarn]\n{\n  \"resolutions\": {\n    \"vite\": \"8.0.0-beta.0\"\n  }\n}\n```\n\n```json [pnpm]\n{\n  \"pnpm\": {\n    \"overrides\": {\n      \"vite\": \"8.0.0-beta.0\"\n    }\n  }\n}\n```\n\n```json [Bun]\n{\n  \"overrides\": {\n    \"vite\": \"8.0.0-beta.0\"\n  }\n}\n```\n\n:::\n\nAfter adding these overrides, reinstall your dependencies and start your development server or build your project as usual.\n\n## Additional Features in Vite 8\n\nIn addition to shipping with Rolldown, Vite 8 comes with:\n\n- **Built-in tsconfig `paths` support:** Developers can enable it by setting [`resolve.tsconfigPaths`](/config/shared-options.md#resolve-tsconfigpaths) to `true`. This feature has a small performance cost and is not enabled by default.\n- **`emitDecoratorMetadata` support:** Vite 8 now has built-in automatic support for TypeScript's [`emitDecoratorMetadata` option](https://www.typescriptlang.org/tsconfig/#emitDecoratorMetadata). See the [Features](/guide/features.md#emitdecoratormetadata) page for more details.\n\n## Looking Ahead\n\nSpeed has always been a defining feature for Vite. The integration with Rolldown and, by extension, Oxc means JavaScript developers benefit from Rust’s speed. Upgrading to Vite 8 should result in performance gains simply from using Rust.\n\nWe are also excited to ship Vite’s Full Bundle Mode soon, which drastically improves Vite’s dev server speed for large projects. Preliminary results show 3× faster dev server startup, 40% faster full reloads, and 10× fewer network requests.\n\nAnother defining Vite feature is the plugin ecosystem. We want JavaScript developers to continue extending and customizing Vite in JavaScript, the language they’re familiar with, while benefiting from Rust’s performance gains. Our team is collaborating with VoidZero team to accelerate JavaScript plugin usage in these Rust-based systems.\n\nUpcoming optimizations that are currently experimental:\n\n- [**Raw AST transfer**](https://github.com/oxc-project/oxc/issues/2409). Allow JavaScript plugins to access the Rust-produced AST with minimal overhead.\n- [**Native MagicString transforms**](https://rolldown.rs/in-depth/native-magic-string#native-magicstring). Simple custom transforms with logic in JavaScript but computation in Rust.\n\n## **Connect with us**\n\nIf you've tried Vite 8 beta, then we'd love to hear your feedback! Please report any issues or share your experience:\n\n- **Discord**: Join our [community server](https://chat.vite.dev/) for real-time discussions\n- **GitHub**: Share feedback on [GitHub discussions](https://github.com/vitejs/vite/discussions)\n- **Issues**: Report issues on the [rolldown-vite repository](https://github.com/vitejs/rolldown-vite/issues) for bugs and regressions\n- **Wins**: Share your improved build times in the [rolldown-vite-perf-wins repository](https://github.com/vitejs/rolldown-vite-perf-wins)\n\nWe appreciate all reports and reproduction cases. They help guide us towards the release of a stable 8.0.0.\n"
  },
  {
    "path": "docs/blog/announcing-vite8.md",
    "content": "---\ntitle: Vite 8.0 is out!\nauthor:\n  name: The Vite Team\ndate: 2026-03-12\nsidebar: false\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: Announcing Vite 8\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-announcing-vite8.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/blog/announcing-vite8\n  - - meta\n    - property: og:description\n      content: Vite 8 Release Announcement\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n# Vite 8.0 is out!\n\n_March 12, 2026_\n\n![Vite 8 Announcement Cover Image](/og-image-announcing-vite8.webp)\n\nWe're thrilled to announce the stable release of Vite 8! When Vite first launched, we made a pragmatic bet on two bundlers: esbuild for speed during development, and Rollup for optimized production builds. That bet served us well for years. We're very grateful to the Rollup and esbuild maintainers. Vite wouldn't have succeeded without them. Today, it resolves into one: Vite 8 ships with [Rolldown](https://rolldown.rs/) as its single, unified, Rust-based bundler, delivering up to 10-30x faster builds while maintaining full plugin compatibility. This is the most significant architectural change since Vite 2.\n\nVite is now being downloaded 65 million times a week, and the ecosystem continues to grow with every release. To help developers navigate the ever-expanding plugin landscape, we also launched [registry.vite.dev](https://registry.vite.dev), a searchable directory of plugins for Vite, Rolldown, and Rollup that collects plugin data from npm daily.\n\nQuick links:\n\n- [Docs](/)\n- Translations: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/), [فارسی](https://fa.vite.dev/)\n- [Migration Guide](/guide/migration)\n- [GitHub Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)\n\nPlay online with Vite 8 using [vite.new](https://vite.new) or scaffold a Vite app locally with your preferred framework running `pnpm create vite`. Check out the [Getting Started Guide](/guide/) for more information.\n\nWe invite you to help us improve Vite (joining the more than [1.2K contributors to Vite Core](https://github.com/vitejs/vite/graphs/contributors)), our dependencies, or plugins and projects in the ecosystem. Learn more at our [Contributing Guide](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md). A good way to get started is by [triaging issues](https://github.com/vitejs/vite/issues), [reviewing PRs](https://github.com/vitejs/vite/pulls), sending tests PRs based on open issues, and supporting others in [Discussions](https://github.com/vitejs/vite/discussions) or Vite Land's [help forum](https://discord.com/channels/804011606160703521/1019670660856942652). If you have questions, join our [Discord community](https://chat.vite.dev) and talk to us in the [#contributing channel](https://discord.com/channels/804011606160703521/804439875226173480).\n\nStay updated and connect with others building on top of Vite by following us on [Bluesky](https://bsky.app/profile/vite.dev), [X](https://twitter.com/vite_js), or [Mastodon](https://webtoo.ls/@vite).\n\n## The Rolldown-Powered Vite\n\n### The problem\n\nSince its earliest versions, Vite relied on two separate bundlers to serve different needs. [esbuild](https://esbuild.github.io/) handled fast compilation during development (dependency pre-bundling and TypeScript/JSX transforms) that made the dev experience feel instant. [Rollup](https://rollupjs.org/) handled production bundling, chunking, and optimization, with its rich plugin API powering the entire Vite plugin ecosystem.\n\nThis dual-bundler approach served Vite well for years. It allowed us to focus on developer experience and orchestration rather than reinventing parsing and bundling from scratch. But it came with trade-offs. Two separate transformation pipelines meant two separate plugin systems, and an increasing amount of glue code needed to keep the two pipelines in sync. Edge cases around inconsistent module handling accumulated over time, and every alignment fix in one pipeline risked introducing differences in the other.\n\n### The solution\n\n[Rolldown](https://rolldown.rs/) is a Rust-based bundler built by the [VoidZero](https://voidzero.dev) team to address these challenges head-on. It was designed with three goals:\n\n- **Performance:** Written in Rust, Rolldown operates at native speed. In benchmarks, it is [10-30x faster than Rollup](https://github.com/rolldown/benchmarks) matching esbuild's performance level.\n- **Compatibility:** Rolldown supports the same plugin API as Rollup and Vite. Most existing Vite plugins work out of the box with Vite 8.\n- **Advanced features:** A single unified bundler unlocks capabilities that were difficult or impossible with the dual-bundler setup, including full bundle mode, more flexible chunk splitting, module-level persistent caching, and Module Federation support.\n\n### The journey to stable\n\nThe migration to Rolldown was deliberate and community-driven. First, a separate [`rolldown-vite`](https://voidzero.dev/posts/announcing-rolldown-vite) package was released as a technical preview, allowing early adopters to test Rolldown's integration without affecting the stable version of Vite. The feedback from those early adopters was invaluable. They pushed the integration through real-world codebases of every shape and size, surfacing edge cases and compatibility issues we could address before a wider release. We also set up a dedicated CI suite validating key Vite plugins and frameworks against the new bundler, catching regressions early and building confidence in the migration path.\n\nIn December 2025, we shipped the [Vite 8 beta](/blog/announcing-vite8-beta) with Rolldown fully integrated. During the beta period, Rolldown itself progressed from beta to a release candidate, with continuous improvements driven by the testing and feedback of the Vite community.\n\n### Real-world performance\n\nDuring the preview and beta phases of `rolldown-vite`, several companies reported measurable reductions in production build times:\n\n- **Linear:** Production build times dropped from 46s to 6s\n- **Ramp:** 57% build time reduction\n- **Mercedes-Benz.io:** Up to 38% build time reduction\n- **Beehiiv:** 64% build time reduction\n\nFor large projects, the impact can be especially noticeable, and we expect further improvements as Rolldown continues to evolve.\n\n### A unified toolchain\n\nWith Vite 8, Vite becomes the entry point to an end-to-end toolchain with closely collaborating teams: the build tool (Vite), the bundler (Rolldown), and the compiler ([Oxc](https://oxc.rs/)). This alignment ensures consistent behavior across the entire stack, from parsing and resolving to transforming and minifying. It also means we can rapidly adopt new language specifications as JavaScript evolves. And by integrating deeply across layers, we can pursue optimizations that were previously out of reach, such as leveraging Oxc's semantic analysis for better tree-shaking in Rolldown.\n\n### Thank you to the community\n\nNone of this would have been possible without the broader community. We want to extend our deep thanks to the framework teams ([SvelteKit](https://svelte.dev/docs/kit/introduction), [React Router](https://reactrouter.com/), [Storybook](https://storybook.js.org/), [Astro](https://astro.build/), [Nuxt](https://nuxt.com/), and many others) who tested `rolldown-vite` early, filed detailed bug reports, and worked with us to resolve compatibility issues. We are equally grateful to every developer who tried the beta, shared their build time improvements, and reported the rough edges that helped us polish this release. Your willingness to test the migration on real projects helped make the transition to Rolldown smoother and more reliable.\n\n## Node.js Support\n\nVite 8 requires Node.js 20.19+, 22.12+, the same requirements as Vite 7. These ranges ensure Node.js supports `require(esm)` without a flag, allowing Vite to be distributed as ESM only.\n\n## Additional Features\n\nBeyond the Rolldown integration, Vite 8 includes several notable features:\n\n- **Integrated Devtools:** Vite 8 ships [`devtools`](/config/shared-options#devtools) option to enable [Vite Devtools](https://devtools.vite.dev/), a developer tooling for debugging and analysis. Vite Devtools provide deeper insights into your Vite-powered projects directly from the dev server.\n\n- **Built-in tsconfig `paths` support:** Developers can enable TypeScript path alias resolution by setting [`resolve.tsconfigPaths`](/config/shared-options.md#resolve-tsconfigpaths) to `true`. This has a small performance cost and is not enabled by default.\n\n- **`emitDecoratorMetadata` support:** Vite 8 now has built-in automatic support for TypeScript's `emitDecoratorMetadata` option, removing the need for external plugins. See the [Features](/guide/features.md#emitdecoratormetadata) page for details.\n\n- **Wasm SSR support:** [`.wasm?init` imports](/guide/features#webassembly) now work in SSR environments, expanding Vite's WebAssembly feature to server-side rendering.\n\n- **Browser console forwarding:** Vite 8 can forward browser console logs and errors to the dev server terminal. This is especially useful when working with coding agents, as runtime client errors become visible in the CLI output. Enable it with [`server.forwardConsole`](/config/server-options.md#server-forwardconsole), which activates automatically when a coding agent is detected.\n\n## `@vitejs/plugin-react` v6\n\nAlongside Vite 8, we are releasing `@vitejs/plugin-react` v6. The plugin uses Oxc for React Refresh transform. Babel is no longer a dependency and the installation size is smaller.\n\nFor projects that need the [React Compiler](https://react.dev/learn/react-compiler), v6 provides a `reactCompilerPreset` helper that works with `@rolldown/plugin-babel`, giving you an explicit opt-in path without burdening the default setup.\n\nSee [the Release Notes](https://github.com/vitejs/vite-plugin-react/releases/tag/plugin-react%406.0.0) for more details.\n\nNote that v5 still works with Vite 8, so you can upgrade the plugin after upgrading Vite.\n\n## Looking Ahead\n\nThe Rolldown integration opens the door to improvements and optimizations. Here is what we are working on next:\n\n- **Full Bundle Mode** (experimental): This mode bundles modules during development, similar to production builds. Preliminary results show 3x faster dev server startup, 40% faster full reloads, and 10x fewer network requests. This is especially impactful for large projects where the unbundled dev approach hits scaling limits.\n\n- [**Raw AST transfer**](https://github.com/oxc-project/oxc/issues/2409): Allows JavaScript plugins to access the Rust-produced AST with minimal serialization overhead, bridging the performance gap between Rust internals and JS plugin code.\n\n- [**Native MagicString transforms**](https://rolldown.rs/in-depth/native-magic-string#native-magicstring): Enables custom transforms where the logic lives in JavaScript but the string manipulation computation runs in Rust.\n\n- **Stabilizing the Environment API**: We are working to make the Environment API stable. The ecosystem has started regular meetings to better collaborate together.\n\n## Install Size\n\nWe want to be transparent about changes to Vite's install size. Vite 8 is approximately 15 MB larger than Vite 7 on its own. This comes from two main sources:\n\n- **~10 MB from lightningcss**: Previously an optional peer dependency, lightningcss is now a normal dependency to provide better CSS minification out of the box.\n- **~5 MB from Rolldown**: The Rolldown binary is larger than esbuild + Rollup mainly due to performance optimizations that favor speed over binary size.\n\nWe will continue monitoring and working to reduce install size as Rolldown matures.\n\n## Migrating to Vite 8\n\nFor most projects, upgrading to Vite 8 should be a smooth process. We built a compatibility layer that auto-converts existing `esbuild` and `rollupOptions` configuration to their Rolldown and Oxc equivalents, so many projects will work without any config changes.\n\nFor larger or more complex projects, we recommend the gradual migration path: first switch from `vite` to the `rolldown-vite` package on Vite 7 to isolate any Rolldown-specific issues, then upgrade to Vite 8. This two-step approach makes it easy to identify whether any issues come from the bundler change or from other Vite 8 changes.\n\nPlease review the detailed [Migration Guide](/guide/migration) before upgrading. The complete list of changes is in the [Vite 8 Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md).\n\n## Thank You, Rollup and esbuild\n\nAs Vite moves to Rolldown, we want to take a moment to express our deep gratitude to the two projects that made Vite possible.\n\nRollup has been Vite's production bundler since the very beginning. Its elegant plugin API design proved so well-conceived that Rolldown adopted it as its own, and Vite's entire plugin ecosystem exists because of the foundation Rollup laid. The quality and thoughtfulness of Rollup's architecture shaped how Vite thinks about extensibility. Thank you, [Rich Harris](https://github.com/Rich-Harris) for creating Rollup, and [Lukas Taegert-Atkinson](https://github.com/lukastaegert) and the Rollup team for maintaining and evolving it into something that has had such a lasting impact on the web tooling ecosystem.\n\nesbuild powered Vite's remarkably fast development experience from its early days: dependency pre-bundling, TypeScript and JSX transforms that completed in milliseconds rather than hundreds. esbuild proved that build tools could be orders of magnitude faster, and its speed set the bar that inspired an entire generation of Rust and Go-based tooling. Thank you, [Evan Wallace](https://github.com/evanw), for showing all of us what was possible.\n\nWithout these two projects, Vite would not exist as it does today. Even as we move forward with Rolldown, the influence of Rollup and esbuild is deeply embedded in Vite's DNA, and we are grateful for everything they have given to the ecosystem. You can learn more about all the projects and people Vite depends on at our [Acknowledgements](/acknowledgements) page.\n\n## Acknowledgments\n\nVite 8 was led by [sapphi-red](https://github.com/sapphi-red) and the [Vite Team](/team) with the help of the wide community of contributors, downstream maintainers, and plugin authors. We want to thank the [Rolldown team](https://rolldown.rs/team) for their close collaboration in making the Rolldown-powered Vite 8 possible. We are also especially grateful to everyone who participated in the `rolldown-vite` preview and the Vite 8 beta period. Your testing, bug reports, and feedback made the Rolldown migration possible and shaped this release into something we are proud of.\n\nVite is brought to you by [VoidZero](https://voidzero.dev), in partnership with [Bolt](https://bolt.new/) and [NuxtLabs](https://nuxtlabs.com/). We also want to thank our sponsors on [Vite's GitHub Sponsors](https://github.com/sponsors/vitejs) and [Vite's Open Collective](https://opencollective.com/vite).\n"
  },
  {
    "path": "docs/blog.md",
    "content": "---\nsidebar: false\neditLink: false\noutline: false\n---\n\n<script setup>\nimport BlogIndex from './.vitepress/theme/components/BlogIndex.vue'\n</script>\n\n# Latest From the Vite Blog\n\n<BlogIndex/>\n"
  },
  {
    "path": "docs/changes/hotupdate-hook.md",
    "content": "# HMR `hotUpdate` Plugin Hook\n\n::: tip Feedback\nGive us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)\n:::\n\nWe're planning to deprecate the `handleHotUpdate` plugin hook in favor of [`hotUpdate` hook](/guide/api-environment#the-hotupdate-hook) to be [Environment API](/guide/api-environment.md) aware, and handle additional watch events with `create` and `delete`.\n\nAffected scope: `Vite Plugin Authors`\n\n::: warning Future Deprecation\n`hotUpdate` was first introduced in `v6.0`. The deprecation of `handleHotUpdate` is planned for a future major. We don't recommend moving away from `handleHotUpdate` yet. If you want to experiment and give us feedback, you can use the `future.removePluginHookHandleHotUpdate` to `\"warn\"` in your vite config.\n:::\n\n## Motivation\n\nThe [`handleHotUpdate` hook](/guide/api-plugin.md#handlehotupdate) allows to perform custom HMR update handling. A list of modules to be updated is passed in the `HmrContext`.\n\n```ts\ninterface HmrContext {\n  file: string\n  timestamp: number\n  modules: Array<ModuleNode>\n  read: () => string | Promise<string>\n  server: ViteDevServer\n}\n```\n\nThis hook is called once for all environments, and the passed modules have mixed information from the Client and SSR environments only. Once frameworks move to custom environments, a new hook that is called for each of them is needed.\n\nThe new `hotUpdate` hook works in the same way as `handleHotUpdate` but it is called for each environment and receives a new `HotUpdateOptions` instance:\n\n```ts\ninterface HotUpdateOptions {\n  type: 'create' | 'update' | 'delete'\n  file: string\n  timestamp: number\n  modules: Array<EnvironmentModuleNode>\n  read: () => string | Promise<string>\n  server: ViteDevServer\n}\n```\n\nThe current dev environment can be accessed like in other Plugin hooks with `this.environment`. The `modules` list will now be module nodes from the current environment only. Each environment update can define different update strategies.\n\nThis hook is also now called for additional watch events and not only for `'update'`. Use `type` to differentiate between them.\n\n## Migration Guide\n\nFilter and narrow down the affected module list so that the HMR is more accurate.\n\n```js\nhandleHotUpdate({ modules }) {\n  return modules.filter(condition)\n}\n\n// Migrate to:\n\nhotUpdate({ modules }) {\n  return modules.filter(condition)\n}\n```\n\nReturn an empty array and perform a full reload:\n\n```js\nhandleHotUpdate({ server, modules, timestamp }) {\n  // Invalidate modules manually\n  const invalidatedModules = new Set()\n  for (const mod of modules) {\n    server.moduleGraph.invalidateModule(\n      mod,\n      invalidatedModules,\n      timestamp,\n      true\n    )\n  }\n  server.ws.send({ type: 'full-reload' })\n  return []\n}\n\n// Migrate to:\n\nhotUpdate({ modules, timestamp }) {\n  // Invalidate modules manually\n  const invalidatedModules = new Set()\n  for (const mod of modules) {\n    this.environment.moduleGraph.invalidateModule(\n      mod,\n      invalidatedModules,\n      timestamp,\n      true\n    )\n  }\n  this.environment.hot.send({ type: 'full-reload' })\n  return []\n}\n```\n\nReturn an empty array and perform complete custom HMR handling by sending custom events to the client:\n\n```js\nhandleHotUpdate({ server }) {\n  server.ws.send({\n    type: 'custom',\n    event: 'special-update',\n    data: {}\n  })\n  return []\n}\n\n// Migrate to...\n\nhotUpdate() {\n  this.environment.hot.send({\n    type: 'custom',\n    event: 'special-update',\n    data: {}\n  })\n  return []\n}\n```\n"
  },
  {
    "path": "docs/changes/index.md",
    "content": "# Breaking Changes\n\nList of breaking changes in Vite including API deprecations, removals, and changes. Most of the changes below can be opt-in using the [`future` option](/config/shared-options.html#future) in your Vite config.\n\n## Planned\n\nThese changes are planned for the next major version of Vite. The deprecation or usage warnings will guide you where possible, and we're reaching out to framework, plugin authors, and users to apply these changes.\n\n- [`this.environment` in Hooks](/changes/this-environment-in-hooks)\n- [HMR `hotUpdate` Plugin Hook](/changes/hotupdate-hook)\n- [SSR Using `ModuleRunner` API](/changes/ssr-using-modulerunner)\n\n## Considering\n\nThese changes are being considered and are often experimental APIs that intend to improve upon current usage patterns. As not all changes are listed here, please check out the [Experimental Label in Vite GitHub Discussions](https://github.com/vitejs/vite/discussions/categories/feedback?discussions_q=label%3Aexperimental+category%3AFeedback) for the full list.\n\nWe don't recommend switching to these APIs yet. They are included in Vite to help us gather feedback. Please check these proposals and let us know how they work in your use case in each's linked GitHub Discussions.\n\n- [Move to Per-environment APIs](/changes/per-environment-apis)\n- [Shared Plugins During Build](/changes/shared-plugins-during-build)\n\n## Past\n\nThe changes below have been done or reverted. They are no longer relevant in the current major version.\n\n- _No past changes yet_\n"
  },
  {
    "path": "docs/changes/per-environment-apis.md",
    "content": "# Move to Per-environment APIs\n\n::: tip Feedback\nGive us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)\n:::\n\nMultiple APIs from `ViteDevServer` related to module graph and modules transforms have been moved to the `DevEnvironment` instances.\n\nAffected scope: `Vite Plugin Authors`\n\n::: warning Future Deprecation\nThe `Environment` instance was first introduced at `v6.0`. The deprecation of `server.moduleGraph` and other methods that are now in environments is planned for a future major. We don't recommend moving away from server methods yet. To identify your usage, set these in your vite config.\n\n```ts\nfuture: {\n  removeServerModuleGraph: 'warn',\n  removeServerReloadModule: 'warn',\n  removeServerPluginContainer: 'warn',\n  removeServerHot: 'warn',\n  removeServerTransformRequest: 'warn',\n  removeServerWarmupRequest: 'warn',\n}\n```\n\n:::\n\n## Motivation\n\nIn Vite v5 and before, a single Vite dev server always had two environments (`client` and `ssr`). The `server.moduleGraph` had mixed modules from both of these environments. Nodes were connected through `clientImportedModules` and `ssrImportedModules` lists (but a single `importers` list was maintained for each). A transformed module was represented by an `id` and a `ssr` boolean. This boolean needed to be passed to APIs, for example `server.moduleGraph.getModuleByUrl(url, ssr)` and `server.transformRequest(url, { ssr })`.\n\nIn Vite v6, it is now possible to create any number of custom environments (`client`, `ssr`, `edge`, etc). A single `ssr` boolean isn't enough anymore. Instead of changing the APIs to be of the form `server.transformRequest(url, { environment })`, we moved these methods to the environment instance allowing them to be called without a Vite dev server.\n\n## Migration Guide\n\n- `server.moduleGraph` -> [`environment.moduleGraph`](/guide/api-environment-instances#separate-module-graphs)\n- `server.reloadModule(module)` -> `environment.reloadModule(module)`\n- `server.pluginContainer` -> `environment.pluginContainer`\n- `server.transformRequest(url, ssr)` -> `environment.transformRequest(url)`\n- `server.warmupRequest(url, ssr)` -> `environment.warmupRequest(url)`\n- `server.hot` -> `server.client.environment.hot`\n"
  },
  {
    "path": "docs/changes/shared-plugins-during-build.md",
    "content": "# Shared Plugins during Build\n\n::: tip Feedback\nGive us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)\n:::\n\nSee [Shared plugins during build](/guide/api-environment-plugins.md#shared-plugins-during-build).\n\nAffected scope: `Vite Plugin Authors`\n\n::: warning Future Default Change\n`builder.sharedConfigBuild` was first introduced in `v6.0`. You can set it true to check how your plugins work with a shared config. We're looking for feedback about changing the default in a future major once the plugin ecosystem is ready.\n:::\n\n## Motivation\n\nAlign dev and build plugin pipelines.\n\n## Migration Guide\n\nTo be able to share plugins across environments, plugin state must be keyed by the current environment. A plugin of the following form will count the number of transformed modules across all environments.\n\n```js\nfunction CountTransformedModulesPlugin() {\n  let transformedModules\n  return {\n    name: 'count-transformed-modules',\n    buildStart() {\n      transformedModules = 0\n    },\n    transform(id) {\n      transformedModules++\n    },\n    buildEnd() {\n      console.log(transformedModules)\n    },\n  }\n}\n```\n\nIf we instead want to count the number of transformed modules for each environment, we need to keep a map:\n\n```js\nfunction PerEnvironmentCountTransformedModulesPlugin() {\n  const state = new Map<Environment, { count: number }>()\n  return {\n    name: 'count-transformed-modules',\n    perEnvironmentStartEndDuringDev: true,\n    buildStart() {\n      state.set(this.environment, { count: 0 })\n    }\n    transform(id) {\n      state.get(this.environment).count++\n    },\n    buildEnd() {\n      console.log(this.environment.name, state.get(this.environment).count)\n    }\n  }\n}\n```\n\nTo simplify this pattern, Vite exports a `perEnvironmentState` helper:\n\n```js\nfunction PerEnvironmentCountTransformedModulesPlugin() {\n  const state = perEnvironmentState<{ count: number }>(() => ({ count: 0 }))\n  return {\n    name: 'count-transformed-modules',\n    perEnvironmentStartEndDuringDev: true,\n    buildStart() {\n      state(this).count = 0\n    }\n    transform(id) {\n      state(this).count++\n    },\n    buildEnd() {\n      console.log(this.environment.name, state(this).count)\n    }\n  }\n}\n```\n"
  },
  {
    "path": "docs/changes/ssr-using-modulerunner.md",
    "content": "# SSR Using `ModuleRunner` API\n\n::: tip Feedback\nGive us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)\n:::\n\n`server.ssrLoadModule` has been replaced by importing from a [Module Runner](/guide/api-environment#modulerunner).\n\nAffected scope: `Vite Plugin Authors`\n\n::: warning Future Deprecation\n`ModuleRunner` was first introduced in `v6.0`. The deprecation of `server.ssrLoadModule` is planned for a future major. To identify your usage, set `future.removeSsrLoadModule` to `\"warn\"` in your vite config.\n:::\n\n## Motivation\n\nThe `server.ssrLoadModule(url)` only allows importing modules in the `ssr` environment and can only execute the modules in the same process as the Vite dev server. For apps with custom environments, each is associated with a `ModuleRunner` that may be running in a separate thread or process. To import modules, we now have `moduleRunner.import(url)`.\n\n## Migration Guide\n\nCheck out the [Environment API for Frameworks Guide](../guide/api-environment-frameworks.md).\n\n`server.ssrFixStacktrace` and `server.ssrRewriteStacktrace` do not have to be called when using the Module Runner APIs. The stack traces will be updated unless `sourcemapInterceptor` is set to `false`.\n"
  },
  {
    "path": "docs/changes/this-environment-in-hooks.md",
    "content": "# `this.environment` in Hooks\n\n::: tip Feedback\nGive us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)\n:::\n\nBefore Vite 6, only two environments were available: `client` and `ssr`. A single `options.ssr` plugin hook argument in `resolveId`, `load` and `transform` allowed plugin authors to differentiate between these two environments when processing modules in plugin hooks. In Vite 6, a Vite application can define any number of named environments as needed. We're introducing `this.environment` in the plugin context to interact with the environment of the current module in hooks.\n\nAffected scope: `Vite Plugin Authors`\n\n::: warning Future Deprecation\n`this.environment` was introduced in `v6.0`. The deprecation of `options.ssr` is planned for a future major. At that point we'll start recommending migrating your plugins to use the new API. To identify your usage, set `future.removePluginHookSsrArgument` to `\"warn\"` in your vite config.\n:::\n\n## Motivation\n\n`this.environment` not only allow the plugin hook implementation to know the current environment name, it also gives access to the environment config options, module graph information, and transform pipeline (`environment.config`, `environment.moduleGraph`, `environment.transformRequest()`). Having the environment instance available in the context allows plugin authors to avoid the dependency of the whole dev server (typically cached at startup through the `configureServer` hook).\n\n## Migration Guide\n\nFor the existing plugin to do a quick migration, replace the `options.ssr` argument with `this.environment.config.consumer === 'server'` in the `resolveId`, `load` and `transform` hooks:\n\n```ts\nimport { Plugin } from 'vite'\n\nexport function myPlugin(): Plugin {\n  return {\n    name: 'my-plugin',\n    resolveId(id, importer, options) {\n      const isSSR = options.ssr // [!code --]\n      const isSSR = this.environment.config.consumer === 'server' // [!code ++]\n\n      if (isSSR) {\n        // SSR specific logic\n      } else {\n        // Client specific logic\n      }\n    },\n  }\n}\n```\n\nFor a more robust long term implementation, the plugin hook should handle for [multiple environments](/guide/api-environment-plugins.html#accessing-the-current-environment-in-hooks) using fine-grained environment options instead of relying on the environment name.\n"
  },
  {
    "path": "docs/config/build-options.md",
    "content": "# Build Options\n\nUnless noted, the options in this section are only applied to build.\n\n## build.target\n\n- **Type:** `string | string[]`\n- **Default:** `'baseline-widely-available'`\n- **Related:** [Browser Compatibility](/guide/build#browser-compatibility)\n\nBrowser compatibility target for the final bundle. The default value is a Vite special value, `'baseline-widely-available'`, which targets browsers that are included in the [Baseline](https://web-platform-dx.github.io/web-features/) Widely Available on 2026-01-01. Specifically, it is `['chrome111', 'edge111', 'firefox114', 'safari16.4']`.\n\nAnother special value is `'esnext'` - which assumes native dynamic imports support and will only perform minimal transpiling.\n\nThe transform is performed with Oxc Transformer and the value should be a valid [Oxc Transformer target option](https://oxc.rs/docs/guide/usage/transformer/lowering#target). Custom targets can either be an ES version (e.g. `es2015`), a browser with version (e.g. `chrome58`), or an array of multiple target strings.\n\nNote the build will output a warning if the code contains features that cannot be safely transpiled by Oxc. See [Oxc docs](https://oxc.rs/docs/guide/usage/transformer/lowering#warnings) for more details.\n\n## build.modulePreload\n\n- **Type:** `boolean | { polyfill?: boolean, resolveDependencies?: ResolveModulePreloadDependenciesFn }`\n- **Default:** `{ polyfill: true }`\n\nBy default, a [module preload polyfill](https://guybedford.com/es-module-preloading-integrity#modulepreload-polyfill) is automatically injected. The polyfill is auto injected into the proxy module of each `index.html` entry. If the build is configured to use a non-HTML custom entry via `build.rollupOptions.input`, then it is necessary to manually import the polyfill in your custom entry:\n\n```js\nimport 'vite/modulepreload-polyfill'\n```\n\nNote: the polyfill does **not** apply to [Library Mode](/guide/build#library-mode). If you need to support browsers without native dynamic import, you should probably avoid using it in your library.\n\nThe polyfill can be disabled using `{ polyfill: false }`.\n\nThe list of chunks to preload for each dynamic import is computed by Vite. By default, an absolute path including the `base` will be used when loading these dependencies. If the `base` is relative (`''` or `'./'`), `import.meta.url` is used at runtime to avoid absolute paths that depend on the final deployed base.\n\nThere is experimental support for fine grained control over the dependencies list and their paths using the `resolveDependencies` function. [Give Feedback](https://github.com/vitejs/vite/discussions/13841). It expects a function of type `ResolveModulePreloadDependenciesFn`:\n\n```ts\ntype ResolveModulePreloadDependenciesFn = (\n  url: string,\n  deps: string[],\n  context: {\n    hostId: string\n    hostType: 'html' | 'js'\n  },\n) => string[]\n```\n\nThe `resolveDependencies` function will be called for each dynamic import with a list of the chunks it depends on, and it will also be called for each chunk imported in entry HTML files. A new dependencies array can be returned with these filtered or more dependencies injected, and their paths modified. The `deps` paths are relative to the `build.outDir`. The return value should be a relative path to the `build.outDir`.\n\n```js twoslash\n/** @type {import('vite').UserConfig} */\nconst config = {\n  // prettier-ignore\n  build: {\n// ---cut-before---\nmodulePreload: {\n  resolveDependencies: (filename, deps, { hostId, hostType }) => {\n    return deps.filter(condition)\n  },\n},\n// ---cut-after---\n  },\n}\n```\n\nThe resolved dependency paths can be further modified using [`experimental.renderBuiltUrl`](../guide/build.md#advanced-base-options).\n\n## build.polyfillModulePreload\n\n- **Type:** `boolean`\n- **Default:** `true`\n- **Deprecated** use `build.modulePreload.polyfill` instead\n\nWhether to automatically inject a [module preload polyfill](https://guybedford.com/es-module-preloading-integrity#modulepreload-polyfill).\n\n## build.outDir\n\n- **Type:** `string`\n- **Default:** `dist`\n\nSpecify the output directory (relative to [project root](/guide/#index-html-and-project-root)).\n\n## build.assetsDir\n\n- **Type:** `string`\n- **Default:** `assets`\n\nSpecify the directory to nest generated assets under (relative to `build.outDir`. This is not used in [Library Mode](/guide/build#library-mode)).\n\n## build.assetsInlineLimit\n\n- **Type:** `number` | `((filePath: string, content: Buffer) => boolean | undefined)`\n- **Default:** `4096` (4 KiB)\n\nImported or referenced assets that are smaller than this threshold will be inlined as base64 URLs to avoid extra http requests. Set to `0` to disable inlining altogether.\n\nIf a callback is passed, a boolean can be returned to opt-in or opt-out. If nothing is returned the default logic applies.\n\nGit LFS placeholders are automatically excluded from inlining because they do not contain the content of the file they represent.\n\n::: tip Note\nIf you specify `build.lib`, `build.assetsInlineLimit` will be ignored and assets will always be inlined, regardless of file size or being a Git LFS placeholder.\n:::\n\n## build.cssCodeSplit\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nEnable/disable CSS code splitting. When enabled, CSS imported in async JS chunks will be preserved as chunks and fetched together when the chunk is fetched.\n\nIf disabled, all CSS in the entire project will be extracted into a single CSS file.\n\n::: tip Note\nIf you specify `build.lib`, `build.cssCodeSplit` will be `false` as default.\n:::\n\n## build.cssTarget\n\n- **Type:** `string | string[]`\n- **Default:** the same as [`build.target`](#build-target)\n\nThis option allows users to set a different browser target for CSS minification from the one used for JavaScript transpilation.\n\nIt should only be used when you are targeting a non-mainstream browser.\nOne example is Android WeChat WebView, which supports most modern JavaScript features but not the [`#RGBA` hexadecimal color notation in CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#rgb_colors).\nIn this case, you need to set `build.cssTarget` to `chrome61` to prevent vite from transforming `rgba()` colors into `#RGBA` hexadecimal notations.\n\n## build.cssMinify\n\n- **Type:** `boolean | 'lightningcss' | 'esbuild'`\n- **Default:** the same as [`build.minify`](#build-minify) for client, `'lightningcss'` for SSR\n\nThis option allows users to override CSS minification specifically instead of defaulting to `build.minify`, so you can configure minification for JS and CSS separately. Vite uses [Lightning CSS](https://lightningcss.dev/minification.html) by default to minify CSS. It can be configured using [`css.lightningcss`](./shared-options.md#css-lightningcss). Set the option to `'esbuild'` to use esbuild instead.\n\nesbuild must be installed when it is set to `'esbuild'`.\n\n```sh\nnpm add -D esbuild\n```\n\n## build.sourcemap\n\n- **Type:** `boolean | 'inline' | 'hidden'`\n- **Default:** `false`\n\nGenerate production source maps. If `true`, a separate sourcemap file will be created. If `'inline'`, the sourcemap will be appended to the resulting output file as a data URI. `'hidden'` works like `true` except that the corresponding sourcemap comments in the bundled files are suppressed.\n\n## build.rolldownOptions\n\n- **Type:** [`RolldownOptions`](https://rolldown.rs/reference/)\n\nDirectly customize the underlying Rolldown bundle. This is the same as options that can be exported from a Rolldown config file and will be merged with Vite's internal Rolldown options. See [Rolldown options docs](https://rolldown.rs/reference/) for more details.\n\n## build.rollupOptions\n\n- **Type:** `RolldownOptions`\n- **Deprecated**\n\nThis option is an alias of `build.rolldownOptions` option. Use `build.rolldownOptions` option instead.\n\n## build.dynamicImportVarsOptions\n\n- **Type:** `{ include?: string | RegExp | (string | RegExp)[], exclude?: string | RegExp | (string | RegExp)[] }`\n- **Related:** [Dynamic Import](/guide/features#dynamic-import)\n\nWhether to transform dynamic imports with variables.\n\n## build.lib\n\n- **Type:** `{ entry: string | string[] | { [entryAlias: string]: string }, name?: string, formats?: ('es' | 'cjs' | 'umd' | 'iife')[], fileName?: string | ((format: ModuleFormat, entryName: string) => string), cssFileName?: string }`\n- **Related:** [Library Mode](/guide/build#library-mode)\n\nBuild as a library. `entry` is required since the library cannot use HTML as entry. `name` is the exposed global variable and is required when `formats` includes `'umd'` or `'iife'`. Default `formats` are `['es', 'umd']`, or `['es', 'cjs']`, if multiple entries are used.\n\n`fileName` is the name of the package file output, which defaults to the `\"name\"` in `package.json`. It can also be defined as a function taking the `format` and `entryName` as arguments, and returning the file name.\n\nIf your package imports CSS, `cssFileName` can be used to specify the name of the CSS file output. It defaults to the same value as `fileName` if it's set a string, otherwise it also falls back to the `\"name\"` in `package.json`.\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: ['src/main.js'],\n      fileName: (format, entryName) => `my-lib-${entryName}.${format}.js`,\n      cssFileName: 'my-lib-style',\n    },\n  },\n})\n```\n\n## build.license\n\n- **Type:** `boolean | { fileName?: string }`\n- **Default:** `false`\n- **Related:** [License](/guide/features#license)\n\nWhen set to `true`, the build will generate a `.vite/license.md` file that includes all bundled dependencies' licenses.\n\nIf `fileName` is passed, it will be used as the license file name relative to the `outDir`. If it ends with `.json`, the raw JSON metadata will be generated instead and can be used for further processing. For example:\n\n```json\n[\n  {\n    \"name\": \"dep-1\",\n    \"version\": \"1.2.3\",\n    \"identifier\": \"CC0-1.0\",\n    \"text\": \"CC0 1.0 Universal\\n\\n...\"\n  },\n  {\n    \"name\": \"dep-2\",\n    \"version\": \"4.5.6\",\n    \"identifier\": \"MIT\",\n    \"text\": \"MIT License\\n\\n...\"\n  }\n]\n```\n\n::: tip\n\nIf you'd like to reference the license file in the built code, you can use [`build.rolldownOptions.output.postBanner`](https://rolldown.rs/reference/OutputOptions.postBanner#postbanner) to inject a comment at the top of the files. For example:\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    license: true,\n    rolldownOptions: {\n      output: {\n        postBanner:\n          '/* See licenses of bundled dependencies at https://example.com/license.md */',\n      },\n    },\n  },\n})\n```\n\n:::\n\n## build.manifest\n\n- **Type:** `boolean | string`\n- **Default:** `false`\n- **Related:** [Backend Integration](/guide/backend-integration)\n\nWhether to generate a manifest file that contains a mapping of non-hashed asset filenames to their hashed versions, which can then be used by a server framework to render the correct asset links.\n\nWhen the value is a string, it will be used as the manifest file path relative to `build.outDir`. When set to `true`, the path would be `.vite/manifest.json`.\n\nIf you are writing a plugin and need to inspect each output chunk or asset's related CSS and static assets during the build, you can also use [`viteMetadata` output bundle metadata API](/guide/api-plugin#output-bundle-metadata).\n\n## build.ssrManifest\n\n- **Type:** `boolean | string`\n- **Default:** `false`\n- **Related:** [Server-Side Rendering](/guide/ssr)\n\nWhether to generate a SSR manifest file for determining style links and asset preload directives in production.\n\nWhen the value is a string, it will be used as the manifest file path relative to `build.outDir`. When set to `true`, the path would be `.vite/ssr-manifest.json`.\n\n## build.ssr\n\n- **Type:** `boolean | string`\n- **Default:** `false`\n- **Related:** [Server-Side Rendering](/guide/ssr)\n\nProduce SSR-oriented build. The value can be a string to directly specify the SSR entry, or `true`, which requires specifying the SSR entry via `rollupOptions.input`.\n\n## build.emitAssets\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nDuring non-client builds, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in other environments build. It is responsibility of the framework to merge the assets with a post build step.\n\n## build.ssrEmitAssets\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nDuring the SSR build, static assets aren't emitted as it is assumed they would be emitted as part of the client build. This option allows frameworks to force emitting them in both the client and SSR build. It is responsibility of the framework to merge the assets with a post build step. This option will be replaced by `build.emitAssets` once Environment API is stable.\n\n## build.minify\n\n- **Type:** `boolean | 'oxc' | 'terser' | 'esbuild'`\n- **Default:** `'oxc'` for client build, `false` for SSR build\n\nSet to `false` to disable minification, or specify the minifier to use. The default is [Oxc Minifier](https://oxc.rs/docs/guide/usage/minifier) which is 30 ~ 90x faster than terser and only 0.5 ~ 2% worse compression. [Benchmarks](https://github.com/privatenumber/minification-benchmarks)\n\n`build.minify: 'esbuild'` is deprecated and will be removed in the future.\n\nNote the `build.minify` option does not minify whitespaces when using the `'es'` format in lib mode, as it removes pure annotations and breaks tree-shaking.\n\nesbuild or Terser must be installed when it is set to `'esbuild'` or `'terser'` respectively.\n\n```sh\nnpm add -D esbuild\nnpm add -D terser\n```\n\n## build.terserOptions\n\n- **Type:** `TerserOptions`\n\nAdditional [minify options](https://terser.org/docs/api-reference#minify-options) to pass on to Terser.\n\nIn addition, you can also pass a `maxWorkers: number` option to specify the max number of workers to spawn. Defaults to the number of CPUs minus 1.\n\n## build.write\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nSet to `false` to disable writing the bundle to disk. This is mostly used in [programmatic `build()` calls](/guide/api-javascript#build) where further post processing of the bundle is needed before writing to disk.\n\n## build.emptyOutDir\n\n- **Type:** `boolean`\n- **Default:** `true` if `outDir` is inside `root`\n\nBy default, Vite will empty the `outDir` on build if it is inside project root. It will emit a warning if `outDir` is outside of root to avoid accidentally removing important files. You can explicitly set this option to suppress the warning. This is also available via command line as `--emptyOutDir`.\n\n## build.copyPublicDir\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nBy default, Vite will copy files from the `publicDir` into the `outDir` on build. Set to `false` to disable this.\n\n## build.reportCompressedSize\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nEnable/disable gzip-compressed size reporting. Compressing large output files can be slow, so disabling this may increase build performance for large projects.\n\n## build.chunkSizeWarningLimit\n\n- **Type:** `number`\n- **Default:** `500`\n\nLimit for chunk size warnings (in kB). It is compared against the uncompressed chunk size as the [JavaScript size itself is related to the execution time](https://v8.dev/blog/cost-of-javascript-2019).\n\n## build.watch\n\n- **Type:** [`WatcherOptions`](https://rolldown.rs/reference/InputOptions.watch)`| null`\n- **Default:** `null`\n\nSet to `{}` to enable rollup watcher. This is mostly used in cases that involve build-only plugins or integrations processes.\n\n::: warning Using Vite on Windows Subsystem for Linux (WSL) 2\n\nThere are cases that file system watching does not work with WSL2.\nSee [`server.watch`](./server-options.md#server-watch) for more details.\n\n:::\n"
  },
  {
    "path": "docs/config/dep-optimization-options.md",
    "content": "# Dep Optimization Options\n\n- **Related:** [Dependency Pre-Bundling](/guide/dep-pre-bundling)\n\nUnless noted, the options in this section are only applied to the dependency optimizer, which is only used in dev.\n\n## optimizeDeps.entries <NonInheritBadge />\n\n- **Type:** `string | string[]`\n\nBy default, Vite will crawl all your `.html` files to detect dependencies that need to be pre-bundled (ignoring `node_modules`, `build.outDir`, `__tests__` and `coverage`). If `build.rollupOptions.input` is specified, Vite will crawl those entry points instead.\n\nIf neither of these fit your needs, you can specify custom entries using this option - the value should be a [`tinyglobby` pattern](https://superchupu.dev/tinyglobby/comparison) or array of patterns that are relative from Vite project root. This will overwrite default entries inference. Only `node_modules` and `build.outDir` folders will be ignored by default when `optimizeDeps.entries` is explicitly defined. If other folders need to be ignored, you can use an ignore pattern as part of the entries list, marked with an initial `!`. `node_modules` will not be ignored for patterns that explicitly include the string `node_modules`.\n\n## optimizeDeps.exclude <NonInheritBadge />\n\n- **Type:** `string[]`\n\nDependencies to exclude from pre-bundling.\n\n:::warning CommonJS\nCommonJS dependencies should not be excluded from optimization. If an ESM dependency is excluded from optimization, but has a nested CommonJS dependency, the CommonJS dependency should be added to `optimizeDeps.include`. Example:\n\n```js twoslash\nimport { defineConfig } from 'vite'\n// ---cut---\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['esm-dep > cjs-dep'],\n  },\n})\n```\n\n:::\n\n## optimizeDeps.include <NonInheritBadge />\n\n- **Type:** `string[]`\n\nBy default, linked packages not inside `node_modules` are not pre-bundled. Use this option to force a linked package to be pre-bundled.\n\n**Experimental:** If you're using a library with many deep imports, you can also specify a trailing glob pattern to pre-bundle all deep imports at once. This will avoid constantly pre-bundling whenever a new deep import is used. [Give Feedback](https://github.com/vitejs/vite/discussions/15833). For example:\n\n```js twoslash\nimport { defineConfig } from 'vite'\n// ---cut---\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['my-lib/components/**/*.vue'],\n  },\n})\n```\n\n## optimizeDeps.rolldownOptions <NonInheritBadge />\n\n- **Type:** <code>Omit<<a href=\"https://rolldown.rs/reference/Interface.RolldownOptions\">RolldownOptions</a>, 'input' | 'logLevel' | 'output'> & { output?: Omit<<a href=\"https://rolldown.rs/reference/#:~:text=Output%20Options\">RolldownOutputOptions</a>, 'format' | 'sourcemap' | 'dir' | 'banner'> }</code>\n\nOptions to pass to Rolldown during the dep scanning and optimization.\n\nCertain options are omitted since changing them would not be compatible with Vite's dep optimization.\n\n- `plugins` are merged with Vite's dep plugin\n\n## optimizeDeps.esbuildOptions <NonInheritBadge />\n\n- **Type:** <code>Omit<<a href=\"https://esbuild.github.io/api/#general-options\">EsbuildBuildOptions</a>, 'bundle' | 'entryPoints' | 'external' | 'write' | 'watch' | 'outdir' | 'outfile' | 'outbase' | 'outExtension' | 'metafile'></code>\n- **Deprecated**\n\nThis option is converted to `optimizeDeps.rolldownOptions` internally. Use `optimizeDeps.rolldownOptions` instead.\n\n## optimizeDeps.force <NonInheritBadge />\n\n- **Type:** `boolean`\n\nSet to `true` to force dependency pre-bundling, ignoring previously cached optimized dependencies.\n\n## optimizeDeps.noDiscovery <NonInheritBadge />\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nWhen set to `true`, automatic dependency discovery will be disabled and only dependencies listed in `optimizeDeps.include` will be optimized. CJS-only dependencies must be present in `optimizeDeps.include` during dev.\n\n## optimizeDeps.holdUntilCrawlEnd <NonInheritBadge />\n\n- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/15834)\n- **Type:** `boolean`\n- **Default:** `true`\n\nWhen enabled, it will hold the first optimized deps results until all static imports are crawled on cold start. This avoids the need for full-page reloads when new dependencies are discovered and they trigger the generation of new common chunks. If all dependencies are found by the scanner plus the explicitly defined ones in `include`, it is better to disable this option to let the browser process more requests in parallel.\n\n## optimizeDeps.disabled <NonInheritBadge />\n\n- **Deprecated**\n- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/13839)\n- **Type:** `boolean | 'build' | 'dev'`\n- **Default:** `'build'`\n\nThis option is deprecated. As of Vite 5.1, pre-bundling of dependencies during build have been removed. Setting `optimizeDeps.disabled` to `true` or `'dev'` disables the optimizer, and configured to `false` or `'build'` leaves the optimizer during dev enabled.\n\nTo disable the optimizer completely, use `optimizeDeps.noDiscovery: true` to disallow automatic discovery of dependencies and leave `optimizeDeps.include` undefined or empty.\n\n:::warning\nOptimizing dependencies during build time was an **experimental** feature. Projects trying out this strategy also removed `@rollup/plugin-commonjs` using `build.commonjsOptions: { include: [] }`. If you did so, a warning will guide you to re-enable it to support CJS only packages while bundling.\n:::\n\n## optimizeDeps.needsInterop <NonInheritBadge />\n\n- **Experimental**\n- **Type:** `string[]`\n\nForces ESM interop when importing these dependencies. Vite is able to properly detect when a dependency needs interop, so this option isn't generally needed. However, different combinations of dependencies could cause some of them to be prebundled differently. Adding these packages to `needsInterop` can speed up cold start by avoiding full-page reloads. You'll receive a warning if this is the case for one of your dependencies, suggesting to add the package name to this array in your config.\n"
  },
  {
    "path": "docs/config/index.md",
    "content": "---\ntitle: Configuring Vite\n---\n\n# Configuring Vite\n\nWhen running `vite` from the command line, Vite will automatically try to resolve a config file named `vite.config.js` inside [project root](/guide/#index-html-and-project-root) (other JS and TS extensions are also supported).\n\nThe most basic config file looks like this:\n\n```js [vite.config.js]\nexport default {\n  // config options\n}\n```\n\nNote Vite supports using ES modules syntax in the config file even if the project is not using native Node ESM, e.g. `\"type\": \"module\"` in `package.json`. In this case, the config file is auto pre-processed before load.\n\nYou can also explicitly specify a config file to use with the `--config` CLI option (resolved relative to `cwd`):\n\n```bash\nvite --config my-config.js\n```\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq/~05jg?via=vite\" title=\"Configuring Vite\">Watch an interactive lesson on Scrimba</ScrimbaLink>\n\n::: tip CONFIG LOADING\nBy default, Vite uses [Rolldown](https://rolldown.rs/) to bundle the config into a temporary file and load it. This may cause issues when importing TypeScript files in a monorepo. If you encounter any issues with this approach, you can specify `--configLoader runner` to use the [module runner](/guide/api-environment-runtimes.html#modulerunner) instead, which will not create a temporary config and will transform any files on the fly. Note that module runner doesn't support CJS in config files, but external CJS packages should work as usual.\n\nAlternatively, if you're using an environment that supports TypeScript (e.g. `node --experimental-strip-types`), or if you're only writing plain JavaScript, you can specify `--configLoader native` to use the environment's native runtime to load the config file. Note that updates to modules imported by the config file are not detected and hence would not auto-restart the Vite server.\n:::\n\n## Config Intellisense\n\nSince Vite ships with TypeScript typings, you can leverage your IDE's intellisense with jsdoc type hints:\n\n```js\n/** @type {import('vite').UserConfig} */\nexport default {\n  // ...\n}\n```\n\nAlternatively, you can use the `defineConfig` helper which should provide intellisense without the need for jsdoc annotations:\n\n```js\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  // ...\n})\n```\n\nVite also supports TypeScript config files. You can use `vite.config.ts` with the `defineConfig` helper function above, or with the `satisfies` operator:\n\n```ts\nimport type { UserConfig } from 'vite'\n\nexport default {\n  // ...\n} satisfies UserConfig\n```\n\n## Conditional Config\n\nIf the config needs to conditionally determine options based on the command (`serve` or `build`), the [mode](/guide/env-and-mode#modes) being used, if it's an SSR build (`isSsrBuild`), or is previewing the build (`isPreview`), it can export a function instead:\n\n```js twoslash\nimport { defineConfig } from 'vite'\n// ---cut---\nexport default defineConfig(({ command, mode, isSsrBuild, isPreview }) => {\n  if (command === 'serve') {\n    return {\n      // dev specific config\n    }\n  } else {\n    // command === 'build'\n    return {\n      // build specific config\n    }\n  }\n})\n```\n\nIt is important to note that in Vite's API the `command` value is `serve` during dev (in the cli [`vite`](/guide/cli#vite), `vite dev`, and `vite serve` are aliases), and `build` when building for production ([`vite build`](/guide/cli#vite-build)).\n\n`isSsrBuild` and `isPreview` are additional optional flags to differentiate the kind of `build` and `serve` commands respectively. Some tools that load the Vite config may not support these flags and will pass `undefined` instead. Hence, it's recommended to use explicit comparison against `true` and `false`.\n\n## Async Config\n\nIf the config needs to call async functions, it can export an async function instead. And this async function can also be passed through `defineConfig` for improved intellisense support:\n\n```js twoslash\nimport { defineConfig } from 'vite'\n// ---cut---\nexport default defineConfig(async ({ command, mode }) => {\n  const data = await asyncFunction()\n  return {\n    // vite config\n  }\n})\n```\n\n## Using Environment Variables in Config\n\nEnvironment variables available while the config itself is being evaluated are only those that already exist in the current process environment (`process.env`). Vite deliberately defers loading any `.env*` files until _after_ the user config has been resolved because the set of files to load depends on config options like [`root`](/guide/#index-html-and-project-root) and [`envDir`](/config/shared-options.md#envdir), and also on the final `mode`.\n\nThis means: variables defined in `.env`, `.env.local`, `.env.[mode]`, or `.env.[mode].local` are **not** automatically injected into `process.env` while your `vite.config.*` is running. They _are_ automatically loaded later and exposed to application code via `import.meta.env` (with the default `VITE_` prefix filter) exactly as documented in [Env Variables and Modes](/guide/env-and-mode.html). So if you only need to pass values from `.env*` files to the app, you don't need to call anything in the config.\n\nIf, however, values from `.env*` files must influence the config itself (for example to set `server.port`, conditionally enable plugins, or compute `define` replacements), you can load them manually using the exported [`loadEnv`](/guide/api-javascript.html#loadenv) helper.\n\n```js twoslash\nimport { defineConfig, loadEnv } from 'vite'\n\nexport default defineConfig(({ mode }) => {\n  // Load env file based on `mode` in the current working directory.\n  // Set the third parameter to '' to load all env regardless of the\n  // `VITE_` prefix.\n  const env = loadEnv(mode, process.cwd(), '')\n  return {\n    define: {\n      // Provide an explicit app-level constant derived from an env var.\n      __APP_ENV__: JSON.stringify(env.APP_ENV),\n    },\n    // Example: use an env var to set the dev server port conditionally.\n    server: {\n      port: env.APP_PORT ? Number(env.APP_PORT) : 5173,\n    },\n  }\n})\n```\n\n## Debugging the Config File on VS Code\n\nWith the default `--configLoader bundle` behavior, Vite writes the generated temporary configuration file to the `node_modules/.vite-temp` folder and a file not found error will occur when setting breakpoint debugging in the Vite config file. To fix the issue, add the following configuration to `.vscode/settings.json`:\n\n```json\n{\n  \"debug.javascript.terminalOptions\": {\n    \"resolveSourceMapLocations\": [\n      \"${workspaceFolder}/**\",\n      \"!**/node_modules/**\",\n      \"**/node_modules/.vite-temp/**\"\n    ]\n  }\n}\n```\n"
  },
  {
    "path": "docs/config/preview-options.md",
    "content": "# Preview Options\n\nUnless noted, the options in this section are only applied to preview.\n\n## preview.host\n\n- **Type:** `string | boolean`\n- **Default:** [`server.host`](./server-options#server-host)\n\nSpecify which IP addresses the server should listen on.\nSet this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses.\n\nThis can be set via the CLI using `--host 0.0.0.0` or `--host`.\n\n::: tip NOTE\n\nThere are cases when other servers might respond instead of Vite.\nSee [`server.host`](./server-options#server-host) for more details.\n\n:::\n\n## preview.allowedHosts\n\n- **Type:** `string[] | true`\n- **Default:** [`server.allowedHosts`](./server-options#server-allowedhosts)\n\nThe hostnames that Vite is allowed to respond to.\n\nSee [`server.allowedHosts`](./server-options#server-allowedhosts) for more details.\n\n## preview.port\n\n- **Type:** `number`\n- **Default:** `4173`\n\nSpecify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on.\n\n**Example:**\n\n```js\nexport default defineConfig({\n  server: {\n    port: 3030,\n  },\n  preview: {\n    port: 8080,\n  },\n})\n```\n\n## preview.strictPort\n\n- **Type:** `boolean`\n- **Default:** [`server.strictPort`](./server-options#server-strictport)\n\nSet to `true` to exit if port is already in use, instead of automatically trying the next available port.\n\n## preview.https\n\n- **Type:** `https.ServerOptions`\n- **Default:** [`server.https`](./server-options#server-https)\n\nEnable TLS + HTTP/2.\n\nSee [`server.https`](./server-options#server-https) for more details.\n\n## preview.open\n\n- **Type:** `boolean | string`\n- **Default:** [`server.open`](./server-options#server-open)\n\nAutomatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname. If you want to open the server in a specific browser you like, you can set the env `process.env.BROWSER` (e.g. `firefox`). You can also set `process.env.BROWSER_ARGS` to pass additional arguments (e.g. `--incognito`).\n\n`BROWSER` and `BROWSER_ARGS` are also special environment variables you can set in the `.env` file to configure it. See [the `open` package](https://github.com/sindresorhus/open#app) for more details.\n\n## preview.proxy\n\n- **Type:** `Record<string, string | ProxyOptions>`\n- **Default:** [`server.proxy`](./server-options#server-proxy)\n\nConfigure custom proxy rules for the preview server. Expects an object of `{ key: options }` pairs. If the key starts with `^`, it will be interpreted as a `RegExp`. The `configure` option can be used to access the proxy instance.\n\nUses [`http-proxy-3`](https://github.com/sagemathinc/http-proxy-3). Full options [here](https://github.com/sagemathinc/http-proxy-3#options).\n\n## preview.cors\n\n- **Type:** `boolean | CorsOptions`\n- **Default:** [`server.cors`](./server-options#server-cors)\n\nConfigure CORS for the preview server.\n\nSee [`server.cors`](./server-options#server-cors) for more details.\n\n## preview.headers\n\n- **Type:** `OutgoingHttpHeaders`\n\nSpecify server response headers.\n"
  },
  {
    "path": "docs/config/server-options.md",
    "content": "# Server Options\n\nUnless noted, the options in this section are only applied to dev.\n\n## server.host\n\n- **Type:** `string | boolean`\n- **Default:** `'localhost'`\n\nSpecify which IP addresses the server should listen on.\nSet this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses.\n\nThis can be set via the CLI using `--host 0.0.0.0` or `--host`.\n\n::: tip NOTE\n\nThere are cases when other servers might respond instead of Vite.\n\nThe first case is when `localhost` is used. Node.js under v17 reorders the result of DNS-resolved addresses by default. When accessing `localhost`, browsers use DNS to resolve the address and that address might differ from the address which Vite is listening to. Vite prints the resolved address when it differs.\n\nYou can set [`dns.setDefaultResultOrder('verbatim')`](https://nodejs.org/api/dns.html#dns_dns_setdefaultresultorder_order) to disable the reordering behavior. Vite will then print the address as `localhost`.\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\nimport dns from 'node:dns'\n\ndns.setDefaultResultOrder('verbatim')\n\nexport default defineConfig({\n  // omit\n})\n```\n\nThe second case is when wildcard hosts (e.g. `0.0.0.0`) are used. This is because servers listening on non-wildcard hosts take priority over those listening on wildcard hosts.\n\n:::\n\n::: tip Accessing the server on WSL2 from your LAN\n\nWhen running Vite on WSL2, it is not sufficient to set `host: true` to access the server from your LAN.\nSee [the WSL document](https://learn.microsoft.com/en-us/windows/wsl/networking#accessing-a-wsl-2-distribution-from-your-local-area-network-lan) for more details.\n\n:::\n\n## server.allowedHosts\n\n- **Type:** `string[] | true`\n- **Default:** `[]`\n\nThe hostnames that Vite is allowed to respond to.\n`localhost` and domains under `.localhost` and all IP addresses are allowed by default.\nWhen using HTTPS, this check is skipped.\n\nIf a string starts with `.`, it will allow that hostname without the `.` and all subdomains under the hostname. For example, `.example.com` will allow `example.com`, `foo.example.com`, and `foo.bar.example.com`. If set to `true`, the server is allowed to respond to requests for any hosts.\n\n::: details What hosts are safe to be added?\n\nHosts that you have control over which IP addresses they resolve to are safe to add to the list of allowed hosts.\n\nFor example, if you own a domain `vite.dev`, you can add `vite.dev` and `.vite.dev` to the list. If you don't own that domain and you cannot trust the owner of that domain, you should not add it.\n\nEspecially, you should never add Top-Level Domains like `.com` to the list. This is because anyone can purchase a domain like `example.com` and control the IP address it resolves to.\n\n:::\n\n::: danger\n\nSetting `server.allowedHosts` to `true` allows any website to send requests to your dev server through DNS rebinding attacks, allowing them to download your source code and content. We recommend always using an explicit list of allowed hosts. See [GHSA-vg6x-rcgg-rjx6](https://github.com/vitejs/vite/security/advisories/GHSA-vg6x-rcgg-rjx6) for more details.\n\n:::\n\n::: details Configure via environment variable\nYou can set the environment variable `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS` to add an additional allowed host.\n:::\n\n## server.port\n\n- **Type:** `number`\n- **Default:** `5173`\n\nSpecify server port. Note if the port is already being used, Vite will automatically try the next available port so this may not be the actual port the server ends up listening on.\n\n## server.strictPort\n\n- **Type:** `boolean`\n\nSet to `true` to exit if port is already in use, instead of automatically trying the next available port.\n\n## server.https\n\n- **Type:** `https.ServerOptions`\n\nEnable TLS + HTTP/2. The value is an [options object](https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener) passed to `https.createServer()`.\n\nA valid certificate is needed. For a basic setup, you can add [@vitejs/plugin-basic-ssl](https://github.com/vitejs/vite-plugin-basic-ssl) to the project plugins, which will automatically create and cache a self-signed certificate. But we recommend creating your own certificates.\n\n## server.open\n\n- **Type:** `boolean | string`\n\nAutomatically open the app in the browser on server start. When the value is a string, it will be used as the URL's pathname. If you want to open the server in a specific browser you like, you can set the env `process.env.BROWSER` (e.g. `firefox`). You can also set `process.env.BROWSER_ARGS` to pass additional arguments (e.g. `--incognito`).\n\n`BROWSER` and `BROWSER_ARGS` are also special environment variables you can set in the `.env` file to configure it. See [the `open` package](https://github.com/sindresorhus/open#app) for more details.\n\n**Example:**\n\n```js\nexport default defineConfig({\n  server: {\n    open: '/docs/index.html',\n  },\n})\n```\n\n## server.proxy\n\n- **Type:** `Record<string, string | ProxyOptions>`\n\nConfigure custom proxy rules for the dev server. Expects an object of `{ key: options }` pairs. Any requests that request path starts with that key will be proxied to that specified target. If the key starts with `^`, it will be interpreted as a `RegExp`. The `configure` option can be used to access the proxy instance. If a request matches any of the configured proxy rules, the request won't be transformed by Vite.\n\nNote that if you are using non-relative [`base`](/config/shared-options.md#base), you must prefix each key with that `base`.\n\nExtends [`http-proxy-3`](https://github.com/sagemathinc/http-proxy-3#options). Additional options are [here](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/server/middlewares/proxy.ts#L13).\n\nIn some cases, you might also want to configure the underlying dev server (e.g. to add custom middlewares to the internal [connect](https://github.com/senchalabs/connect) app). In order to do that, you need to write your own [plugin](/guide/using-plugins.html) and use [configureServer](/guide/api-plugin.html#configureserver) function.\n\n**Example:**\n\n```js\nexport default defineConfig({\n  server: {\n    proxy: {\n      // string shorthand:\n      // http://localhost:5173/foo\n      //   -> http://localhost:4567/foo\n      '/foo': 'http://localhost:4567',\n      // with options:\n      // http://localhost:5173/api/bar\n      //   -> http://jsonplaceholder.typicode.com/bar\n      '/api': {\n        target: 'http://jsonplaceholder.typicode.com',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/api/, ''),\n      },\n      // with RegExp:\n      // http://localhost:5173/fallback/\n      //   -> http://jsonplaceholder.typicode.com/\n      '^/fallback/.*': {\n        target: 'http://jsonplaceholder.typicode.com',\n        changeOrigin: true,\n        rewrite: (path) => path.replace(/^\\/fallback/, ''),\n      },\n      // Using the proxy instance\n      '/api': {\n        target: 'http://jsonplaceholder.typicode.com',\n        changeOrigin: true,\n        configure: (proxy, options) => {\n          // proxy will be an instance of 'http-proxy'\n        },\n      },\n      // Proxying websockets or socket.io:\n      // ws://localhost:5173/socket.io\n      //   -> ws://localhost:5174/socket.io\n      // Exercise caution using `rewriteWsOrigin` as it can leave the\n      // proxying open to CSRF attacks.\n      '/socket.io': {\n        target: 'ws://localhost:5174',\n        ws: true,\n        rewriteWsOrigin: true,\n      },\n    },\n  },\n})\n```\n\n## server.cors\n\n- **Type:** `boolean | CorsOptions`\n- **Default:** `{ origin: /^https?:\\/\\/(?:(?:[^:]+\\.)?localhost|127\\.0\\.0\\.1|\\[::1\\])(?::\\d+)?$/ }` (allows localhost, `127.0.0.1` and `::1`)\n\nConfigure CORS for the dev server. Pass an [options object](https://github.com/expressjs/cors#configuration-options) to fine tune the behavior or `true` to allow any origin.\n\n::: danger\n\nSetting `server.cors` to `true` allows any website to send requests to your dev server and download your source code and content. We recommend always using an explicit list of allowed origins.\n\n:::\n\n## server.headers\n\n- **Type:** `OutgoingHttpHeaders`\n\nSpecify server response headers.\n\n## server.hmr\n\n- **Type:** `boolean | { protocol?: string, host?: string, port?: number, path?: string, timeout?: number, overlay?: boolean, clientPort?: number, server?: Server }`\n\nDisable or configure HMR connection (in cases where the HMR websocket must use a different address from the http server).\n\nSet `server.hmr.overlay` to `false` to disable the server error overlay.\n\n`protocol` sets the WebSocket protocol used for the HMR connection: `ws` (WebSocket) or `wss` (WebSocket Secure).\n\n`clientPort` is an advanced option that overrides the port only on the client side, allowing you to serve the websocket on a different port than the client code looks for it on.\n\nWhen `server.hmr.server` is defined, Vite will process the HMR connection requests through the provided server. If not in middleware mode, Vite will attempt to process HMR connection requests through the existing server. This can be helpful when using self-signed certificates or when you want to expose Vite over a network on a single port.\n\nCheck out [`vite-setup-catalogue`](https://github.com/sapphi-red/vite-setup-catalogue) for some examples.\n\n::: tip NOTE\n\nWith the default configuration, reverse proxies in front of Vite are expected to support proxying WebSocket. If the Vite HMR client fails to connect WebSocket, the client will fall back to connecting the WebSocket directly to the Vite HMR server bypassing the reverse proxies:\n\n```\nDirect websocket connection fallback. Check out https://vite.dev/config/server-options.html#server-hmr to remove the previous connection error.\n```\n\nThe error that appears in the Browser when the fallback happens can be ignored. To avoid the error by directly bypassing reverse proxies, you could either:\n\n- configure the reverse proxy to proxy WebSocket too\n- set [`server.strictPort = true`](#server-strictport) and set `server.hmr.clientPort` to the same value with `server.port`\n- set `server.hmr.port` to a different value from [`server.port`](#server-port)\n\n:::\n\n## server.forwardConsole\n\n- **Type:** `boolean | { unhandledErrors?: boolean, logLevels?: ('error' | 'warn' | 'info' | 'log' | 'debug')[] }`\n- **Default:** auto (`true` when an AI coding agent is detected based on [`@vercel/detect-agent`](https://www.npmjs.com/package/@vercel/detect-agent), otherwise `false`)\n\nForward browser runtime events to the Vite server console during development.\n\n- `true` enables forwarding unhandled errors and `console.error` / `console.warn` logs.\n- `unhandledErrors` controls forwarding uncaught exceptions and unhandled promise rejections.\n- `logLevels` controls which `console.*` calls are forwarded.\n\nFor example:\n\n```js\nexport default defineConfig({\n  server: {\n    forwardConsole: {\n      unhandledErrors: true,\n      logLevels: ['warn', 'error'],\n    },\n  },\n})\n```\n\nWhen unhandled errors are forwarded, they are logged in the server terminal with enhanced formatting, for example:\n\n```log\n1:18:38 AM [vite] (client) [Unhandled error] Error: this is test error\n > testError src/main.ts:20:8\n     18|\n     19| function testError() {\n     20|   throw new Error('this is test error')\n       |        ^\n     21| }\n     22|\n > HTMLButtonElement.<anonymous> src/main.ts:6:2\n```\n\n## server.warmup\n\n- **Type:** `{ clientFiles?: string[], ssrFiles?: string[] }`\n- **Related:** [Warm Up Frequently Used Files](/guide/performance.html#warm-up-frequently-used-files)\n\nWarm up files to transform and cache the results in advance. This improves the initial page load during server starts and prevents transform waterfalls.\n\n`clientFiles` are files that are used in the client only, while `ssrFiles` are files that are used in SSR only. They accept an array of file paths or [`tinyglobby` patterns](https://superchupu.dev/tinyglobby/comparison) relative to the `root`.\n\nMake sure to only add files that are frequently used to not overload the Vite dev server on startup.\n\n```js\nexport default defineConfig({\n  server: {\n    warmup: {\n      clientFiles: ['./src/components/*.vue', './src/utils/big-utils.js'],\n      ssrFiles: ['./src/server/modules/*.js'],\n    },\n  },\n})\n```\n\n## server.watch\n\n- **Type:** `object | null`\n\nFile system watcher options to pass on to [chokidar](https://github.com/paulmillr/chokidar/tree/3.6.0#api).\n\nThe Vite server watcher watches the `root` and skips the `.git/`, `node_modules/`, `test-results/`, and Vite's `cacheDir` and `build.outDir` directories by default. When updating a watched file, Vite will apply HMR and update the page only if needed.\n\nIf set to `null`, no files will be watched. [`server.watcher`](/guide/api-javascript.html#vitedevserver) will provide a compatible event emitter, but calling `add` or `unwatch` will have no effect.\n\n::: warning Watching files in `node_modules`\n\nIt's currently not possible to watch files and packages in `node_modules`. For further progress and workarounds, you can follow [issue #8619](https://github.com/vitejs/vite/issues/8619).\n\n:::\n\n::: warning Using Vite on Windows Subsystem for Linux (WSL) 2\n\nWhen running Vite on WSL2, file system watching does not work when a file is edited by Windows applications (non-WSL2 process). This is due to [a WSL2 limitation](https://github.com/microsoft/WSL/issues/4739). This also applies to running on Docker with a WSL2 backend.\n\nTo fix it, you could either:\n\n- **Recommended**: Use WSL2 applications to edit your files.\n  - It is also recommended to move the project folder outside of a Windows filesystem. Accessing Windows filesystem from WSL2 is slow. Removing that overhead will improve performance.\n- Set `{ usePolling: true }`.\n  - Note that [`usePolling` leads to high CPU utilization](https://github.com/paulmillr/chokidar/tree/3.6.0#performance).\n\n:::\n\n## server.middlewareMode\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nCreate Vite server in middleware mode.\n\n- **Related:** [appType](./shared-options#apptype), [SSR - Setting Up the Dev Server](/guide/ssr#setting-up-the-dev-server)\n\n- **Example:**\n\n```js twoslash\nimport express from 'express'\nimport { createServer as createViteServer } from 'vite'\n\nasync function createServer() {\n  const app = express()\n\n  // Create Vite server in middleware mode\n  const vite = await createViteServer({\n    server: { middlewareMode: true },\n    // don't include Vite's default HTML handling middlewares\n    appType: 'custom',\n  })\n  // Use vite's connect instance as middleware\n  app.use(vite.middlewares)\n\n  app.use('*', async (req, res) => {\n    // Since `appType` is `'custom'`, should serve response here.\n    // Note: if `appType` is `'spa'` or `'mpa'`, Vite includes middlewares\n    // to handle HTML requests and 404s so user middlewares should be added\n    // before Vite's middlewares to take effect instead\n  })\n}\n\ncreateServer()\n```\n\n## server.fs.strict\n\n- **Type:** `boolean`\n- **Default:** `true` (enabled by default since Vite 2.7)\n\nRestrict serving files outside of workspace root.\n\n## server.fs.allow\n\n- **Type:** `string[]`\n\nRestrict files that could be served via `/@fs/`. When `server.fs.strict` is set to `true`, accessing files outside this directory list that aren't imported from an allowed file will result in a 403.\n\nBoth directories and files can be provided.\n\nVite will search for the root of the potential workspace and use it as default. A valid workspace met the following conditions, otherwise will fall back to the [project root](/guide/#index-html-and-project-root).\n\n- contains `workspaces` field in `package.json`\n- contains one of the following file\n  - `lerna.json`\n  - `pnpm-workspace.yaml`\n\nAccepts a path to specify the custom workspace root. Could be a absolute path or a path relative to [project root](/guide/#index-html-and-project-root). For example:\n\n```js\nexport default defineConfig({\n  server: {\n    fs: {\n      // Allow serving files from one level up to the project root\n      allow: ['..'],\n    },\n  },\n})\n```\n\nWhen `server.fs.allow` is specified, the auto workspace root detection will be disabled. To extend the original behavior, a utility `searchForWorkspaceRoot` is exposed:\n\n```js\nimport { defineConfig, searchForWorkspaceRoot } from 'vite'\n\nexport default defineConfig({\n  server: {\n    fs: {\n      allow: [\n        // search up for workspace root\n        searchForWorkspaceRoot(process.cwd()),\n        // your custom rules\n        '/path/to/custom/allow_directory',\n        '/path/to/custom/allow_file.demo',\n      ],\n    },\n  },\n})\n```\n\n## server.fs.deny\n\n- **Type:** `string[]`\n- **Default:** `['.env', '.env.*', '*.{crt,pem}', '**/.git/**']`\n\nBlocklist for sensitive files being restricted to be served by Vite dev server. This will have higher priority than [`server.fs.allow`](#server-fs-allow). [picomatch patterns](https://github.com/micromatch/picomatch#globbing-features) are supported.\n\n::: tip NOTE\n\nThis blocklist does not apply to [the public directory](/guide/assets.md#the-public-directory). All files in the public directory are served without any filtering, since they are copied directly to the output directory during build.\n\n:::\n\n## server.origin\n\n- **Type:** `string`\n\nDefines the origin of the generated asset URLs during development.\n\n```js\nexport default defineConfig({\n  server: {\n    origin: 'http://127.0.0.1:8080',\n  },\n})\n```\n\n## server.sourcemapIgnoreList\n\n- **Type:** `false | (sourcePath: string, sourcemapPath: string) => boolean`\n- **Default:** `(sourcePath) => sourcePath.includes('node_modules')`\n\nWhether or not to ignore source files in the server sourcemap, used to populate the [`x_google_ignoreList` source map extension](https://developer.chrome.com/articles/x-google-ignore-list/).\n\n`server.sourcemapIgnoreList` is the equivalent of [`build.rollupOptions.output.sourcemapIgnoreList`](https://rollupjs.org/configuration-options/#output-sourcemapignorelist) for the dev server. A difference between the two config options is that the rollup function is called with a relative path for `sourcePath` while `server.sourcemapIgnoreList` is called with an absolute path. During dev, most modules have the map and the source in the same folder, so the relative path for `sourcePath` is the file name itself. In these cases, absolute paths makes it convenient to be used instead.\n\nBy default, it excludes all paths containing `node_modules`. You can pass `false` to disable this behavior, or, for full control, a function that takes the source path and sourcemap path and returns whether to ignore the source path.\n\n```js\nexport default defineConfig({\n  server: {\n    // This is the default value, and will add all files with node_modules\n    // in their paths to the ignore list.\n    sourcemapIgnoreList(sourcePath, sourcemapPath) {\n      return sourcePath.includes('node_modules')\n    },\n  },\n})\n```\n\n::: tip Note\n[`server.sourcemapIgnoreList`](#server-sourcemapignorelist) and [`build.rollupOptions.output.sourcemapIgnoreList`](https://rollupjs.org/configuration-options/#output-sourcemapignorelist) need to be set independently. `server.sourcemapIgnoreList` is a server only config and doesn't get its default value from the defined rollup options.\n:::\n"
  },
  {
    "path": "docs/config/shared-options.md",
    "content": "# Shared Options\n\nUnless noted, the options in this section are applied to all dev, build, and preview.\n\n## root\n\n- **Type:** `string`\n- **Default:** `process.cwd()`\n\nProject root directory (where `index.html` is located). Can be an absolute path, or a path relative to the current working directory.\n\nSee [Project Root](/guide/#index-html-and-project-root) for more details.\n\n## base\n\n- **Type:** `string`\n- **Default:** `/`\n- **Related:** [`server.origin`](/config/server-options.md#server-origin)\n\nBase public path when served in development or production. Valid values include:\n\n- Absolute URL pathname, e.g. `/foo/`\n- Full URL, e.g. `https://bar.com/foo/` (The origin part won't be used in development so the value is the same as `/foo/`)\n- Empty string or `./` (for embedded deployment)\n\nSee [Public Base Path](/guide/build#public-base-path) for more details.\n\n## mode\n\n- **Type:** `string`\n- **Default:** `'development'` for serve, `'production'` for build\n\nSpecifying this in config will override the default mode for **both serve and build**. This value can also be overridden via the command line `--mode` option.\n\nSee [Env Variables and Modes](/guide/env-and-mode) for more details.\n\n## define\n\n- **Type:** `Record<string, any>`\n\nDefine global constant replacements. Entries will be defined as globals during dev and statically replaced during build.\n\nVite uses [Oxc's define feature](https://oxc.rs/docs/guide/usage/transformer/global-variable-replacement#define) to perform replacements, so value expressions must be a string that contains a JSON-serializable value (null, boolean, number, string, array, or object) or a single identifier. For non-string values, Vite will automatically convert it to a string with `JSON.stringify`.\n\n**Example:**\n\n```js\nexport default defineConfig({\n  define: {\n    __APP_VERSION__: JSON.stringify('v1.0.0'),\n    __API_URL__: 'window.__backend_api_url',\n  },\n})\n```\n\n::: tip NOTE\nFor TypeScript users, make sure to add the type declarations in the `vite-env.d.ts` file to get type checks and Intellisense.\n\nExample:\n\n```ts\n// vite-env.d.ts\ndeclare const __APP_VERSION__: string\n```\n\n:::\n\n## plugins\n\n- **Type:** `(Plugin | Plugin[] | Promise<Plugin | Plugin[]>)[]`\n\nArray of plugins to use. Falsy plugins are ignored and arrays of plugins are flattened. If a promise is returned, it would be resolved before running. See [Plugin API](/guide/api-plugin) for more details on Vite plugins.\n\n## publicDir\n\n- **Type:** `string | false`\n- **Default:** `\"public\"`\n\nDirectory to serve as plain static assets. Files in this directory are served at `/` during dev and copied to the root of `outDir` during build, and are always served or copied as-is without transform. The value can be either an absolute file system path or a path relative to project root.\n\nDefining `publicDir` as `false` disables this feature.\n\nSee [The `public` Directory](/guide/assets#the-public-directory) for more details.\n\n## cacheDir\n\n- **Type:** `string`\n- **Default:** `\"node_modules/.vite\"`\n\nDirectory to save cache files. Files in this directory are pre-bundled deps or some other cache files generated by vite, which can improve the performance. You can use `--force` flag or manually delete the directory to regenerate the cache files. The value can be either an absolute file system path or a path relative to project root. Default to `.vite` when no `package.json` is detected.\n\n## resolve.alias\n\n- **Type:**\n  `Record<string, string> | Array<{ find: string | RegExp, replacement: string }>`\n\nDefines aliases used to replace values in `import` or `require` statements. This works similar to [`@rollup/plugin-alias`](https://github.com/rollup/plugins/tree/master/packages/alias).\n\nThe order of the entries is important, in that the first defined rules are applied first.\n\nWhen aliasing to file system paths, always use absolute paths. Relative alias values will be used as-is and will not be resolved into file system paths.\n\nMore advanced custom resolution can be achieved through [plugins](/guide/api-plugin).\n\n::: warning Using with SSR\nIf you have configured aliases for [SSR externalized dependencies](/guide/ssr.md#ssr-externals), you may want to alias the actual `node_modules` packages. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.io/aliases/) support aliasing via the `npm:` prefix.\n:::\n\n### Object Format (`Record<string, string>`)\n\nThe Object format allows specifying aliases as a key, and the corresponding value as the actual import value. For example:\n\n```js\nresolve: {\n  alias: {\n    utils: '../../../utils',\n    'batman-1.0.0': './joker-1.5.0'\n  }\n}\n```\n\n### Array Format (`Array<{ find: string | RegExp, replacement: string }>`)\n\nThe Array format allows specifying aliases as objects, which can be useful for complex key/value pairs.\n\n```js\nresolve: {\n  alias: [\n    { find: 'utils', replacement: '../../../utils' },\n    { find: 'batman-1.0.0', replacement: './joker-1.5.0' },\n  ]\n}\n```\n\nWhen `find` is a regular expression, the `replacement` can use [replacement patterns](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement), such as `$1`. For example, to remove extensions with another, a pattern like the following might be used:\n\n```js\n{ find:/^(.*)\\.js$/, replacement: '$1.alias' }\n```\n\n## resolve.dedupe\n\n- **Type:** `string[]`\n\nIf you have duplicated copies of the same dependency in your app (likely due to hoisting or linked packages in monorepos), use this option to force Vite to always resolve listed dependencies to the same copy (from project root).\n\n:::warning SSR + ESM\nFor SSR builds, deduplication does not work for ESM build outputs configured from `build.rollupOptions.output`. A workaround is to use CJS build outputs until ESM has better plugin support for module loading.\n:::\n\n## resolve.conditions <NonInheritBadge />\n\n- **Type:** `string[]`\n- **Default:** `['module', 'browser', 'development|production']` (`defaultClientConditions`)\n\nAdditional allowed conditions when resolving [Conditional Exports](https://nodejs.org/api/packages.html#packages_conditional_exports) from a package.\n\nA package with conditional exports may have the following `exports` field in its `package.json`:\n\n```json\n{\n  \"exports\": {\n    \".\": {\n      \"import\": \"./index.mjs\",\n      \"require\": \"./index.js\"\n    }\n  }\n}\n```\n\nHere, `import` and `require` are \"conditions\". Conditions can be nested and should be specified from most specific to least specific.\n\n`development|production` is a special value that is replaced with `production` or `development` depending on the value of `process.env.NODE_ENV`. It is replaced with `production` when `process.env.NODE_ENV === 'production'` and `development` otherwise.\n\nNote that `import`, `require`, `default` conditions are always applied if the requirements are met.\n\nIn addition, the `style` condition is applied when resolving style imports, e.g. `@import 'my-library'`. For some CSS pre-processors, their corresponding conditions are also applied, i.e. `sass` for Sass and `less` for Less.\n\n## resolve.mainFields <NonInheritBadge />\n\n- **Type:** `string[]`\n- **Default:** `['browser', 'module', 'jsnext:main', 'jsnext']` (`defaultClientMainFields`)\n\nList of fields in `package.json` to try when resolving a package's entry point. Note this takes lower precedence than conditional exports resolved from the `exports` field: if an entry point is successfully resolved from `exports`, the main field will be ignored.\n\n## resolve.extensions\n\n- **Type:** `string[]`\n- **Default:** `['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']`\n\nList of file extensions to try for imports that omit extensions. Note it is **NOT** recommended to omit extensions for custom import types (e.g. `.vue`) since it can interfere with IDE and type support.\n\n## resolve.preserveSymlinks\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nEnabling this setting causes vite to determine file identity by the original file path (i.e. the path without following symlinks) instead of the real file path (i.e. the path after following symlinks).\n\n- **Related:** [esbuild#preserve-symlinks](https://esbuild.github.io/api/#preserve-symlinks), [webpack#resolve.symlinks\n  ](https://webpack.js.org/configuration/resolve/#resolvesymlinks)\n\n## resolve.tsconfigPaths\n\n- **Type:** `boolean`\n- **Default:** `false`\n\nEnables the tsconfig paths resolution feature. `paths` option in `tsconfig.json` will be used to resolve imports. See [Features](/guide/features.md#paths) for more details.\n\n## html.cspNonce\n\n- **Type:** `string`\n- **Related:** [Content Security Policy (CSP)](/guide/features#content-security-policy-csp)\n\nA nonce value placeholder that will be used when generating script / style tags. Setting this value will also generate a meta tag with nonce value.\n\n## css.modules\n\n- **Type:**\n  ```ts\n  interface CSSModulesOptions {\n    getJSON?: (\n      cssFileName: string,\n      json: Record<string, string>,\n      outputFileName: string,\n    ) => void\n    scopeBehaviour?: 'global' | 'local'\n    globalModulePaths?: RegExp[]\n    exportGlobals?: boolean\n    generateScopedName?:\n      | string\n      | ((name: string, filename: string, css: string) => string)\n    hashPrefix?: string\n    /**\n     * default: undefined\n     */\n    localsConvention?:\n      | 'camelCase'\n      | 'camelCaseOnly'\n      | 'dashes'\n      | 'dashesOnly'\n      | ((\n          originalClassName: string,\n          generatedClassName: string,\n          inputFile: string,\n        ) => string)\n  }\n  ```\n\nConfigure CSS modules behavior. The options are passed on to [postcss-modules](https://github.com/css-modules/postcss-modules).\n\nThis option doesn't have any effect when using [Lightning CSS](../guide/features.md#lightning-css). If enabled, [`css.lightningcss.cssModules`](https://lightningcss.dev/css-modules.html) should be used instead.\n\n## css.postcss\n\n- **Type:** `string | (postcss.ProcessOptions & { plugins?: postcss.AcceptedPlugin[] })`\n\nInline PostCSS config or a custom directory to search PostCSS config from (default is project root).\n\nFor inline PostCSS config, it expects the same format as `postcss.config.js`. But for `plugins` property, only [array format](https://github.com/postcss/postcss-load-config/blob/main/README.md#array) can be used.\n\nThe search is done using [postcss-load-config](https://github.com/postcss/postcss-load-config) and only the supported config file names are loaded. Config files outside the workspace root (or the [project root](/guide/#index-html-and-project-root) if no workspace is found) are not searched by default. You can specify a custom path outside of the root to load the specific config file instead if needed.\n\nNote if an inline config is provided, Vite will not search for other PostCSS config sources.\n\n## css.preprocessorOptions\n\n- **Type:** `Record<string, object>`\n\nSpecify options to pass to CSS pre-processors. The file extensions are used as keys for the options. The supported options for each preprocessor can be found in their respective documentation:\n\n- `sass`/`scss`:\n  - Uses `sass-embedded` if installed, otherwise uses `sass`. For the best performance, it's recommended to install the `sass-embedded` package.\n  - [Options](https://sass-lang.com/documentation/js-api/interfaces/stringoptions/)\n- `less`: [Options](https://lesscss.org/usage/#less-options).\n- `styl`/`stylus`: Only [`define`](https://stylus-lang.com/docs/js.html#define-name-node) is supported, which can be passed as an object.\n\n**Example:**\n\n```js\nexport default defineConfig({\n  css: {\n    preprocessorOptions: {\n      less: {\n        math: 'parens-division',\n      },\n      styl: {\n        define: {\n          $specialColor: new stylus.nodes.RGBA(51, 197, 255, 1),\n        },\n      },\n      scss: {\n        importers: [\n          // ...\n        ],\n      },\n    },\n  },\n})\n```\n\n### css.preprocessorOptions[extension].additionalData\n\n- **Type:** `string | ((source: string, filename: string) => (string | { content: string; map?: SourceMap }))`\n\nThis option can be used to inject extra code for each style content. Note that if you include actual styles and not just variables, those styles will be duplicated in the final bundle.\n\n**Example:**\n\n```js\nexport default defineConfig({\n  css: {\n    preprocessorOptions: {\n      scss: {\n        additionalData: `$injectedColor: orange;`,\n      },\n    },\n  },\n})\n```\n\n::: tip Importing files\nSince the same code is prepended to files in different directories, relative paths won't resolve correctly. Use absolute paths or [aliases](#resolve-alias) instead.\n:::\n\n## css.preprocessorMaxWorkers\n\n- **Type:** `number | true`\n- **Default:** `true`\n\nSpecifies the maximum number of threads CSS preprocessors can use. `true` means up to the number of CPUs minus 1. When set to `0`, Vite will not create any workers and will run the preprocessors in the main thread.\n\nDepending on the preprocessor options, Vite may run the preprocessors on the main thread even if this option is not set to `0`.\n\n## css.devSourcemap\n\n- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/13845)\n- **Type:** `boolean`\n- **Default:** `false`\n\nWhether to enable sourcemaps during dev.\n\n## css.transformer\n\n- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/13835)\n- **Type:** `'postcss' | 'lightningcss'`\n- **Default:** `'postcss'`\n\nSelects the engine used for CSS processing. Check out [Lightning CSS](../guide/features.md#lightning-css) for more information.\n\n::: info Duplicate `@import`s\nNote that postcss (postcss-import) has a different behavior with duplicated `@import` from browsers. See [postcss/postcss-import#462](https://github.com/postcss/postcss-import/issues/462).\n:::\n\n## css.lightningcss\n\n- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/13835)\n- **Type:**\n\n```js\nimport type {\n  CSSModulesConfig,\n  Drafts,\n  Features,\n  NonStandard,\n  PseudoClasses,\n  Targets,\n} from 'lightningcss'\n```\n\n```js\n{\n  targets?: Targets\n  include?: Features\n  exclude?: Features\n  drafts?: Drafts\n  nonStandard?: NonStandard\n  pseudoClasses?: PseudoClasses\n  unusedSymbols?: string[]\n  cssModules?: CSSModulesConfig,\n  // ...\n}\n```\n\nConfigures Lightning CSS. Full transform options can be found in [the Lightning CSS repo](https://github.com/parcel-bundler/lightningcss/blob/master/node/index.d.ts).\n\n## json.namedExports\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nWhether to support named imports from `.json` files.\n\n## json.stringify\n\n- **Type:** `boolean | 'auto'`\n- **Default:** `'auto'`\n\nIf set to `true`, imported JSON will be transformed into `export default JSON.parse(\"...\")` which is significantly more performant than Object literals, especially when the JSON file is large.\n\nIf set to `'auto'`, the data will be stringified only if [the data is bigger than 10kB](https://v8.dev/blog/cost-of-javascript-2019#json:~:text=A%20good%20rule%20of%20thumb%20is%20to%20apply%20this%20technique%20for%20objects%20of%2010%20kB%20or%20larger).\n\n## oxc\n\n- **Type:** `OxcOptions | false`\n\n`OxcOptions` extends [Oxc Transformer's options](https://oxc.rs/docs/guide/usage/transformer). The most common use case is customizing JSX:\n\n```js\nexport default defineConfig({\n  oxc: {\n    jsx: {\n      runtime: 'classic',\n      pragma: 'h',\n      pragmaFrag: 'Fragment',\n    },\n  },\n})\n```\n\nBy default, transformation by Oxc is applied to `ts`, `jsx` and `tsx` files. You can customize this with `oxc.include` and `oxc.exclude`, which can be a regex, a [picomatch](https://github.com/micromatch/picomatch#globbing-features) pattern, or an array of either.\n\nIn addition, you can also use `oxc.jsxInject` to automatically inject JSX helper imports for every file transformed by Oxc:\n\n```js\nexport default defineConfig({\n  oxc: {\n    jsxInject: `import React from 'react'`,\n  },\n})\n```\n\nSet to `false` to disable transformation by Oxc.\n\n## esbuild\n\n- **Type:** `ESBuildOptions | false`\n- **Deprecated**\n\nThis option is converted to `oxc` option internally. Use `oxc` option instead.\n\n## assetsInclude\n\n- **Type:** `string | RegExp | (string | RegExp)[]`\n- **Related:** [Static Asset Handling](/guide/assets)\n\nSpecify additional [picomatch patterns](https://github.com/micromatch/picomatch#globbing-features) to be treated as static assets so that:\n\n- They will be excluded from the plugin transform pipeline when referenced from HTML or directly requested over `fetch` or XHR.\n\n- Importing them from JS will return their resolved URL string (this can be overwritten if you have a `enforce: 'pre'` plugin to handle the asset type differently).\n\nThe built-in asset type list can be found [here](https://github.com/vitejs/vite/blob/main/packages/vite/src/node/constants.ts).\n\n**Example:**\n\n```js\nexport default defineConfig({\n  assetsInclude: ['**/*.gltf'],\n})\n```\n\n## logLevel\n\n- **Type:** `'info' | 'warn' | 'error' | 'silent'`\n\nAdjust console output verbosity. Default is `'info'`.\n\n## customLogger\n\n- **Type:**\n  ```ts\n  interface Logger {\n    info(msg: string, options?: LogOptions): void\n    warn(msg: string, options?: LogOptions): void\n    warnOnce(msg: string, options?: LogOptions): void\n    error(msg: string, options?: LogErrorOptions): void\n    clearScreen(type: LogType): void\n    hasErrorLogged(error: Error | RollupError): boolean\n    hasWarned: boolean\n  }\n  ```\n\nUse a custom logger to log messages. You can use Vite's `createLogger` API to get the default logger and customize it to, for example, change the message or filter out certain warnings.\n\n```ts twoslash\nimport { createLogger, defineConfig } from 'vite'\n\nconst logger = createLogger()\nconst loggerWarn = logger.warn\n\nlogger.warn = (msg, options) => {\n  // Ignore empty CSS files warning\n  if (msg.includes('vite:css') && msg.includes(' is empty')) return\n  loggerWarn(msg, options)\n}\n\nexport default defineConfig({\n  customLogger: logger,\n})\n```\n\n## clearScreen\n\n- **Type:** `boolean`\n- **Default:** `true`\n\nSet to `false` to prevent Vite from clearing the terminal screen when logging certain messages. Via command line, use `--clearScreen false`.\n\n## envDir\n\n- **Type:** `string | false`\n- **Default:** `root`\n\nThe directory from which `.env` files are loaded. Can be an absolute path, or a path relative to the project root. `false` will disable the `.env` file loading.\n\nSee [here](/guide/env-and-mode#env-files) for more about environment files.\n\n## envPrefix\n\n- **Type:** `string | string[]`\n- **Default:** `VITE_`\n\nEnv variables starting with `envPrefix` will be exposed to your client source code via `import.meta.env`.\n\n:::warning SECURITY NOTES\n`envPrefix` should not be set as `''`, which will expose all your env variables and cause unexpected leaking of sensitive information. Vite will throw an error when detecting `''`.\n\nIf you would like to expose an unprefixed variable, you can use [define](#define) to expose it:\n\n```js\ndefine: {\n  'import.meta.env.ENV_VARIABLE': JSON.stringify(process.env.ENV_VARIABLE)\n}\n```\n\n:::\n\n## appType\n\n- **Type:** `'spa' | 'mpa' | 'custom'`\n- **Default:** `'spa'`\n\nWhether your application is a Single Page Application (SPA), a [Multi Page Application (MPA)](../guide/build#multi-page-app), or Custom Application (SSR and frameworks with custom HTML handling):\n\n- `'spa'`: include HTML middlewares and use SPA fallback. Configure [sirv](https://github.com/lukeed/sirv) with `single: true` in preview\n- `'mpa'`: include HTML middlewares\n- `'custom'`: don't include HTML middlewares\n\nLearn more in Vite's [SSR guide](/guide/ssr#vite-cli). Related: [`server.middlewareMode`](./server-options#server-middlewaremode).\n\n## devtools\n\n- **Experimental:** [Give Feedback](https://github.com/vitejs/devtools/discussions)\n- **Type:** `boolean` | `DevToolsConfig`\n- **Default:** `false`\n\nEnable devtools integration for visualizing the internal state and build analysis.\nEnsure that `@vitejs/devtools` is installed as a dependency. This feature is currently supported only in build mode.\n\nSee [Vite DevTools](https://github.com/vitejs/devtools) for more details.\n\n## future\n\n- **Type:** `Record<string, 'warn' | undefined>`\n- **Related:** [Breaking Changes](/changes/)\n\nEnable future breaking changes to prepare for a smooth migration to the next major version of Vite. The list may be updated, added, or removed at any time as new features are developed.\n\nSee the [Breaking Changes](/changes/) page for details of the possible options.\n"
  },
  {
    "path": "docs/config/ssr-options.md",
    "content": "# SSR Options\n\nUnless noted, the options in this section are applied to both dev and build.\n\n## ssr.external\n\n- **Type:** `string[] | true`\n- **Related:** [SSR Externals](/guide/ssr#ssr-externals)\n\nExternalize the given dependencies and their transitive dependencies for SSR. By default, all dependencies are externalized except for linked dependencies (for HMR). If you prefer to externalize the linked dependency, you can pass its name to this option.\n\nIf `true`, all dependencies including linked dependencies are externalized.\n\nNote that the explicitly listed dependencies (using `string[]` type) will always take priority if they're also listed in `ssr.noExternal` (using any type).\n\n## ssr.noExternal\n\n- **Type:** `string | RegExp | (string | RegExp)[] | true`\n- **Related:** [SSR Externals](/guide/ssr#ssr-externals)\n\nPrevent listed dependencies from being externalized for SSR, which they will get bundled in build. By default, only linked dependencies are not externalized (for HMR). If you prefer to externalize the linked dependency, you can pass its name to the `ssr.external` option.\n\nIf `true`, no dependencies are externalized. However, dependencies explicitly listed in `ssr.external` (using `string[]` type) can take priority and still be externalized. If `ssr.target: 'node'` is set, Node.js built-ins will also be externalized by default.\n\nNote that if both `ssr.noExternal: true` and `ssr.external: true` are configured, `ssr.noExternal` takes priority and no dependencies are externalized.\n\n## ssr.target\n\n- **Type:** `'node' | 'webworker'`\n- **Default:** `node`\n\nBuild target for the SSR server.\n\n## ssr.resolve.conditions\n\n- **Type:** `string[]`\n- **Default:** `['module', 'node', 'development|production']` (`defaultServerConditions`) (`['module', 'browser', 'development|production']` (`defaultClientConditions`) for `ssr.target === 'webworker'`)\n- **Related:** [Resolve Conditions](./shared-options.md#resolve-conditions)\n\nThese conditions are used in the plugin pipeline, and only affect non-externalized dependencies during the SSR build. Use `ssr.resolve.externalConditions` to affect externalized imports.\n\n## ssr.resolve.externalConditions\n\n- **Type:** `string[]`\n- **Default:** `['node']`\n\nConditions that are used during ssr import (including `ssrLoadModule`) of externalized direct dependencies (external dependencies imported by Vite).\n\n:::tip\n\nWhen using this option, make sure to run Node with [`--conditions` flag](https://nodejs.org/docs/latest/api/cli.html#-c-condition---conditionscondition) with the same values in both dev and build to get a consistent behavior.\n\nFor example, when setting `['node', 'custom']`, you should run `NODE_OPTIONS='--conditions custom' vite` in dev and `NODE_OPTIONS=\"--conditions custom\" node ./dist/server.js` after build.\n\n:::\n\n## ssr.resolve.mainFields\n\n- **Type:** `string[]`\n- **Default:** `['module', 'jsnext:main', 'jsnext']`\n\nList of fields in `package.json` to try when resolving a package's entry point. Note this takes lower precedence than conditional exports resolved from the `exports` field: if an entry point is successfully resolved from `exports`, the main field will be ignored. This setting only affects non-externalized dependencies.\n"
  },
  {
    "path": "docs/config/worker-options.md",
    "content": "# Worker Options\n\nUnless noted, the options in this section are applied to all dev, build, and preview.\n\n## worker.format\n\n- **Type:** `'es' | 'iife'`\n- **Default:** `'iife'`\n\nOutput format for worker bundle.\n\n## worker.plugins\n\n- **Type:** [`() => (Plugin | Plugin[])[]`](./shared-options#plugins)\n\nVite plugins that apply to the worker bundles. Note that [config.plugins](./shared-options#plugins) only applies to workers in dev, it should be configured here instead for build.\nThe function should return new plugin instances as they are used in parallel rollup worker builds. As such, modifying `config.worker` options in the `config` hook will be ignored.\n\n## worker.rolldownOptions\n\n- **Type:** [`RolldownOptions`](https://rolldown.rs/reference/)\n\nRolldown options to build worker bundle.\n\n## worker.rollupOptions\n\n- **Type:** `RolldownOptions`\n- **Deprecated**\n\nThis option is an alias of `worker.rolldownOptions` option. Use `worker.rolldownOptions` option instead.\n"
  },
  {
    "path": "docs/guide/api-environment-frameworks.md",
    "content": "# Environment API for Frameworks\n\n:::info Release Candidate\nThe Environment API is generally in the release candidate phase. We'll maintain stability in the APIs between major releases to allow the ecosystem to experiment and build upon them. However, note that [some specific APIs](/changes/#considering) are still considered experimental.\n\nWe plan to stabilize these new APIs (with potential breaking changes) in a future major release once downstream projects have had time to experiment with the new features and validate them.\n\nResources:\n\n- [Feedback discussion](https://github.com/vitejs/vite/discussions/16358) where we are gathering feedback about the new APIs.\n- [Environment API PR](https://github.com/vitejs/vite/pull/16471) where the new APIs were implemented and reviewed.\n\nPlease share your feedback with us.\n:::\n\n## DevEnvironment Communication Levels\n\nSince environments may run in different runtimes, communication against the environment may have constraints depending on the runtime. To allow frameworks to write runtime agnostic code easily, the Environment API provides three kinds of communication levels.\n\n### `RunnableDevEnvironment`\n\n`RunnableDevEnvironment` is an environment that can communicate arbitrary values. The implicit `ssr` environment and other non-client environments use a `RunnableDevEnvironment` by default during dev. While this requires the runtime to be the same with the one the Vite server is running in, this works similarly with `ssrLoadModule` and allows frameworks to migrate and enable HMR for their SSR dev story. You can guard any runnable environment with an `isRunnableDevEnvironment` function.\n\n```ts\nexport class RunnableDevEnvironment extends DevEnvironment {\n  public readonly runner: ModuleRunner\n}\n\nclass ModuleRunner {\n  /**\n   * URL to execute.\n   * Accepts file path, server path, or id relative to the root.\n   * Returns an instantiated module (same as in ssrLoadModule)\n   */\n  public async import(url: string): Promise<Record<string, any>>\n  /**\n   * Other ModuleRunner methods...\n   */\n}\n\nif (isRunnableDevEnvironment(server.environments.ssr)) {\n  await server.environments.ssr.runner.import('/entry-point.js')\n}\n```\n\n:::warning\nThe `runner` is evaluated lazily only when it's accessed for the first time. Beware that Vite enables source map support when the `runner` is created by calling `process.setSourceMapsEnabled` or by overriding `Error.prepareStackTrace` if it's not available.\n:::\n\nGiven a Vite server configured in middleware mode as described by the [SSR setup guide](/guide/ssr#setting-up-the-dev-server), let's implement the SSR middleware using the environment API. Remember that it doesn't have to be called `ssr`, so we'll name it `server` in this example. Error handling is omitted.\n\n```js\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { createServer } from 'vite'\n\nconst viteServer = await createServer({\n  server: { middlewareMode: true },\n  appType: 'custom',\n  environments: {\n    server: {\n      // by default, modules are run in the same process as the vite server\n    },\n  },\n})\n\n// You might need to cast this to RunnableDevEnvironment in TypeScript or\n// use isRunnableDevEnvironment to guard the access to the runner\nconst serverEnvironment = viteServer.environments.server\n\napp.use('*', async (req, res, next) => {\n  const url = req.originalUrl\n\n  // 1. Read index.html\n  const indexHtmlPath = path.resolve(import.meta.dirname, 'index.html')\n  let template = fs.readFileSync(indexHtmlPath, 'utf-8')\n\n  // 2. Apply Vite HTML transforms. This injects the Vite HMR client,\n  //    and also applies HTML transforms from Vite plugins, e.g. global\n  //    preambles from @vitejs/plugin-react\n  template = await viteServer.transformIndexHtml(url, template)\n\n  // 3. Load the server entry. import(url) automatically transforms\n  //    ESM source code to be usable in Node.js! There is no bundling\n  //    required, and provides full HMR support.\n  const { render } = await serverEnvironment.runner.import(\n    '/src/entry-server.js',\n  )\n\n  // 4. render the app HTML. This assumes entry-server.js's exported\n  //     `render` function calls appropriate framework SSR APIs,\n  //    e.g. ReactDOMServer.renderToString()\n  const appHtml = await render(url)\n\n  // 5. Inject the app-rendered HTML into the template.\n  const html = template.replace(`<!--ssr-outlet-->`, appHtml)\n\n  // 6. Send the rendered HTML back.\n  res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n})\n```\n\nWhen using environments that support HMR (such as `RunnableDevEnvironment`), you should add `import.meta.hot.accept()` in your server entry file for optimal behavior. Without this, server file changes will invalidate the entire server module graph:\n\n```js\n// src/entry-server.js\nexport function render(...) { ... }\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n```\n\n### `FetchableDevEnvironment`\n\n:::info\n\nWe are looking for feedback on [the `FetchableDevEnvironment` proposal](https://github.com/vitejs/vite/discussions/18191).\n\n:::\n\n`FetchableDevEnvironment` is an environment that can communicate with its runtime via the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) interface. Since the `RunnableDevEnvironment` is only possible to implement in a limited set of runtimes, we recommend to use the `FetchableDevEnvironment` instead of the `RunnableDevEnvironment`.\n\nThis environment provides a standardized way of handling requests via the `handleRequest` method:\n\n```ts\nimport {\n  createServer,\n  createFetchableDevEnvironment,\n  isFetchableDevEnvironment,\n} from 'vite'\n\nconst server = await createServer({\n  server: { middlewareMode: true },\n  appType: 'custom',\n  environments: {\n    custom: {\n      dev: {\n        createEnvironment(name, config) {\n          return createFetchableDevEnvironment(name, config, {\n            handleRequest(request: Request): Promise<Response> | Response {\n              // handle Request and return a Response\n            },\n          })\n        },\n      },\n    },\n  },\n})\n\n// Any consumer of the environment API can now call `dispatchFetch`\nif (isFetchableDevEnvironment(server.environments.custom)) {\n  const response: Response = await server.environments.custom.dispatchFetch(\n    new Request('http://example.com/request-to-handle'),\n  )\n}\n```\n\n:::warning\nVite validates the input and output of the `dispatchFetch` method: the request must be an instance of the global `Request` class and the response must be the instance of the global `Response` class. Vite will throw a `TypeError` if this is not the case.\n\nNote that although the `FetchableDevEnvironment` is implemented as a class, it is considered an implementation detail by the Vite team and might change at any moment.\n:::\n\n### raw `DevEnvironment`\n\nIf the environment does not implement the `RunnableDevEnvironment` or `FetchableDevEnvironment` interfaces, you need to set up the communication manually.\n\nIf your code can run in the same runtime as the user modules (i.e., it does not rely on Node.js-specific APIs), you can use a virtual module. This approach eliminates the need to access the value from the code using Vite's APIs.\n\n```ts\n// code using the Vite's APIs\nimport { createServer } from 'vite'\n\nconst server = createServer({\n  plugins: [\n    // a plugin that handles `virtual:entrypoint`\n    {\n      name: 'virtual-module',\n      /* plugin implementation */\n    },\n  ],\n})\nconst ssrEnvironment = server.environment.ssr\nconst input = {}\n\n// use exposed functions by each environment factories that runs the code\n// check for each environment factories what they provide\nif (ssrEnvironment instanceof CustomDevEnvironment) {\n  ssrEnvironment.runEntrypoint('virtual:entrypoint')\n} else {\n  throw new Error(`Unsupported runtime for ${ssrEnvironment.name}`)\n}\n\n// -------------------------------------\n// virtual:entrypoint\nconst { createHandler } = await import('./entrypoint.js')\nconst handler = createHandler(input)\nconst response = handler(new Request('http://example.com/'))\n\n// -------------------------------------\n// ./entrypoint.js\nexport function createHandler(input) {\n  return function handler(req) {\n    return new Response('hello')\n  }\n}\n```\n\nFor example, to call `transformIndexHtml` on the user module, the following plugin can be used:\n\n```ts {13-21}\nfunction vitePluginVirtualIndexHtml(): Plugin {\n  let server: ViteDevServer | undefined\n  return {\n    name: vitePluginVirtualIndexHtml.name,\n    configureServer(server_) {\n      server = server_\n    },\n    resolveId(source) {\n      return source === 'virtual:index-html' ? '\\0' + source : undefined\n    },\n    async load(id) {\n      if (id === '\\0' + 'virtual:index-html') {\n        let html: string\n        if (server) {\n          this.addWatchFile('index.html')\n          html = fs.readFileSync('index.html', 'utf-8')\n          html = await server.transformIndexHtml('/', html)\n        } else {\n          html = fs.readFileSync('dist/client/index.html', 'utf-8')\n        }\n        return `export default ${JSON.stringify(html)}`\n      }\n      return\n    },\n  }\n}\n```\n\nIf your code requires Node.js APIs, you can use `hot.send` to communicate with the code that uses Vite's APIs from the user modules. However, be aware that this approach may not work the same way after the build process.\n\n```ts\n// code using the Vite's APIs\nimport { createServer } from 'vite'\n\nconst server = createServer({\n  plugins: [\n    // a plugin that handles `virtual:entrypoint`\n    {\n      name: 'virtual-module',\n      /* plugin implementation */\n    },\n  ],\n})\nconst ssrEnvironment = server.environment.ssr\nconst input = {}\n\n// use exposed functions by each environment factories that runs the code\n// check for each environment factories what they provide\nif (ssrEnvironment instanceof RunnableDevEnvironment) {\n  ssrEnvironment.runner.import('virtual:entrypoint')\n} else if (ssrEnvironment instanceof CustomDevEnvironment) {\n  ssrEnvironment.runEntrypoint('virtual:entrypoint')\n} else {\n  throw new Error(`Unsupported runtime for ${ssrEnvironment.name}`)\n}\n\nconst req = new Request('http://example.com/')\n\nconst uniqueId = 'a-unique-id'\nssrEnvironment.send('request', serialize({ req, uniqueId }))\nconst response = await new Promise((resolve) => {\n  ssrEnvironment.on('response', (data) => {\n    data = deserialize(data)\n    if (data.uniqueId === uniqueId) {\n      resolve(data.res)\n    }\n  })\n})\n\n// -------------------------------------\n// virtual:entrypoint\nconst { createHandler } = await import('./entrypoint.js')\nconst handler = createHandler(input)\n\nimport.meta.hot.on('request', (data) => {\n  const { req, uniqueId } = deserialize(data)\n  const res = handler(req)\n  import.meta.hot.send('response', serialize({ res: res, uniqueId }))\n})\n\nconst response = handler(new Request('http://example.com/'))\n\n// -------------------------------------\n// ./entrypoint.js\nexport function createHandler(input) {\n  return function handler(req) {\n    return new Response('hello')\n  }\n}\n```\n\n## Environments During Build\n\nIn the CLI, calling `vite build` and `vite build --ssr` will still build the client only and ssr only environments for backward compatibility.\n\nWhen `builder` option is not `undefined` (or when calling `vite build --app`), `vite build` will opt-in into building the entire app instead. This would later on become the default in a future major. A `ViteBuilder` instance will be created (build-time equivalent to a `ViteDevServer`) to build all configured environments for production. By default the build of environments is run in series respecting the order of the `environments` record. A framework or user can further configure how the environments are built using `builder.buildApp` option:\n\n```js [vite.config.js]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  builder: {\n    buildApp: async (builder) => {\n      const environments = Object.values(builder.environments)\n      await Promise.all(\n        environments.map((environment) => builder.build(environment)),\n      )\n    },\n  },\n})\n```\n\nPlugins can also define a `buildApp` hook. Order `'pre'` and `null` are executed before the configured `builder.buildApp`, and order `'post'` hooks are executed after it. `environment.isBuilt` can be used to check if an environment has already being build.\n\n## Environment Agnostic Code\n\nMost of the time, the current `environment` instance will be available as part of the context of the code being run so the need to access them through `server.environments` should be rare. For example, inside plugin hooks the environment is exposed as part of the `PluginContext`, so it can be accessed using `this.environment`. See [Environment API for Plugins](./api-environment-plugins.md) to learn about how to build environment aware plugins.\n"
  },
  {
    "path": "docs/guide/api-environment-instances.md",
    "content": "# Using `Environment` Instances\n\n:::info Release Candidate\nThe Environment API is generally in the release candidate phase. We'll maintain stability in the APIs between major releases to allow the ecosystem to experiment and build upon them. However, note that [some specific APIs](/changes/#considering) are still considered experimental.\n\nWe plan to stabilize these new APIs (with potential breaking changes) in a future major release once downstream projects have had time to experiment with the new features and validate them.\n\nResources:\n\n- [Feedback discussion](https://github.com/vitejs/vite/discussions/16358) where we are gathering feedback about the new APIs.\n- [Environment API PR](https://github.com/vitejs/vite/pull/16471) where the new APIs were implemented and reviewed.\n\nPlease share your feedback with us.\n:::\n\n## Accessing the Environments\n\nDuring dev, the available environments in a dev server can be accessed using `server.environments`:\n\n```js\n// create the server, or get it from the configureServer hook\nconst server = await createServer(/* options */)\n\nconst clientEnvironment = server.environments.client\nclientEnvironment.transformRequest(url)\nconsole.log(server.environments.ssr.moduleGraph)\n```\n\nYou can also access the current environment from plugins. See the [Environment API for Plugins](./api-environment-plugins.md#accessing-the-current-environment-in-hooks) for more details.\n\n## `DevEnvironment` class\n\nDuring dev, each environment is an instance of the `DevEnvironment` class:\n\n```ts\nclass DevEnvironment {\n  /**\n   * Unique identifier for the environment in a Vite server.\n   * By default Vite exposes 'client' and 'ssr' environments.\n   */\n  name: string\n  /**\n   * Communication channel to send and receive messages from the\n   * associated module runner in the target runtime.\n   */\n  hot: NormalizedHotChannel\n  /**\n   * Graph of module nodes, with the imported relationship between\n   * processed modules and the cached result of the processed code.\n   */\n  moduleGraph: EnvironmentModuleGraph\n  /**\n   * Resolved plugins for this environment, including the ones\n   * created using the per-environment `create` hook\n   */\n  plugins: Plugin[]\n  /**\n   * Allows to resolve, load, and transform code through the\n   * environment plugins pipeline\n   */\n  pluginContainer: EnvironmentPluginContainer\n  /**\n   * Resolved config options for this environment. Options at the server\n   * global scope are taken as defaults for all environments, and can\n   * be overridden (resolve conditions, external, optimizedDeps)\n   */\n  config: ResolvedConfig & ResolvedDevEnvironmentOptions\n\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    context: DevEnvironmentContext,\n  )\n\n  /**\n   * Resolve the URL to an id, load it, and process the code using the\n   * plugins pipeline. The module graph is also updated.\n   */\n  async transformRequest(url: string): Promise<TransformResult | null>\n\n  /**\n   * Register a request to be processed with low priority. This is useful\n   * to avoid waterfalls. The Vite server has information about the\n   * imported modules by other requests, so it can warmup the module graph\n   * so the modules are already processed when they are requested.\n   */\n  async warmupRequest(url: string): Promise<void>\n}\n```\n\nWith `DevEnvironmentContext` being:\n\n```ts\ninterface DevEnvironmentContext {\n  hot: boolean\n  transport?: HotChannel | WebSocketServer\n  options?: EnvironmentOptions\n  remoteRunner?: {\n    inlineSourceMap?: boolean\n  }\n  depsOptimizer?: DepsOptimizer\n}\n```\n\nand with `TransformResult` being:\n\n```ts\ninterface TransformResult {\n  code: string\n  map: SourceMap | { mappings: '' } | null\n  etag?: string\n  deps?: string[]\n  dynamicDeps?: string[]\n}\n```\n\nAn environment instance in the Vite server lets you process a URL using the `environment.transformRequest(url)` method. This function will use the plugin pipeline to resolve the `url` to a module `id`, load it (reading the file from the file system or through a plugin that implements a virtual module), and then transform the code. While transforming the module, imports and other metadata will be recorded in the environment module graph by creating or updating the corresponding module node. When processing is done, the transform result is also stored in the module.\n\n:::info transformRequest naming\nWe are using `transformRequest(url)` and `warmupRequest(url)` in the current version of this proposal so it is easier to discuss and understand for users used to Vite's current API. Before releasing, we can take the opportunity to review these names too. For example, it could be named `environment.processModule(url)` or `environment.loadModule(url)` taking a page from Rollup's `context.load(id)` in plugin hooks. For the moment, we think keeping the current names and delaying this discussion is better.\n:::\n\n## Separate Module Graphs\n\nEach environment has an isolated module graph. All module graphs have the same signature, so generic algorithms can be implemented to crawl or query the graph without depending on the environment. `hotUpdate` is a good example. When a file is modified, the module graph of each environment will be used to discover the affected modules and perform HMR for each environment independently.\n\n::: info\nVite v5 had a mixed Client and SSR module graph. Given an unprocessed or invalidated node, it isn't possible to know if it corresponds to the Client, SSR, or both environments. Module nodes have some properties prefixed, like `clientImportedModules` and `ssrImportedModules` (and `importedModules` that returns the union of both). `importers` contains all importers from both the Client and SSR environment for each module node. A module node also has `transformResult` and `ssrTransformResult`. A backward compatibility layer allows the ecosystem to migrate from the deprecated `server.moduleGraph`.\n:::\n\nEach module is represented by a `EnvironmentModuleNode` instance. Modules may be registered in the graph without yet being processed (`transformResult` would be `null` in that case). `importers` and `importedModules` are also updated after the module is processed.\n\n```ts\nclass EnvironmentModuleNode {\n  environment: string\n\n  url: string\n  id: string | null = null\n  file: string | null = null\n\n  type: 'js' | 'css'\n\n  importers = new Set<EnvironmentModuleNode>()\n  importedModules = new Set<EnvironmentModuleNode>()\n  importedBindings: Map<string, Set<string>> | null = null\n\n  info?: ModuleInfo\n  meta?: Record<string, any>\n  transformResult: TransformResult | null = null\n\n  acceptedHmrDeps = new Set<EnvironmentModuleNode>()\n  acceptedHmrExports: Set<string> | null = null\n  isSelfAccepting?: boolean\n  lastHMRTimestamp = 0\n  lastInvalidationTimestamp = 0\n}\n```\n\n`environment.moduleGraph` is an instance of `EnvironmentModuleGraph`:\n\n```ts\nexport class EnvironmentModuleGraph {\n  environment: string\n\n  urlToModuleMap = new Map<string, EnvironmentModuleNode>()\n  idToModuleMap = new Map<string, EnvironmentModuleNode>()\n  etagToModuleMap = new Map<string, EnvironmentModuleNode>()\n  fileToModulesMap = new Map<string, Set<EnvironmentModuleNode>>()\n\n  constructor(\n    environment: string,\n    resolveId: (url: string) => Promise<PartialResolvedId | null>,\n  )\n\n  async getModuleByUrl(\n    rawUrl: string,\n  ): Promise<EnvironmentModuleNode | undefined>\n\n  getModuleById(id: string): EnvironmentModuleNode | undefined\n\n  getModulesByFile(file: string): Set<EnvironmentModuleNode> | undefined\n\n  onFileChange(file: string): void\n\n  onFileDelete(file: string): void\n\n  invalidateModule(\n    mod: EnvironmentModuleNode,\n    seen: Set<EnvironmentModuleNode> = new Set(),\n    timestamp: number = monotonicDateNow(),\n    isHmr: boolean = false,\n  ): void\n\n  invalidateAll(): void\n\n  async ensureEntryFromUrl(\n    rawUrl: string,\n    setIsSelfAccepting = true,\n  ): Promise<EnvironmentModuleNode>\n\n  createFileOnlyEntry(file: string): EnvironmentModuleNode\n\n  async resolveUrl(url: string): Promise<ResolvedUrl>\n\n  updateModuleTransformResult(\n    mod: EnvironmentModuleNode,\n    result: TransformResult | null,\n  ): void\n\n  getModuleByEtag(etag: string): EnvironmentModuleNode | undefined\n}\n```\n"
  },
  {
    "path": "docs/guide/api-environment-plugins.md",
    "content": "# Environment API for Plugins\n\n:::info Release Candidate\nThe Environment API is generally in the release candidate phase. We'll maintain stability in the APIs between major releases to allow the ecosystem to experiment and build upon them. However, note that [some specific APIs](/changes/#considering) are still considered experimental.\n\nWe plan to stabilize these new APIs (with potential breaking changes) in a future major release once downstream projects have had time to experiment with the new features and validate them.\n\nResources:\n\n- [Feedback discussion](https://github.com/vitejs/vite/discussions/16358) where we are gathering feedback about the new APIs.\n- [Environment API PR](https://github.com/vitejs/vite/pull/16471) where the new APIs were implemented and reviewed.\n\nPlease share your feedback with us.\n:::\n\n## Accessing the Current Environment in Hooks\n\nGiven that there were only two Environments until Vite 6 (`client` and `ssr`), a `ssr` boolean was enough to identify the current environment in Vite APIs. Plugin Hooks received a `ssr` boolean in the last options parameter, and several APIs expected an optional last `ssr` parameter to properly associate modules to the correct environment (for example `server.moduleGraph.getModuleByUrl(url, { ssr })`).\n\nWith the advent of configurable environments, we now have a uniform way to access their options and instance in plugins. Plugin hooks now expose `this.environment` in their context, and APIs that previously expected a `ssr` boolean are now scoped to the proper environment (for example `environment.moduleGraph.getModuleByUrl(url)`).\n\nThe Vite server has a shared plugin pipeline, but when a module is processed it is always done in the context of a given environment. The `environment` instance is available in the plugin context.\n\nA plugin could use the `environment` instance to change how a module is processed depending on the configuration for the environment (which can be accessed using `environment.config`).\n\n```ts\n  transform(code, id) {\n    console.log(this.environment.config.resolve.conditions)\n  }\n```\n\n## Registering New Environments Using Hooks\n\nPlugins can add new environments in the `config` hook. For example, [RSC support](/plugins/#vitejs-plugin-rsc) uses an additional environment to have a separate module graph with the `react-server` condition:\n\n```ts\n  config(config: UserConfig) {\n    return {\n      environments: {\n        rsc: {\n          resolve: {\n            conditions: ['react-server', ...defaultServerConditions],\n          },\n        },\n      },\n    }\n  }\n```\n\nAn empty object is enough to register the environment, using default values from the root level environment config.\n\n## Configuring Environment Using Hooks\n\nWhile the `config` hook is running, the complete list of environments isn't yet known and the environments can be affected by both the default values from the root level environment config or explicitly through the `config.environments` record.\nPlugins should set default values using the `config` hook. To configure each environment, they can use the new `configEnvironment` hook. This hook is called for each environment with its partially resolved config including resolution of final defaults.\n\n```ts\n  configEnvironment(name: string, options: EnvironmentOptions) {\n    // add \"workerd\" condition to the rsc environment\n    if (name === 'rsc') {\n      return {\n        resolve: {\n          conditions: ['workerd'],\n        },\n      }\n    }\n  }\n```\n\n## The `hotUpdate` Hook\n\n- **Type:** `(this: { environment: DevEnvironment }, options: HotUpdateOptions) => Array<EnvironmentModuleNode> | void | Promise<Array<EnvironmentModuleNode> | void>`\n- **Kind:** `async`, `sequential`\n- **See also:** [HMR API](./api-hmr)\n\nThe `hotUpdate` hook allows plugins to perform custom HMR update handling for a given environment. When a file changes, the HMR algorithm is run for each environment in series according to the order in `server.environments`, so the `hotUpdate` hook will be called multiple times. The hook receives a context object with the following signature:\n\n```ts\ninterface HotUpdateOptions {\n  type: 'create' | 'update' | 'delete'\n  file: string\n  timestamp: number\n  modules: Array<EnvironmentModuleNode>\n  read: () => string | Promise<string>\n  server: ViteDevServer\n}\n```\n\n- `this.environment` is the module execution environment where a file update is currently being processed.\n\n- `modules` is an array of modules in this environment that are affected by the changed file. It's an array because a single file may map to multiple served modules (e.g. Vue SFCs).\n\n- `read` is an async read function that returns the content of the file. This is provided because, on some systems, the file change callback may fire too fast before the editor finishes updating the file, and direct `fs.readFile` will return empty content. The read function passed in normalizes this behavior.\n\nThe hook can choose to:\n\n- Filter and narrow down the affected module list so that the HMR is more accurate.\n\n- Return an empty array and perform a full reload:\n\n  ```js\n  hotUpdate({ modules, timestamp }) {\n    if (this.environment.name !== 'client')\n      return\n\n    // Invalidate modules manually\n    const invalidatedModules = new Set()\n    for (const mod of modules) {\n      this.environment.moduleGraph.invalidateModule(\n        mod,\n        invalidatedModules,\n        timestamp,\n        true\n      )\n    }\n    this.environment.hot.send({ type: 'full-reload' })\n    return []\n  }\n  ```\n\n- Return an empty array and perform complete custom HMR handling by sending custom events to the client:\n\n  ```js\n  hotUpdate() {\n    if (this.environment.name !== 'client')\n      return\n\n    this.environment.hot.send({\n      type: 'custom',\n      event: 'special-update',\n      data: {}\n    })\n    return []\n  }\n  ```\n\n  Client code should register the corresponding handler using the [HMR API](./api-hmr) (this could be injected by the same plugin's `transform` hook):\n\n  ```js\n  if (import.meta.hot) {\n    import.meta.hot.on('special-update', (data) => {\n      // perform custom update\n    })\n  }\n  ```\n\n## Per-environment State in Plugins\n\nGiven that the same plugin instance is used for different environments, the plugin state needs to be keyed with `this.environment`. This is the same pattern the ecosystem has already been using to keep state about modules using the `ssr` boolean as key to avoid mixing client and ssr modules state. A `Map<Environment, State>` can be used to keep the state for each environment separately. Note that for backward compatibility, `buildStart` and `buildEnd` are only called for the client environment without the `perEnvironmentStartEndDuringDev: true` flag. Same for `watchChange` and the `perEnvironmentWatchChangeDuringDev: true` flag.\n\n```js\nfunction PerEnvironmentCountTransformedModulesPlugin() {\n  const state = new Map<Environment, { count: number }>()\n  return {\n    name: 'count-transformed-modules',\n    perEnvironmentStartEndDuringDev: true,\n    buildStart() {\n      state.set(this.environment, { count: 0 })\n    },\n    transform(id) {\n      state.get(this.environment).count++\n    },\n    buildEnd() {\n      console.log(this.environment.name, state.get(this.environment).count)\n    }\n  }\n}\n```\n\n## Per-environment Plugins\n\nA plugin can define what are the environments it should apply to with the `applyToEnvironment` function.\n\n```js\nconst UnoCssPlugin = () => {\n  // shared global state\n  return {\n    buildStart() {\n      // init per-environment state with WeakMap<Environment,Data>\n      // using this.environment\n    },\n    configureServer() {\n      // use global hooks normally\n    },\n    applyToEnvironment(environment) {\n      // return true if this plugin should be active in this environment,\n      // or return a new plugin to replace it.\n      // if the hook is not used, the plugin is active in all environments\n    },\n    resolveId(id, importer) {\n      // only called for environments this plugin apply to\n    },\n  }\n}\n```\n\nIf a plugin isn't environment aware and has state that isn't keyed on the current environment, the `applyToEnvironment` hook allows to easily make it per-environment.\n\n```js\nimport { nonShareablePlugin } from 'non-shareable-plugin'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'per-environment-plugin',\n      applyToEnvironment(environment) {\n        return nonShareablePlugin({ outputName: environment.name })\n      },\n    },\n  ],\n})\n```\n\nVite exports a `perEnvironmentPlugin` helper to simplify these cases where no other hooks are required:\n\n```js\nimport { nonShareablePlugin } from 'non-shareable-plugin'\n\nexport default defineConfig({\n  plugins: [\n    perEnvironmentPlugin('per-environment-plugin', (environment) =>\n      nonShareablePlugin({ outputName: environment.name }),\n    ),\n  ],\n})\n```\n\nThe `applyToEnvironment` hook is called at config time, currently after `configResolved` due to projects in the ecosystem modifying the plugins in it. Environment plugins resolution may be moved before `configResolved` in the future.\n\n## Application-Plugin Communication\n\n`environment.hot` allows plugins to communicate with the code on the application side for a given environment. This is the equivalent of [the Client-server Communication feature](/guide/api-plugin#client-server-communication), but supports environments other than the client environment.\n\n:::warning Note\n\nNote that this feature is only available for environments that support HMR.\n\n:::\n\n### Managing the Application Instances\n\nBe aware that there might be multiple application instances running in the same environment. For example, if you have multiple tabs open in the browser, each tab is a separate application instance and has a separate connection to the server.\n\nWhen a new connection is established, a `vite:client:connect` event is emitted on the environment's `hot` instance. When the connection is closed, a `vite:client:disconnect` event is emitted.\n\nEach event handler receives the `NormalizedHotChannelClient` as the second argument. The client is an object with a `send` method that can be used to send messages to that specific application instance. The client reference is always the same for the same connection, so you can keep it to track the connection.\n\n### Example Usage\n\nThe plugin side:\n\n```js\nconfigureServer(server) {\n  server.environments.ssr.hot.on('my:greetings', (data, client) => {\n    // do something with the data,\n    // and optionally send a response to that application instance\n    client.send('my:foo:reply', `Hello from server! You said: ${data}`)\n  })\n\n  // broadcast a message to all application instances\n  server.environments.ssr.hot.send('my:foo', 'Hello from server!')\n}\n```\n\nThe application side is same with the Client-server Communication feature. You can use the `import.meta.hot` object to send messages to the plugin.\n\n## Environment in Build Hooks\n\nIn the same way as during dev, plugin hooks also receive the environment instance during build, replacing the `ssr` boolean.\nThis also works for `renderChunk`, `generateBundle`, and other build only hooks.\n\n## Shared Plugins During Build\n\nBefore Vite 6, the plugins pipelines worked in a different way during dev and build:\n\n- **During dev:** plugins are shared\n- **During Build:** plugins are isolated for each environment (in different processes: `vite build` then `vite build --ssr`).\n\nThis forced frameworks to share state between the `client` build and the `ssr` build through manifest files written to the file system. In Vite 6, we are now building all environments in a single process so the way the plugins pipeline and inter-environment communication can be aligned with dev.\n\nIn a future major, we could have complete alignment:\n\n- **During both dev and build:** plugins are shared, with [per-environment filtering](#per-environment-plugins)\n\nThere will also be a single `ResolvedConfig` instance shared during build, allowing for caching at entire app build process level in the same way as we have been doing with `WeakMap<ResolvedConfig, CachedData>` during dev.\n\nFor Vite 6, we need to do a smaller step to keep backward compatibility. Ecosystem plugins are currently using `config.build` instead of `environment.config.build` to access configuration, so we need to create a new `ResolvedConfig` per-environment by default. A project can opt-in into sharing the full config and plugins pipeline setting `builder.sharedConfigBuild` to `true`.\n\nThis option would only work of a small subset of projects at first, so plugin authors can opt-in for a particular plugin to be shared by setting the `sharedDuringBuild` flag to `true`. This allows for easily sharing state both for regular plugins:\n\n```js\nfunction myPlugin() {\n  // Share state among all environments in dev and build\n  const sharedState = ...\n  return {\n    name: 'shared-plugin',\n    transform(code, id) { ... },\n\n    // Opt-in into a single instance for all environments\n    sharedDuringBuild: true,\n  }\n}\n```\n"
  },
  {
    "path": "docs/guide/api-environment-runtimes.md",
    "content": "# Environment API for Runtimes\n\n:::info Release Candidate\nThe Environment API is generally in the release candidate phase. We'll maintain stability in the APIs between major releases to allow the ecosystem to experiment and build upon them. However, note that [some specific APIs](/changes/#considering) are still considered experimental.\n\nWe plan to stabilize these new APIs (with potential breaking changes) in a future major release once downstream projects have had time to experiment with the new features and validate them.\n\nResources:\n\n- [Feedback discussion](https://github.com/vitejs/vite/discussions/16358) where we are gathering feedback about the new APIs.\n- [Environment API PR](https://github.com/vitejs/vite/pull/16471) where the new APIs were implemented and reviewed.\n\nPlease share your feedback with us.\n:::\n\n## Environment Factories\n\nEnvironments factories are intended to be implemented by Environment providers like Cloudflare, and not by end users. Environment factories return a `EnvironmentOptions` for the most common case of using the target runtime for both dev and build environments. The default environment options can also be set so the user doesn't need to do it.\n\n```ts\nfunction createWorkerdEnvironment(\n  userConfig: EnvironmentOptions,\n): EnvironmentOptions {\n  return mergeConfig(\n    {\n      resolve: {\n        conditions: [\n          /*...*/\n        ],\n      },\n      dev: {\n        createEnvironment(name, config) {\n          return createWorkerdDevEnvironment(name, config, {\n            hot: true,\n            transport: customHotChannel(),\n          })\n        },\n      },\n      build: {\n        createEnvironment(name, config) {\n          return createWorkerdBuildEnvironment(name, config)\n        },\n      },\n    },\n    userConfig,\n  )\n}\n```\n\nThen the config file can be written as:\n\n```js\nimport { createWorkerdEnvironment } from 'vite-environment-workerd'\n\nexport default {\n  environments: {\n    ssr: createWorkerdEnvironment({\n      build: {\n        outDir: '/dist/ssr',\n      },\n    }),\n    rsc: createWorkerdEnvironment({\n      build: {\n        outDir: '/dist/rsc',\n      },\n    }),\n  },\n}\n```\n\nand frameworks can use an environment with the workerd runtime to do SSR using:\n\n```js\nconst ssrEnvironment = server.environments.ssr\n```\n\n## Creating a New Environment Factory\n\nA Vite dev server exposes two environments by default: a `client` environment and an `ssr` environment. The client environment is a browser environment by default, and the module runner is implemented by importing the virtual module `/@vite/client` to client apps. The SSR environment runs in the same Node runtime as the Vite server by default and allows application servers to be used to render requests during dev with full HMR support.\n\nThe transformed source code is called a module, and the relationships between the modules processed in each environment are kept in a module graph. The transformed code for these modules is sent to the runtimes associated with each environment to be executed. When a module is evaluated in the runtime, its imported modules will be requested triggering the processing of a section of the module graph.\n\nA Vite Module Runner allows running any code by processing it with Vite plugins first. It is different from `server.ssrLoadModule` because the runner implementation is decoupled from the server. This allows library and framework authors to implement their layer of communication between the Vite server and the runner. The browser communicates with its corresponding environment using the server WebSocket and through HTTP requests. The Node Module runner can directly do function calls to process modules as it is running in the same process. Other environments could run modules connecting to a JS runtime like workerd, or a Worker Thread as Vitest does.\n\n```dot\ndigraph module_runner {\n  rankdir=LR\n  node [shape=box style=\"rounded,filled\" fontname=\"Arial\" fontsize=11 margin=\"0.2,0.1\" fontcolor=\"${#3c3c43|#ffffff}\" color=\"${#c2c2c4|#3c3f44}\"]\n  edge [color=\"${#67676c|#98989f}\" fontname=\"Arial\" fontsize=10 fontcolor=\"${#67676c|#98989f}\"]\n  bgcolor=\"transparent\"\n  compound=true\n\n  subgraph cluster_server {\n    label=\"Vite Dev Server (Node.js)\" labeljust=l fontname=\"Arial\" fontsize=12\n    style=\"rounded,filled\" fillcolor=\"${#f6f6f7|#1a1a1f}\" color=\"${#c2c2c4|#3c3f44}\"\n    fontcolor=\"${#3c3c43|#ffffff}\"\n\n    subgraph cluster_env {\n      label=\"DevEnvironment\" labeljust=l fontname=\"Arial\" fontsize=11\n      style=\"rounded,filled\" fillcolor=\"${#f2ecfc|#2c273e}\" color=\"${#c2c2c4|#3c3f44}\"\n      fontcolor=\"${#3c3c43|#ffffff}\"\n\n      plugins [label=\"Plugin\\nPipeline\" fillcolor=\"${#e9eaff|#222541}\"]\n      mg [label=\"Module\\nGraph\" fillcolor=\"${#e9eaff|#222541}\"]\n      hot [label=\"HotChannel\" fillcolor=\"${#fcf4dc|#38301a}\"]\n\n      plugins -> mg [dir=both]\n      mg -> hot [style=invis]\n    }\n  }\n\n  subgraph cluster_runtime {\n    label=\"Target Runtime\" labeljust=l fontname=\"Arial\" fontsize=12\n    style=\"rounded,filled\" fillcolor=\"${#f0fdf4|#131b15}\" color=\"${#c2c2c4|#3c3f44}\"\n    fontcolor=\"${#3c3c43|#ffffff}\"\n\n    subgraph cluster_runner {\n      label=\"ModuleRunner\" labeljust=l fontname=\"Arial\" fontsize=11\n      style=\"rounded,filled\" fillcolor=\"${#def5ed|#15312d}\" color=\"${#c2c2c4|#3c3f44}\"\n      fontcolor=\"${#3c3c43|#ffffff}\"\n\n      evaluator [label=\"Module\\nEvaluator\" fillcolor=\"${#def5ed|#15312d}\"]\n      transport [label=\"Transport\" fillcolor=\"${#fcf4dc|#38301a}\"]\n    }\n  }\n\n  hot -> transport [label=\"HMR / Module\\nfetch & invoke\" dir=both style=bold color=\"${#6f42c1|#c8abfa}\"]\n}\n```\n\nOne of the goals of this feature is to provide a customizable API to process and run code. Users can create new environment factories using the exposed primitives.\n\n```ts\nimport { DevEnvironment, HotChannel } from 'vite'\n\nfunction createWorkerdDevEnvironment(\n  name: string,\n  config: ResolvedConfig,\n  context: DevEnvironmentContext\n) {\n  const connection = /* ... */\n  const transport: HotChannel = {\n    on: (listener) => { connection.on('message', listener) },\n    send: (data) => connection.send(data),\n  }\n\n  const workerdDevEnvironment = new DevEnvironment(name, config, {\n    options: {\n      resolve: { conditions: ['custom'] },\n      ...context.options,\n    },\n    hot: true,\n    transport,\n  })\n  return workerdDevEnvironment\n}\n```\n\nThere are [multiple communication levels for the `DevEnvironment`](/guide/api-environment-frameworks#devenvironment-communication-levels). To make it easier for frameworks to write runtime agnostic code, we recommend to implement the most flexible communication level possible.\n\n## `ModuleRunner`\n\nA module runner is instantiated in the target runtime. All APIs in the next section are imported from `vite/module-runner` unless stated otherwise. This export entry point is kept as lightweight as possible, only exporting the minimal needed to create module runners.\n\n**Type Signature:**\n\n```ts\nexport class ModuleRunner {\n  constructor(\n    public options: ModuleRunnerOptions,\n    public evaluator: ModuleEvaluator = new ESModulesEvaluator(),\n    private debug?: ModuleRunnerDebugger,\n  ) {}\n  /**\n   * URL to execute.\n   * Accepts file path, server path, or id relative to the root.\n   */\n  public async import<T = any>(url: string): Promise<T>\n  /**\n   * Clear all caches including HMR listeners.\n   */\n  public clearCache(): void\n  /**\n   * Clear all caches, remove all HMR listeners, reset sourcemap support.\n   * This method doesn't stop the HMR connection.\n   */\n  public async close(): Promise<void>\n  /**\n   * Returns `true` if the runner has been closed by calling `close()`.\n   */\n  public isClosed(): boolean\n}\n```\n\nThe module evaluator in `ModuleRunner` is responsible for executing the code. Vite exports `ESModulesEvaluator` out of the box, it uses `new AsyncFunction` to evaluate the code. You can provide your own implementation if your JavaScript runtime doesn't support unsafe evaluation.\n\nModule runner exposes `import` method. When Vite server triggers `full-reload` HMR event, all affected modules will be re-executed. Be aware that Module Runner doesn't update `exports` object when this happens (it overrides it), you would need to run `import` or get the module from `evaluatedModules` again if you rely on having the latest `exports` object.\n\n**Example Usage:**\n\n```js\nimport {\n  ModuleRunner,\n  ESModulesEvaluator,\n  createNodeImportMeta,\n} from 'vite/module-runner'\nimport { transport } from './rpc-implementation.js'\n\nconst moduleRunner = new ModuleRunner(\n  {\n    transport,\n    createImportMeta: createNodeImportMeta, // if the module runner runs in Node.js\n  },\n  new ESModulesEvaluator(),\n)\n\nawait moduleRunner.import('/src/entry-point.js')\n```\n\n## `ModuleRunnerOptions`\n\n```ts twoslash\nimport type {\n  InterceptorOptions as InterceptorOptionsRaw,\n  ModuleRunnerHmr as ModuleRunnerHmrRaw,\n  EvaluatedModules,\n} from 'vite/module-runner'\nimport type { Debug } from '@type-challenges/utils'\n\ntype InterceptorOptions = Debug<InterceptorOptionsRaw>\ntype ModuleRunnerHmr = Debug<ModuleRunnerHmrRaw>\n/** see below */\ntype ModuleRunnerTransport = unknown\n\n// ---cut---\ninterface ModuleRunnerOptions {\n  /**\n   * A set of methods to communicate with the server.\n   */\n  transport: ModuleRunnerTransport\n  /**\n   * Configure how source maps are resolved.\n   * Prefers `node` if `process.setSourceMapsEnabled` is available.\n   * Otherwise it will use `prepareStackTrace` by default which overrides\n   * `Error.prepareStackTrace` method.\n   * You can provide an object to configure how file contents and\n   * source maps are resolved for files that were not processed by Vite.\n   */\n  sourcemapInterceptor?:\n    | false\n    | 'node'\n    | 'prepareStackTrace'\n    | InterceptorOptions\n  /**\n   * Disable HMR or configure HMR options.\n   *\n   * @default true\n   */\n  hmr?: boolean | ModuleRunnerHmr\n  /**\n   * Custom module cache. If not provided, it creates a separate module\n   * cache for each module runner instance.\n   */\n  evaluatedModules?: EvaluatedModules\n}\n```\n\n## `ModuleEvaluator`\n\n**Type Signature:**\n\n```ts twoslash\nimport type { ModuleRunnerContext as ModuleRunnerContextRaw } from 'vite/module-runner'\nimport type { Debug } from '@type-challenges/utils'\n\ntype ModuleRunnerContext = Debug<ModuleRunnerContextRaw>\n\n// ---cut---\nexport interface ModuleEvaluator {\n  /**\n   * Number of prefixed lines in the transformed code.\n   */\n  startOffset?: number\n  /**\n   * Evaluate code that was transformed by Vite.\n   * @param context Function context\n   * @param code Transformed code\n   * @param id ID that was used to fetch the module\n   */\n  runInlinedModule(\n    context: ModuleRunnerContext,\n    code: string,\n    id: string,\n  ): Promise<any>\n  /**\n   * evaluate externalized module.\n   * @param file File URL to the external module\n   */\n  runExternalModule(file: string): Promise<any>\n}\n```\n\nVite exports `ESModulesEvaluator` that implements this interface by default. It uses `new AsyncFunction` to evaluate code, so if the code has inlined source map it should contain an [offset of 2 lines](https://tc39.es/ecma262/#sec-createdynamicfunction) to accommodate for new lines added. This is done automatically by the `ESModulesEvaluator`. Custom evaluators will not add additional lines.\n\n## `ModuleRunnerTransport`\n\n**Type Signature:**\n\n```ts twoslash\nimport type { ModuleRunnerTransportHandlers } from 'vite/module-runner'\n/** an object */\ntype HotPayload = unknown\n// ---cut---\ninterface ModuleRunnerTransport {\n  connect?(handlers: ModuleRunnerTransportHandlers): Promise<void> | void\n  disconnect?(): Promise<void> | void\n  send?(data: HotPayload): Promise<void> | void\n  invoke?(data: HotPayload): Promise<{ result: any } | { error: any }>\n  timeout?: number\n}\n```\n\nTransport object that communicates with the environment via an RPC or by directly calling the function. When `invoke` method is not implemented, the `send` method and `connect` method is required to be implemented. Vite will construct the `invoke` internally.\n\nYou need to couple it with the `HotChannel` instance on the server like in this example where module runner is created in the worker thread:\n\n::: code-group\n\n```js [worker.js]\nimport { parentPort } from 'node:worker_threads'\nimport { fileURLToPath } from 'node:url'\nimport {\n  ESModulesEvaluator,\n  ModuleRunner,\n  createNodeImportMeta,\n} from 'vite/module-runner'\n\n/** @type {import('vite/module-runner').ModuleRunnerTransport} */\nconst transport = {\n  connect({ onMessage, onDisconnection }) {\n    parentPort.on('message', onMessage)\n    parentPort.on('close', onDisconnection)\n  },\n  send(data) {\n    parentPort.postMessage(data)\n  },\n}\n\nconst runner = new ModuleRunner(\n  {\n    transport,\n    createImportMeta: createNodeImportMeta,\n  },\n  new ESModulesEvaluator(),\n)\n```\n\n```js [server.js]\nimport { BroadcastChannel } from 'node:worker_threads'\nimport { createServer, RemoteEnvironmentTransport, DevEnvironment } from 'vite'\n\nfunction createWorkerEnvironment(name, config, context) {\n  const worker = new Worker('./worker.js')\n  const handlerToWorkerListener = new WeakMap()\n  const client = {\n    send(payload: HotPayload) {\n      worker.postMessage(payload)\n    },\n  }\n\n  const workerHotChannel = {\n    send: (data) => worker.postMessage(data),\n    on: (event, handler) => {\n      // client is already connected\n      if (event === 'vite:client:connect') return\n      if (event === 'vite:client:disconnect') {\n        const listener = () => {\n          handler(undefined, client)\n        }\n        handlerToWorkerListener.set(handler, listener)\n        worker.on('exit', listener)\n        return\n      }\n\n      const listener = (value) => {\n        if (value.type === 'custom' && value.event === event) {\n          handler(value.data, client)\n        }\n      }\n      handlerToWorkerListener.set(handler, listener)\n      worker.on('message', listener)\n    },\n    off: (event, handler) => {\n      if (event === 'vite:client:connect') return\n      if (event === 'vite:client:disconnect') {\n        const listener = handlerToWorkerListener.get(handler)\n        if (listener) {\n          worker.off('exit', listener)\n          handlerToWorkerListener.delete(handler)\n        }\n        return\n      }\n\n      const listener = handlerToWorkerListener.get(handler)\n      if (listener) {\n        worker.off('message', listener)\n        handlerToWorkerListener.delete(handler)\n      }\n    },\n  }\n\n  return new DevEnvironment(name, config, {\n    transport: workerHotChannel,\n  })\n}\n\nawait createServer({\n  environments: {\n    worker: {\n      dev: {\n        createEnvironment: createWorkerEnvironment,\n      },\n    },\n  },\n})\n```\n\n:::\n\nMake sure to implement the `vite:client:connect` / `vite:client:disconnect` events in the `on` / `off` methods when those methods exist. `vite:client:connect` event should be emitted when the connection is established, and `vite:client:disconnect` event should be emitted when the connection is closed. The `HotChannelClient` object passed to the event handler must have the same reference for the same connection.\n\nA different example using an HTTP request to communicate between the runner and the server:\n\n```ts\nimport { ESModulesEvaluator, ModuleRunner } from 'vite/module-runner'\n\nexport const runner = new ModuleRunner(\n  {\n    transport: {\n      async invoke(data) {\n        const response = await fetch(`http://my-vite-server/invoke`, {\n          method: 'POST',\n          body: JSON.stringify(data),\n        })\n        return response.json()\n      },\n    },\n    hmr: false, // disable HMR as HMR requires transport.connect\n  },\n  new ESModulesEvaluator(),\n)\n\nawait runner.import('/entry.js')\n```\n\nIn this case, the `handleInvoke` method in the `NormalizedHotChannel` can be used:\n\n```ts\nconst customEnvironment = new DevEnvironment(name, config, context)\n\nserver.onRequest((request: Request) => {\n  const url = new URL(request.url)\n  if (url.pathname === '/invoke') {\n    const payload = (await request.json()) as HotPayload\n    const result = customEnvironment.hot.handleInvoke(payload)\n    return new Response(JSON.stringify(result))\n  }\n  return Response.error()\n})\n```\n\nBut note that for HMR support, `send` and `connect` methods are required. The `send` method is usually called when the custom event is triggered (like, `import.meta.hot.send(\"my-event\")`).\n\nVite exports `createServerHotChannel` from the main entry point to support HMR during Vite SSR.\n"
  },
  {
    "path": "docs/guide/api-environment.md",
    "content": "# Environment API\n\n:::info Release Candidate\nThe Environment API is generally in the release candidate phase. We'll maintain stability in the APIs between major releases to allow the ecosystem to experiment and build upon them. However, note that [some specific APIs](/changes/#considering) are still considered experimental.\n\nWe plan to stabilize these new APIs (with potential breaking changes) in a future major release once downstream projects have had time to experiment with the new features and validate them.\n\nResources:\n\n- [Feedback discussion](https://github.com/vitejs/vite/discussions/16358) where we are gathering feedback about the new APIs.\n- [Environment API PR](https://github.com/vitejs/vite/pull/16471) where the new APIs were implemented and reviewed.\n\nPlease share your feedback with us.\n:::\n\n## Formalizing Environments\n\nVite 6 formalizes the concept of Environments. Until Vite 5, there were two implicit Environments (`client`, and optionally `ssr`). The new Environment API allows users and framework authors to create as many environments as needed to map the way their apps work in production. This new capability required a big internal refactoring, but a lot of effort has been placed on backward compatibility. The initial goal of Vite 6 is to move the ecosystem to the new major as smoothly as possible, delaying the adoption of the APIs until enough users have migrated and frameworks and plugin authors have validated the new design.\n\n## Closing the Gap Between Build and Dev\n\nFor a simple SPA/MPA, no new APIs around environments are exposed to the config. Internally, Vite will apply the options to a `client` environment, but it's not necessary to know of this concept when configuring Vite. The config and behavior from Vite 5 should work seamlessly here.\n\nWhen we move to a typical server-side rendered (SSR) app, we'll have two environments:\n\n- `client`: runs the app in the browser.\n- `ssr`: runs the app in node (or other server runtimes) which renders pages before sending them to the browser.\n\nIn dev, Vite executes the server code in the same Node process as the Vite dev server, giving a close approximation to the production environment. However, it is also possible for servers to run in other JS runtimes, like [Cloudflare's workerd](https://github.com/cloudflare/workerd) which have different constraints. Modern apps may also run in more than two environments, e.g. a browser, a node server, and an edge server. Vite 5 didn't allow to properly represent these environments.\n\nVite 6 allows users to configure their app during build and dev to map all of its environments. During dev, a single Vite dev server can now be used to run code in multiple different environments concurrently. The app source code is still transformed by Vite dev server. On top of the shared HTTP server, middlewares, resolved config, and plugins pipeline, the Vite dev server now has a set of independent dev environments. Each of them is configured to match the production environment as closely as possible, and is connected to a dev runtime where the code is executed (for workerd, the server code can now run in miniflare locally). In the client, the browser imports and executes the code. In other environments, a module runner fetches and evaluates the transformed code.\n\n![Vite Environments](../images/vite-environments.svg)\n\n## Environments Configuration\n\nFor an SPA/MPA, the configuration will look similar to Vite 5. Internally these options are used to configure the `client` environment.\n\n```js\nexport default defineConfig({\n  build: {\n    sourcemap: false,\n  },\n  optimizeDeps: {\n    include: ['lib'],\n  },\n})\n```\n\nThis is important because we'd like to keep Vite approachable and avoid exposing new concepts until they are needed.\n\nIf the app is composed of several environments, then these environments can be configured explicitly with the `environments` config option.\n\n```js\nexport default {\n  build: {\n    sourcemap: false,\n  },\n  optimizeDeps: {\n    include: ['lib'],\n  },\n  environments: {\n    server: {},\n    edge: {\n      resolve: {\n        noExternal: true,\n      },\n    },\n  },\n}\n```\n\nWhen not explicitly documented, environment inherits the configured top-level config options (for example, the new `server` and `edge` environments will inherit the `build.sourcemap: false` option). A small number of top-level options, like `optimizeDeps`, only apply to the `client` environment, as they don't work well when applied as a default to server environments. Those options have <NonInheritBadge /> badge in [the reference](/config/). The `client` environment can also be configured explicitly through `environments.client`, but we recommend to do it with the top-level options so the client config remains unchanged when adding new environments.\n\nThe `EnvironmentOptions` interface exposes all the per-environment options. There are environment options that apply to both `build` and `dev`, like `resolve`. And there are `DevEnvironmentOptions` and `BuildEnvironmentOptions` for dev and build specific options (like `dev.warmup` or `build.outDir`). Some options like `optimizeDeps` only applies to dev, but is kept as top level instead of nested in `dev` for backward compatibility.\n\n```ts\ninterface EnvironmentOptions {\n  define?: Record<string, any>\n  resolve?: EnvironmentResolveOptions\n  optimizeDeps: DepOptimizationOptions\n  consumer?: 'client' | 'server'\n  dev: DevOptions\n  build: BuildOptions\n}\n```\n\nThe `UserConfig` interface extends from the `EnvironmentOptions` interface, allowing to configure the client and defaults for other environments, configured through the `environments` option. The `client` and a server environment named `ssr` are always present during dev. This allows backward compatibility with `server.ssrLoadModule(url)` and `server.moduleGraph`. During build, the `client` environment is always present, and the `ssr` environment is only present if it is explicitly configured (using `environments.ssr` or for backward compatibility `build.ssr`). An app doesn't need to use the `ssr` name for its SSR environment, it could name it `server` for example.\n\n```ts\ninterface UserConfig extends EnvironmentOptions {\n  environments: Record<string, EnvironmentOptions>\n  // other options\n}\n```\n\nNote that the `ssr` top-level property is going to be deprecated once the Environment API is stable. This option has the same role as `environments`, but for the default `ssr` environment and only allowed configuring of a small set of options.\n\n## Custom Environment Instances\n\nLow level configuration APIs are available so runtime providers can provide environments with proper defaults for their runtimes. These environments can also spawn other processes or threads to run the modules during dev in a closer runtime to the production environment.\n\nFor example, the [Cloudflare Vite plugin](https://developers.cloudflare.com/workers/vite-plugin/) uses the Environment API to run code in the Cloudflare Workers runtime (`workerd`) during development.\n\n```js\nimport { customEnvironment } from 'vite-environment-provider'\n\nexport default {\n  build: {\n    outDir: '/dist/client',\n  },\n  environments: {\n    ssr: customEnvironment({\n      build: {\n        outDir: '/dist/ssr',\n      },\n    }),\n  },\n}\n```\n\n## Backward Compatibility\n\nThe current Vite server API is not yet deprecated and is backward compatible with Vite 5.\n\nThe `server.moduleGraph` returns a mixed view of the client and ssr module graphs. Backward compatible mixed module nodes will be returned from all its methods. The same scheme is used for the module nodes passed to `handleHotUpdate`.\n\nWe don't recommend switching to Environment API yet. We are aiming for a good portion of the user base to adopt Vite 6 before so plugins don't need to maintain two versions. Checkout the future breaking changes section for information on future deprecations and upgrade path:\n\n- [`this.environment` in Hooks](/changes/this-environment-in-hooks)\n- [HMR `hotUpdate` Plugin Hook](/changes/hotupdate-hook)\n- [Move to Per-environment APIs](/changes/per-environment-apis)\n- [SSR Using `ModuleRunner` API](/changes/ssr-using-modulerunner)\n- [Shared Plugins During Build](/changes/shared-plugins-during-build)\n\n## Target Users\n\nThis guide provides the basic concepts about environments for end users.\n\nPlugin authors have a more consistent API available to interact with the current environment configuration. If you're building on top of Vite, the [Environment API Plugins Guide](./api-environment-plugins.md) guide describes the way extended plugin APIs available to support multiple custom environments.\n\nFrameworks could decide to expose environments at different levels. If you're a framework author, continue reading the [Environment API Frameworks Guide](./api-environment-frameworks) to learn about the Environment API programmatic side.\n\nFor Runtime providers, the [Environment API Runtimes Guide](./api-environment-runtimes.md) explains how to offer custom environments to be consumed by frameworks and users.\n"
  },
  {
    "path": "docs/guide/api-hmr.md",
    "content": "# HMR API\n\n:::tip Note\nThis is the client HMR API. For handling HMR update in plugins, see [handleHotUpdate](./api-plugin#handlehotupdate).\n\nThe manual HMR API is primarily intended for framework and tooling authors. As an end user, HMR is likely already handled for you in the framework specific starter templates.\n:::\n\nVite exposes its manual HMR API via the special `import.meta.hot` object:\n\n```ts twoslash\nimport type { ModuleNamespace } from 'vite/types/hot.d.ts'\nimport type {\n  CustomEventName,\n  InferCustomEventPayload,\n} from 'vite/types/customEvent.d.ts'\n\n// ---cut---\ninterface ImportMeta {\n  readonly hot?: ViteHotContext\n}\n\ninterface ViteHotContext {\n  readonly data: any\n\n  accept(): void\n  accept(cb: (mod: ModuleNamespace | undefined) => void): void\n  accept(dep: string, cb: (mod: ModuleNamespace | undefined) => void): void\n  accept(\n    deps: readonly string[],\n    cb: (mods: Array<ModuleNamespace | undefined>) => void,\n  ): void\n\n  dispose(cb: (data: any) => void): void\n  prune(cb: (data: any) => void): void\n  invalidate(message?: string): void\n\n  on<T extends CustomEventName>(\n    event: T,\n    cb: (payload: InferCustomEventPayload<T>) => void,\n  ): void\n  off<T extends CustomEventName>(\n    event: T,\n    cb: (payload: InferCustomEventPayload<T>) => void,\n  ): void\n  send<T extends CustomEventName>(\n    event: T,\n    data?: InferCustomEventPayload<T>,\n  ): void\n}\n```\n\n## Required Conditional Guard\n\nFirst of all, make sure to guard all HMR API usage with a conditional block so that the code can be tree-shaken in production:\n\n```js\nif (import.meta.hot) {\n  // HMR code\n}\n```\n\n## IntelliSense for TypeScript\n\nVite provides type definitions for `import.meta.hot` in [`vite/client.d.ts`](https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts). You can add \"vite/client\" in the `tsconfig.json` so TypeScript picks up the type definitions:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"types\": [\"vite/client\"]\n  }\n}\n```\n\n## `hot.accept(cb)`\n\nFor a module to self-accept, use `import.meta.hot.accept` with a callback which receives the updated module:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nexport const count = 1\n\nif (import.meta.hot) {\n  import.meta.hot.accept((newModule) => {\n    if (newModule) {\n      // newModule is undefined when SyntaxError happened\n      console.log('updated: count is now ', newModule.count)\n    }\n  })\n}\n```\n\nA module that \"accepts\" hot updates is considered an **HMR boundary**.\n\n```dot\ndigraph hmr_boundary {\n  rankdir=RL\n  ranksep=0.3\n  node [shape=box style=\"rounded,filled\" fontname=\"Arial\" fontsize=11 margin=\"0.2,0.1\" fontcolor=\"${#3c3c43|#ffffff}\" color=\"${#c2c2c4|#3c3f44}\"]\n  edge [color=\"${#67676c|#98989f}\" fontname=\"Arial\" fontsize=10 fontcolor=\"${#67676c|#98989f}\"]\n  bgcolor=\"transparent\"\n\n  root [label=\"main.js\" fillcolor=\"${#f6f6f7|#2e2e32}\"]\n  parent [label=\"App.vue\" fillcolor=\"${#f6f6f7|#2e2e32}\"]\n  boundary [label=\"Component.vue\\n(HMR boundary)\\nhot.accept()\" fillcolor=\"${#def5ed|#15312d}\" color=\"${#18794e|#3dd68c}\" penwidth=2]\n  edited [label=\"utils.js\\n(edited)\" fillcolor=\"${#fcf4dc|#38301a}\" color=\"${#915930|#f9b44e}\" penwidth=2]\n\n  boundary -> edited [label=\"imports\" color=\"${#915930|#f9b44e}\" style=bold]\n  parent -> boundary [label=\"imports\" style=dashed]\n  root -> parent [label=\"imports\" style=dashed]\n}\n```\n\nVite's HMR does not actually swap the originally imported module: if an HMR boundary module re-exports imports from a dep, then it is responsible for updating those re-exports (and these exports must be using `let`). In addition, importers up the chain from the boundary module will not be notified of the change. This simplified HMR implementation is sufficient for most dev use cases, while allowing us to skip the expensive work of generating proxy modules.\n\nVite requires that the call to this function appears as `import.meta.hot.accept(` (whitespace-sensitive) in the source code in order for the module to accept update. This is a requirement of the static analysis that Vite does to enable HMR support for a module.\n\n## `hot.accept(deps, cb)`\n\nA module can also accept updates from direct dependencies without reloading itself:\n\n```js twoslash\n// @filename: /foo.d.ts\nexport declare const foo: () => void\n\n// @filename: /example.js\nimport 'vite/client'\n// ---cut---\nimport { foo } from './foo.js'\n\nfoo()\n\nif (import.meta.hot) {\n  import.meta.hot.accept('./foo.js', (newFoo) => {\n    // the callback receives the updated './foo.js' module\n    newFoo?.foo()\n  })\n\n  // Can also accept an array of dep modules:\n  import.meta.hot.accept(\n    ['./foo.js', './bar.js'],\n    ([newFooModule, newBarModule]) => {\n      // The callback receives an array where only the updated module is\n      // non null. If the update was not successful (syntax error for ex.),\n      // the array is empty\n    },\n  )\n}\n```\n\n## `hot.dispose(cb)`\n\nA self-accepting module or a module that expects to be accepted by others can use `hot.dispose` to clean-up any persistent side effects created by its updated copy:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nfunction setupSideEffect() {}\n\nsetupSideEffect()\n\nif (import.meta.hot) {\n  import.meta.hot.dispose((data) => {\n    // cleanup side effect\n  })\n}\n```\n\n## `hot.prune(cb)`\n\nRegister a callback that will call when the module is no longer imported on the page. Compared to `hot.dispose`, this can be used if the source code cleans up side-effects by itself on updates and you only need to clean-up when it's removed from the page. Vite currently uses this for `.css` imports.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nfunction setupOrReuseSideEffect() {}\n\nsetupOrReuseSideEffect()\n\nif (import.meta.hot) {\n  import.meta.hot.prune((data) => {\n    // cleanup side effect\n  })\n}\n```\n\n## `hot.data`\n\nThe `import.meta.hot.data` object is persisted across different instances of the same updated module. It can be used to pass on information from a previous version of the module to the next one.\n\nNote that re-assignment of `data` itself is not supported. Instead, you should mutate properties of the `data` object so information added from other handlers are preserved.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// ok\nimport.meta.hot.data.someValue = 'hello'\n\n// not supported\nimport.meta.hot.data = { someValue: 'hello' }\n```\n\n## `hot.decline()`\n\nThis is currently a noop and is there for backward compatibility. This could change in the future if there is a new usage for it. To indicate that the module is not hot-updatable, use `hot.invalidate()`.\n\n## `hot.invalidate(message?: string)`\n\nA self-accepting module may realize during runtime that it can't handle a HMR update, and so the update needs to be forcefully propagated to importers. By calling `import.meta.hot.invalidate()`, the HMR server will invalidate the importers of the caller, as if the caller wasn't self-accepting. This will log a message both in the browser console and in the terminal. You can pass a message to give some context on why the invalidation happened.\n\nNote that you should always call `import.meta.hot.accept` even if you plan to call `invalidate` immediately afterwards, or else the HMR client won't listen for future changes to the self-accepting module. To communicate your intent clearly, we recommend calling `invalidate` within the `accept` callback like so:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport.meta.hot.accept((module) => {\n  // You may use the new module instance to decide whether to invalidate.\n  if (cannotHandleUpdate(module)) {\n    import.meta.hot.invalidate()\n  }\n})\n```\n\n## `hot.on(event, cb)`\n\nListen to an HMR event.\n\nThe following HMR events are dispatched by Vite automatically:\n\n- `'vite:beforeUpdate'` when an update is about to be applied (e.g. a module will be replaced)\n- `'vite:afterUpdate'` when an update has just been applied (e.g. a module has been replaced)\n- `'vite:beforeFullReload'` when a full reload is about to occur\n- `'vite:beforePrune'` when modules that are no longer needed are about to be pruned\n- `'vite:invalidate'` when a module is invalidated with `import.meta.hot.invalidate()`\n- `'vite:error'` when an error occurs (e.g. syntax error)\n- `'vite:ws:disconnect'` when the WebSocket connection is lost\n- `'vite:ws:connect'` when the WebSocket connection is (re-)established\n\nCustom HMR events can also be sent from plugins. See [handleHotUpdate](./api-plugin#handlehotupdate) for more details.\n\n## `hot.off(event, cb)`\n\nRemove callback from the event listeners.\n\n## `hot.send(event, data)`\n\nSend custom events back to Vite's dev server.\n\nIf called before connected, the data will be buffered and sent once the connection is established.\n\nSee [Client-server Communication](/guide/api-plugin.html#client-server-communication) for more details, including a section on [Typing Custom Events](/guide/api-plugin.html#typescript-for-custom-events).\n\n## Further Reading\n\nIf you'd like to learn more about how to use the HMR API and how it works under-the-hood. Check out these resources:\n\n- [Hot Module Replacement is Easy](https://bjornlu.com/blog/hot-module-replacement-is-easy)\n"
  },
  {
    "path": "docs/guide/api-javascript.md",
    "content": "# JavaScript API\n\nVite's JavaScript APIs are fully typed, and it's recommended to use TypeScript or enable JS type checking in VS Code to leverage the intellisense and validation.\n\n## `createServer`\n\n**Type Signature:**\n\n```ts\nasync function createServer(inlineConfig?: InlineConfig): Promise<ViteDevServer>\n```\n\n**Example Usage:**\n\n```ts twoslash\nimport { createServer } from 'vite'\n\nconst server = await createServer({\n  // any valid user config options, plus `mode` and `configFile`\n  configFile: false,\n  root: import.meta.dirname,\n  server: {\n    port: 1337,\n  },\n})\nawait server.listen()\n\nserver.printUrls()\nserver.bindCLIShortcuts({ print: true })\n```\n\n::: tip NOTE\nWhen using `createServer` and `build` in the same Node.js process, both functions rely on `process.env.NODE_ENV` to work properly, which also depends on the `mode` config option. To prevent conflicting behavior, set `process.env.NODE_ENV` or the `mode` of the two APIs to `development`. Otherwise, you can spawn a child process to run the APIs separately.\n:::\n\n::: tip NOTE\nWhen using [middleware mode](/config/server-options.html#server-middlewaremode) combined with [proxy config for WebSocket](/config/server-options.html#server-proxy), the parent http server should be provided in `middlewareMode` to bind the proxy correctly.\n\n<details>\n<summary>Example</summary>\n\n```ts twoslash\nimport http from 'http'\nimport { createServer } from 'vite'\n\nconst parentServer = http.createServer() // or express, koa, etc.\n\nconst vite = await createServer({\n  server: {\n    // Enable middleware mode\n    middlewareMode: {\n      // Provide the parent http server for proxy WebSocket\n      server: parentServer,\n    },\n    proxy: {\n      '/ws': {\n        target: 'ws://localhost:3000',\n        // Proxying WebSocket\n        ws: true,\n      },\n    },\n  },\n})\n\n// @noErrors: 2339\nparentServer.use(vite.middlewares)\n```\n\n</details>\n:::\n\n## `InlineConfig`\n\nThe `InlineConfig` interface extends `UserConfig` with additional properties:\n\n- `configFile`: specify config file to use. If not set, Vite will try to automatically resolve one from project root. Set to `false` to disable auto resolving.\n\n## `ResolvedConfig`\n\nThe `ResolvedConfig` interface has all the same properties of a `UserConfig`, except most properties are resolved and non-undefined. It also contains utilities like:\n\n- `config.assetsInclude`: A function to check if an `id` is considered an asset.\n- `config.logger`: Vite's internal logger object.\n\n## `ViteDevServer`\n\n```ts\ninterface ViteDevServer {\n  /**\n   * The resolved Vite config object.\n   */\n  config: ResolvedConfig\n  /**\n   * A connect app instance\n   * - Can be used to attach custom middlewares to the dev server.\n   * - Can also be used as the handler function of a custom http server\n   *   or as a middleware in any connect-style Node.js frameworks.\n   *\n   * https://github.com/senchalabs/connect#use-middleware\n   */\n  middlewares: Connect.Server\n  /**\n   * Native Node http server instance.\n   * Will be null in middleware mode.\n   */\n  httpServer: http.Server | null\n  /**\n   * Chokidar watcher instance. If `config.server.watch` is set to `null`,\n   * it will not watch any files and calling `add` or `unwatch` will have no effect.\n   * https://github.com/paulmillr/chokidar/tree/3.6.0#api\n   */\n  watcher: FSWatcher\n  /**\n   * WebSocket server with `send(payload)` method.\n   */\n  ws: WebSocketServer\n  /**\n   * Rollup plugin container that can run plugin hooks on a given file.\n   */\n  pluginContainer: PluginContainer\n  /**\n   * Module graph that tracks the import relationships, url to file mapping\n   * and hmr state.\n   */\n  moduleGraph: ModuleGraph\n  /**\n   * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null`\n   * in middleware mode or if the server is not listening on any port.\n   */\n  resolvedUrls: ResolvedServerUrls | null\n  /**\n   * Programmatically resolve, load and transform a URL and get the result\n   * without going through the http request pipeline.\n   */\n  transformRequest(\n    url: string,\n    options?: TransformOptions,\n  ): Promise<TransformResult | null>\n  /**\n   * Apply Vite built-in HTML transforms and any plugin HTML transforms.\n   */\n  transformIndexHtml(\n    url: string,\n    html: string,\n    originalUrl?: string,\n  ): Promise<string>\n  /**\n   * Load a given URL as an instantiated module for SSR.\n   */\n  ssrLoadModule(\n    url: string,\n    options?: { fixStacktrace?: boolean },\n  ): Promise<Record<string, any>>\n  /**\n   * Fix ssr error stacktrace.\n   */\n  ssrFixStacktrace(e: Error): void\n  /**\n   * Triggers HMR for a module in the module graph. You can use the `server.moduleGraph`\n   * API to retrieve the module to be reloaded. If `hmr` is false, this is a no-op.\n   */\n  reloadModule(module: ModuleNode): Promise<void>\n  /**\n   * Start the server.\n   */\n  listen(port?: number, isRestart?: boolean): Promise<ViteDevServer>\n  /**\n   * Restart the server.\n   *\n   * @param forceOptimize - force the optimizer to re-bundle, same as --force cli flag\n   */\n  restart(forceOptimize?: boolean): Promise<void>\n  /**\n   * Stop the server.\n   */\n  close(): Promise<void>\n  /**\n   * Bind CLI shortcuts\n   */\n  bindCLIShortcuts(options?: BindCLIShortcutsOptions<ViteDevServer>): void\n  /**\n   * Calling `await server.waitForRequestsIdle(id)` will wait until all static imports\n   * are processed. If called from a load or transform plugin hook, the id needs to be\n   * passed as a parameter to avoid deadlocks. Calling this function after the first\n   * static imports section of the module graph has been processed will resolve immediately.\n   * @experimental\n   */\n  waitForRequestsIdle: (ignoredId?: string) => Promise<void>\n}\n```\n\n:::info\n`waitForRequestsIdle` is meant to be used as a escape hatch to improve DX for features that can't be implemented following the on-demand nature of the Vite dev server. It can be used during startup by tools like Tailwind to delay generating the app CSS classes until the app code has been seen, avoiding flashes of style changes. When this function is used in a load or transform hook, and the default HTTP1 server is used, one of the six http channels will be blocked until the server processes all static imports. Vite's dependency optimizer currently uses this function to avoid full-page reloads on missing dependencies by delaying loading of pre-bundled dependencies until all imported dependencies have been collected from static imported sources. Vite may switch to a different strategy in a future major release, setting `optimizeDeps.crawlUntilStaticImports: false` by default to avoid the performance hit in large applications during cold start.\n:::\n\n## `build`\n\n**Type Signature:**\n\n```ts\nasync function build(\n  inlineConfig?: InlineConfig,\n): Promise<RollupOutput | RollupOutput[]>\n```\n\n**Example Usage:**\n\n```ts twoslash [vite.config.js]\nimport path from 'node:path'\nimport { build } from 'vite'\n\nawait build({\n  root: path.resolve(import.meta.dirname, './project'),\n  base: '/foo/',\n  build: {\n    rollupOptions: {\n      // ...\n    },\n  },\n})\n```\n\n## `preview`\n\n**Type Signature:**\n\n```ts\nasync function preview(inlineConfig?: InlineConfig): Promise<PreviewServer>\n```\n\n**Example Usage:**\n\n```ts twoslash\nimport { preview } from 'vite'\n\nconst previewServer = await preview({\n  // any valid user config options, plus `mode` and `configFile`\n  preview: {\n    port: 8080,\n    open: true,\n  },\n})\n\npreviewServer.printUrls()\npreviewServer.bindCLIShortcuts({ print: true })\n```\n\n## `PreviewServer`\n\n```ts\ninterface PreviewServer {\n  /**\n   * The resolved vite config object\n   */\n  config: ResolvedConfig\n  /**\n   * A connect app instance.\n   * - Can be used to attach custom middlewares to the preview server.\n   * - Can also be used as the handler function of a custom http server\n   *   or as a middleware in any connect-style Node.js frameworks\n   *\n   * https://github.com/senchalabs/connect#use-middleware\n   */\n  middlewares: Connect.Server\n  /**\n   * native Node http server instance\n   */\n  httpServer: http.Server\n  /**\n   * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null`\n   * if the server is not listening on any port.\n   */\n  resolvedUrls: ResolvedServerUrls | null\n  /**\n   * Print server urls\n   */\n  printUrls(): void\n  /**\n   * Bind CLI shortcuts\n   */\n  bindCLIShortcuts(options?: BindCLIShortcutsOptions<PreviewServer>): void\n}\n```\n\n## `resolveConfig`\n\n**Type Signature:**\n\n```ts\nasync function resolveConfig(\n  inlineConfig: InlineConfig,\n  command: 'build' | 'serve',\n  defaultMode = 'development',\n  defaultNodeEnv = 'development',\n  isPreview = false,\n): Promise<ResolvedConfig>\n```\n\nThe `command` value is `serve` in dev and preview, and `build` in build.\n\n## `mergeConfig`\n\n**Type Signature:**\n\n```ts\nfunction mergeConfig(\n  defaults: Record<string, any>,\n  overrides: Record<string, any>,\n  isRoot = true,\n): Record<string, any>\n```\n\nDeeply merge two Vite configs. `isRoot` represents the level within the Vite config which is being merged. For example, set `false` if you're merging two `build` options.\n\n::: tip NOTE\n`mergeConfig` accepts only config in object form. If you have a config in callback form, you should call it before passing into `mergeConfig`.\n\nYou can use the `defineConfig` helper to merge a config in callback form with another config:\n\n```ts twoslash\nimport {\n  defineConfig,\n  mergeConfig,\n  type UserConfigFnObject,\n  type UserConfig,\n} from 'vite'\ndeclare const configAsCallback: UserConfigFnObject\ndeclare const configAsObject: UserConfig\n\n// ---cut---\nexport default defineConfig((configEnv) =>\n  mergeConfig(configAsCallback(configEnv), configAsObject),\n)\n```\n\n:::\n\n## `searchForWorkspaceRoot`\n\n**Type Signature:**\n\n```ts\nfunction searchForWorkspaceRoot(\n  current: string,\n  root = searchForPackageRoot(current),\n): string\n```\n\n**Related:** [server.fs.allow](/config/server-options.md#server-fs-allow)\n\nSearch for the root of the potential workspace if it meets the following conditions, otherwise it would fallback to `root`:\n\n- contains `workspaces` field in `package.json`\n- contains one of the following file\n  - `lerna.json`\n  - `pnpm-workspace.yaml`\n\n## `loadEnv`\n\n**Type Signature:**\n\n```ts\nfunction loadEnv(\n  mode: string,\n  envDir: string,\n  prefixes: string | string[] = 'VITE_',\n): Record<string, string>\n```\n\n**Related:** [`.env` Files](./env-and-mode.md#env-files)\n\nLoad `.env` files within the `envDir`. By default, only env variables prefixed with `VITE_` are loaded, unless `prefixes` is changed.\n\n## `normalizePath`\n\n**Type Signature:**\n\n```ts\nfunction normalizePath(id: string): string\n```\n\n**Related:** [Path Normalization](./api-plugin.md#path-normalization)\n\nNormalizes a path to interoperate between Vite plugins.\n\n## `transformWithOxc`\n\n**Type Signature:**\n\n```ts\nasync function transformWithOxc(\n  code: string,\n  filename: string,\n  options?: OxcTransformOptions,\n  inMap?: object,\n): Promise<Omit<OxcTransformResult, 'errors'> & { warnings: string[] }>\n```\n\nTransform JavaScript or TypeScript with [Oxc Transformer](https://oxc.rs/docs/guide/usage/transformer). Useful for plugins that prefer matching Vite's internal Oxc Transformer transform.\n\n## `transformWithEsbuild`\n\n**Type Signature:**\n\n```ts\nasync function transformWithEsbuild(\n  code: string,\n  filename: string,\n  options?: EsbuildTransformOptions,\n  inMap?: object,\n): Promise<ESBuildTransformResult>\n```\n\n**Deprecated:** Use `transformWithOxc` instead.\n\nTransform JavaScript or TypeScript with esbuild. Useful for plugins that prefer matching Vite's internal esbuild transform.\n\n## `loadConfigFromFile`\n\n**Type Signature:**\n\n```ts\nasync function loadConfigFromFile(\n  configEnv: ConfigEnv,\n  configFile?: string,\n  configRoot: string = process.cwd(),\n  logLevel?: LogLevel,\n  customLogger?: Logger,\n): Promise<{\n  path: string\n  config: UserConfig\n  dependencies: string[]\n} | null>\n```\n\nLoad a Vite config file manually with esbuild.\n\n## `preprocessCSS`\n\n- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/13815)\n\n**Type Signature:**\n\n```ts\nasync function preprocessCSS(\n  code: string,\n  filename: string,\n  config: ResolvedConfig,\n): Promise<PreprocessCSSResult>\n\ninterface PreprocessCSSResult {\n  code: string\n  map?: SourceMapInput\n  modules?: Record<string, string>\n  deps?: Set<string>\n}\n```\n\nPre-processes `.css`, `.scss`, `.sass`, `.less`, `.styl` and `.stylus` files to plain CSS so it can be used in browsers or parsed by other tools. Similar to the [built-in CSS pre-processing support](/guide/features#css-pre-processors), the corresponding pre-processor must be installed if used.\n\nThe pre-processor used is inferred from the `filename` extension. If the `filename` ends with `.module.{ext}`, it is inferred as a [CSS module](https://github.com/css-modules/css-modules) and the returned result will include a `modules` object mapping the original class names to the transformed ones.\n\nNote that pre-processing will not resolve URLs in `url()` or `image-set()`.\n\n## `version`\n\n**Type:** `string`\n\nThe current version of Vite as a string (e.g. `\"8.0.0\"`).\n\n## `rolldownVersion`\n\n**Type:** `string`\n\nThe version of Rolldown used by Vite as a string (e.g. `\"1.0.0\"`). A re-export of [`VERSION`](https://rolldown.rs/reference/Variable.VERSION) from `rolldown`.\n\n## `esbuildVersion`\n\n**Type:** `string`\n\nOnly kept for backward compatibility.\n\n## `rollupVersion`\n\n**Type:** `string`\n\nOnly kept for backward compatibility.\n"
  },
  {
    "path": "docs/guide/api-plugin.md",
    "content": "# Plugin API\n\nVite plugins extends Rolldown's plugin interface with a few extra Vite-specific options. As a result, you can write a Vite plugin once and have it work for both dev and build.\n\n**It is recommended to go through [Rolldown's plugin documentation](https://rolldown.rs/apis/plugin-api) first before reading the sections below.**\n\n## Authoring a Plugin\n\nVite strives to offer established patterns out of the box, so before creating a new plugin make sure that you check the [Features guide](/guide/features) to see if your need is covered. Also review available community plugins, both in the form of a [compatible Rollup plugin](https://github.com/rollup/awesome) and [Vite Specific plugins](https://github.com/vitejs/awesome-vite#plugins).\n\nWhen creating a plugin, you can inline it in your `vite.config.js`. There is no need to create a new package for it. Once you see that a plugin was useful in your projects, consider sharing it to help others [in the ecosystem](https://chat.vite.dev).\n\n::: tip\nWhen learning, debugging, or authoring plugins, we suggest including [vite-plugin-inspect](https://github.com/antfu/vite-plugin-inspect) in your project. It allows you to inspect the intermediate state of Vite plugins. After installing, you can visit `localhost:5173/__inspect/` to inspect the modules and transformation stack of your project. Check out install instructions in the [vite-plugin-inspect docs](https://github.com/antfu/vite-plugin-inspect).\n![vite-plugin-inspect](../images/vite-plugin-inspect.webp)\n:::\n\n## Conventions\n\nIf the plugin doesn't use Vite specific hooks and can be implemented as a [Compatible Rolldown Plugin](#rolldown-plugin-compatibility), then it is recommended to use the [Rolldown Plugin naming conventions](https://rolldown.rs/apis/plugin-api#conventions).\n\n- Rolldown Plugins should have a clear name with `rolldown-plugin-` prefix.\n- Include `rolldown-plugin` and `vite-plugin` keywords in package.json `keywords` field.\n\nThis exposes the plugin to be also used in pure Rolldown or Rollup based projects.\n\nFor Vite only plugins\n\n- Vite Plugins should have a clear name with `vite-plugin-` prefix.\n- Include `vite-plugin` keyword in package.json `keywords` field.\n- Include a section in the plugin docs detailing why it is a Vite only plugin (for example, it uses Vite specific plugin hooks).\n\nIf your plugin is only going to work for a particular framework, its name should be included as part of the prefix.\n\n- `vite-plugin-vue-` prefix for Vue Plugins\n- `vite-plugin-react-` prefix for React Plugins\n- `vite-plugin-svelte-` prefix for Svelte Plugins\n\nSee also [Virtual Modules Convention](#virtual-modules-convention).\n\n## Plugins Config\n\nUsers will add plugins to the project `devDependencies` and configure them using the `plugins` array option.\n\n```js [vite.config.js]\nimport vitePlugin from 'vite-plugin-feature'\nimport rollupPlugin from 'rollup-plugin-feature'\n\nexport default defineConfig({\n  plugins: [vitePlugin(), rollupPlugin()],\n})\n```\n\nFalsy plugins will be ignored, which can be used to easily activate or deactivate plugins.\n\n`plugins` also accepts presets including several plugins as a single element. This is useful for complex features (like framework integration) that are implemented using several plugins. The array will be flattened internally.\n\n```js\n// framework-plugin\nimport frameworkRefresh from 'vite-plugin-framework-refresh'\nimport frameworkDevtools from 'vite-plugin-framework-devtools'\n\nexport default function framework(config) {\n  return [frameworkRefresh(config), frameworkDevTools(config)]\n}\n```\n\n```js [vite.config.js]\nimport { defineConfig } from 'vite'\nimport framework from 'vite-plugin-framework'\n\nexport default defineConfig({\n  plugins: [framework()],\n})\n```\n\n## Simple Examples\n\n:::tip\nIt is common convention to author a Vite/Rolldown/Rollup plugin as a factory function that returns the actual plugin object. The function can accept options which allows users to customize the behavior of the plugin.\n:::\n\n### Transforming Custom File Types\n\n```js\nconst fileRegex = /\\.(my-file-ext)$/\n\nexport default function myPlugin() {\n  return {\n    name: 'transform-file',\n\n    transform: {\n      filter: {\n        id: fileRegex,\n      },\n      handler(src, id) {\n        return {\n          code: compileFileToJS(src),\n          map: null, // provide source map if available\n        }\n      },\n    },\n  }\n}\n```\n\n### Importing a Virtual File\n\nSee the example in the [next section](#virtual-modules-convention).\n\n## Virtual Modules Convention\n\nVirtual modules are a useful scheme that allows you to pass build time information to the source files using normal ESM import syntax.\n\n```js\nimport { exactRegex } from '@rolldown/pluginutils'\n\nexport default function myPlugin() {\n  const virtualModuleId = 'virtual:my-module'\n  const resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n  return {\n    name: 'my-plugin', // required, will show up in warnings and errors\n    resolveId: {\n      filter: { id: exactRegex(virtualModuleId) },\n      handler() {\n        return resolvedVirtualModuleId\n      },\n    },\n    load: {\n      filter: { id: exactRegex(resolvedVirtualModuleId) },\n      handler() {\n        return `export const msg = \"from virtual module\"`\n      },\n    },\n  }\n}\n```\n\nWhich allows importing the module in JavaScript:\n\n```js\nimport { msg } from 'virtual:my-module'\n\nconsole.log(msg)\n```\n\nVirtual modules in Vite (and Rolldown / Rollup) are prefixed with `virtual:` for the user-facing path by convention. If possible the plugin name should be used as a namespace to avoid collisions with other plugins in the ecosystem. For example, a `vite-plugin-posts` could ask users to import a `virtual:posts` or `virtual:posts/helpers` virtual modules to get build time information. Internally, plugins that use virtual modules should prefix the module ID with `\\0` while resolving the id, a convention from the rollup ecosystem. This prevents other plugins from trying to process the id (like node resolution), and core features like sourcemaps can use this info to differentiate between virtual modules and regular files. `\\0` is not a permitted char in import URLs so we have to replace them during import analysis. A `\\0{id}` virtual id ends up encoded as `/@id/__x00__{id}` during dev in the browser. The id will be decoded back before entering the plugins pipeline, so this is not seen by plugins hooks code.\n\nNote that modules directly derived from a real file, as in the case of a script module in a Single File Component (like a .vue or .svelte SFC) don't need to follow this convention. SFCs generally generate a set of submodules when processed but the code in these can be mapped back to the filesystem. Using `\\0` for these submodules would prevent sourcemaps from working correctly.\n\n## Universal Hooks\n\nDuring dev, the Vite dev server creates a plugin container that invokes [Rolldown Build Hooks](https://rolldown.rs/apis/plugin-api#build-hooks) the same way Rolldown does it.\n\nThe following hooks are called once on server start:\n\n- [`options`](https://rolldown.rs/reference/interface.plugin#options)\n- [`buildStart`](https://rolldown.rs/reference/Interface.Plugin#buildstart)\n\nThe following hooks are called on each incoming module request:\n\n- [`resolveId`](https://rolldown.rs/reference/Interface.Plugin#resolveid)\n- [`load`](https://rolldown.rs/reference/Interface.Plugin#load)\n- [`transform`](https://rolldown.rs/reference/Interface.Plugin#transform)\n\nThese hooks also have an extended `options` parameter with additional Vite-specific properties. You can read more in the [SSR documentation](/guide/ssr#ssr-specific-plugin-logic).\n\nSome `resolveId` calls' `importer` value may be an absolute path for a generic `index.html` at root as it's not always possible to derive the actual importer due to Vite's unbundled dev server pattern. For imports handled within Vite's resolve pipeline, the importer can be tracked during the import analysis phase, providing the correct `importer` value.\n\nThe following hooks are called when the server is closed:\n\n- [`buildEnd`](https://rolldown.rs/reference/Interface.Plugin#buildend)\n- [`closeBundle`](https://rolldown.rs/reference/Interface.Plugin#closebundle)\n\nNote that the [`moduleParsed`](https://rolldown.rs/reference/Interface.Plugin#moduleparsed) hook is **not** called during dev, because Vite avoids full AST parses for better performance.\n\n[Output Generation Hooks](https://rolldown.rs/apis/plugin-api#output-generation-hooks) (except `closeBundle`) are **not** called during dev.\n\n## Vite Specific Hooks\n\nVite plugins can also provide hooks that serve Vite-specific purposes. These hooks are ignored by Rollup.\n\n### `config`\n\n- **Type:** `(config: UserConfig, env: { mode: string, command: string }) => UserConfig | null | void`\n- **Kind:** `async`, `sequential`\n\n  Modify Vite config before it's resolved. The hook receives the raw user config (CLI options merged with config file) and the current config env which exposes the `mode` and `command` being used. It can return a partial config object that will be deeply merged into existing config, or directly mutate the config (if the default merging cannot achieve the desired result).\n\n  **Example:**\n\n  ```js\n  // return partial config (recommended)\n  const partialConfigPlugin = () => ({\n    name: 'return-partial',\n    config: () => ({\n      resolve: {\n        alias: {\n          foo: 'bar',\n        },\n      },\n    }),\n  })\n\n  // mutate the config directly (use only when merging doesn't work)\n  const mutateConfigPlugin = () => ({\n    name: 'mutate-config',\n    config(config, { command }) {\n      if (command === 'build') {\n        config.root = 'foo'\n      }\n    },\n  })\n  ```\n\n  ::: warning Note\n  User plugins are resolved before running this hook so injecting other plugins inside the `config` hook will have no effect.\n  :::\n\n### `configResolved`\n\n- **Type:** `(config: ResolvedConfig) => void | Promise<void>`\n- **Kind:** `async`, `parallel`\n\n  Called after the Vite config is resolved. Use this hook to read and store the final resolved config. It is also useful when the plugin needs to do something different based on the command being run.\n\n  **Example:**\n\n  ```js\n  const examplePlugin = () => {\n    let config\n\n    return {\n      name: 'read-config',\n\n      configResolved(resolvedConfig) {\n        // store the resolved config\n        config = resolvedConfig\n      },\n\n      // use stored config in other hooks\n      transform(code, id) {\n        if (config.command === 'serve') {\n          // dev: plugin invoked by dev server\n        } else {\n          // build: plugin invoked by Rollup\n        }\n      },\n    }\n  }\n  ```\n\n  Note that the `command` value is `serve` in dev (in the cli `vite`, `vite dev`, and `vite serve` are aliases).\n\n### `configureServer`\n\n- **Type:** `(server: ViteDevServer) => (() => void) | void | Promise<(() => void) | void>`\n- **Kind:** `async`, `sequential`\n- **See also:** [ViteDevServer](./api-javascript#vitedevserver)\n\n  Hook for configuring the dev server. The most common use case is adding custom middlewares to the internal [connect](https://github.com/senchalabs/connect) app:\n\n  ```js\n  const myPlugin = () => ({\n    name: 'configure-server',\n    configureServer(server) {\n      server.middlewares.use((req, res, next) => {\n        // custom handle request...\n      })\n    },\n  })\n  ```\n\n  **Injecting Post Middleware**\n\n  The `configureServer` hook is called before internal middlewares are installed, so the custom middlewares will run before internal middlewares by default. If you want to inject a middleware **after** internal middlewares, you can return a function from `configureServer`, which will be called after internal middlewares are installed:\n\n  ```js\n  const myPlugin = () => ({\n    name: 'configure-server',\n    configureServer(server) {\n      // return a post hook that is called after internal middlewares are\n      // installed\n      return () => {\n        server.middlewares.use((req, res, next) => {\n          // custom handle request...\n        })\n      }\n    },\n  })\n  ```\n\n  **Storing Server Access**\n\n  In some cases, other plugin hooks may need access to the dev server instance (e.g. accessing the WebSocket server, the file system watcher, or the module graph). This hook can also be used to store the server instance for access in other hooks:\n\n  ```js\n  const myPlugin = () => {\n    let server\n    return {\n      name: 'configure-server',\n      configureServer(_server) {\n        server = _server\n      },\n      transform(code, id) {\n        if (server) {\n          // use server...\n        }\n      },\n    }\n  }\n  ```\n\n  Note `configureServer` is not called when running the production build so your other hooks need to guard against its absence.\n\n### `configurePreviewServer`\n\n- **Type:** `(server: PreviewServer) => (() => void) | void | Promise<(() => void) | void>`\n- **Kind:** `async`, `sequential`\n- **See also:** [PreviewServer](./api-javascript#previewserver)\n\n  Same as [`configureServer`](/guide/api-plugin.html#configureserver) but for the preview server. Similarly to `configureServer`, the `configurePreviewServer` hook is called before other middlewares are installed. If you want to inject a middleware **after** other middlewares, you can return a function from `configurePreviewServer`, which will be called after internal middlewares are installed:\n\n  ```js\n  const myPlugin = () => ({\n    name: 'configure-preview-server',\n    configurePreviewServer(server) {\n      // return a post hook that is called after other middlewares are\n      // installed\n      return () => {\n        server.middlewares.use((req, res, next) => {\n          // custom handle request...\n        })\n      }\n    },\n  })\n  ```\n\n### `transformIndexHtml`\n\n- **Type:** `IndexHtmlTransformHook | { order?: 'pre' | 'post', handler: IndexHtmlTransformHook }`\n- **Kind:** `async`, `sequential`\n\n  Dedicated hook for transforming HTML entry point files such as `index.html`. The hook receives the current HTML string and a transform context. The context exposes the [`ViteDevServer`](./api-javascript#vitedevserver) instance during dev, and exposes the Rollup output bundle during build.\n\n  The hook can be async and can return one of the following:\n  - Transformed HTML string\n  - An array of tag descriptor objects (`{ tag, attrs, children }`) to inject to the existing HTML. Each tag can also specify where it should be injected to (default is prepending to `<head>`)\n  - An object containing both as `{ html, tags }`\n\n  By default `order` is `undefined`, with this hook applied after the HTML has been transformed. In order to inject a script that should go through the Vite plugins pipeline, `order: 'pre'` will apply the hook before processing the HTML. `order: 'post'` applies the hook after all hooks with `order` undefined are applied.\n\n  **Basic Example:**\n\n  ```js\n  const htmlPlugin = () => {\n    return {\n      name: 'html-transform',\n      transformIndexHtml(html) {\n        return html.replace(\n          /<title>(.*?)<\\/title>/,\n          `<title>Title replaced!</title>`,\n        )\n      },\n    }\n  }\n  ```\n\n  **Full Hook Signature:**\n\n  ```ts\n  type IndexHtmlTransformHook = (\n    html: string,\n    ctx: {\n      path: string\n      filename: string\n      server?: ViteDevServer\n      bundle?: import('rollup').OutputBundle\n      chunk?: import('rollup').OutputChunk\n    },\n  ) =>\n    | IndexHtmlTransformResult\n    | void\n    | Promise<IndexHtmlTransformResult | void>\n\n  type IndexHtmlTransformResult =\n    | string\n    | HtmlTagDescriptor[]\n    | {\n        html: string\n        tags: HtmlTagDescriptor[]\n      }\n\n  interface HtmlTagDescriptor {\n    tag: string\n    /**\n     * attribute values will be escaped automatically if needed\n     */\n    attrs?: Record<string, string | boolean>\n    children?: string | HtmlTagDescriptor[]\n    /**\n     * default: 'head-prepend'\n     */\n    injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'\n  }\n  ```\n\n  ::: warning Note\n  This hook won't be called if you are using a framework that has custom handling of entry files (for example [SvelteKit](https://github.com/sveltejs/kit/discussions/8269#discussioncomment-4509145)).\n  :::\n\n### `handleHotUpdate`\n\n- **Type:** `(ctx: HmrContext) => Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>`\n- **Kind:** `async`, `sequential`\n- **See also:** [HMR API](./api-hmr)\n\n  Perform custom HMR update handling. The hook receives a context object with the following signature:\n\n  ```ts\n  interface HmrContext {\n    file: string\n    timestamp: number\n    modules: Array<ModuleNode>\n    read: () => string | Promise<string>\n    server: ViteDevServer\n  }\n  ```\n\n  - `modules` is an array of modules that are affected by the changed file. It's an array because a single file may map to multiple served modules (e.g. Vue SFCs).\n\n  - `read` is an async read function that returns the content of the file. This is provided because on some systems, the file change callback may fire too fast before the editor finishes updating the file and direct `fs.readFile` will return empty content. The read function passed in normalizes this behavior.\n\n  The hook can choose to:\n  - Filter and narrow down the affected module list so that the HMR is more accurate.\n\n  - Return an empty array and perform a full reload:\n\n    ```js\n    handleHotUpdate({ server, modules, timestamp }) {\n      // Invalidate modules manually\n      const invalidatedModules = new Set()\n      for (const mod of modules) {\n        server.moduleGraph.invalidateModule(\n          mod,\n          invalidatedModules,\n          timestamp,\n          true\n        )\n      }\n      server.ws.send({ type: 'full-reload' })\n      return []\n    }\n    ```\n\n  - Return an empty array and perform complete custom HMR handling by sending custom events to the client:\n\n    ```js\n    handleHotUpdate({ server }) {\n      server.ws.send({\n        type: 'custom',\n        event: 'special-update',\n        data: {}\n      })\n      return []\n    }\n    ```\n\n    Client code should register corresponding handler using the [HMR API](./api-hmr) (this could be injected by the same plugin's `transform` hook):\n\n    ```js\n    if (import.meta.hot) {\n      import.meta.hot.on('special-update', (data) => {\n        // perform custom update\n      })\n    }\n    ```\n\n## Plugin Context Meta\n\nFor plugin hooks that has access to the plugin context, Vite exposes additional properties on `this.meta`:\n\n- `this.meta.viteVersion`: The current Vite version string (e.g. `\"8.0.0\"`).\n\n::: tip Detecting Rolldown powered Vite\n\n[`this.meta.rolldownVersion`](https://rolldown.rs/reference/Interface.PluginContextMeta#rolldownversion) is only available for Rolldown powered Vite (i.e. Vite 8+). You can use it to detect whether the current Vite instance is powered by Rolldown:\n\n```ts\nfunction versionCheckPlugin(): Plugin {\n  return {\n    name: 'version-check',\n    buildStart() {\n      if (this.meta.rolldownVersion) {\n        // only do something if running on a Rolldown powered Vite\n      } else {\n        // do something else if running on a Rollup powered Vite\n      }\n    },\n  }\n}\n```\n\n:::\n\n## Output Bundle Metadata\n\nDuring build, Vite augments Rolldown's build output objects with a Vite-specific `viteMetadata` field.\n\nThis is available through:\n\n- `RenderedChunk` (for example in `renderChunk` and `augmentChunkHash`)\n- `OutputChunk` and `OutputAsset` (for example in `generateBundle` and `writeBundle`)\n\n`viteMetadata` provides:\n\n- `viteMetadata.importedCss: Set<string>`\n- `viteMetadata.importedAssets: Set<string>`\n\nThis is useful when writing plugins that need to inspect emitted CSS and static assets without relying on [`build.manifest`](/config/build-options#build-manifest).\n\nExample:\n\n```ts [vite.config.ts]\nfunction outputMetadataPlugin(): Plugin {\n  return {\n    name: 'output-metadata-plugin',\n    generateBundle(_, bundle) {\n      for (const output of Object.values(bundle)) {\n        const css = output.viteMetadata?.importedCss\n        const assets = output.viteMetadata?.importedAssets\n        if (!css?.size && !assets?.size) continue\n\n        console.log(output.fileName, {\n          css: css ? [...css] : [],\n          assets: assets ? [...assets] : [],\n        })\n      }\n    },\n  }\n}\n```\n\n## Plugin Ordering\n\nA Vite plugin can additionally specify an `enforce` property (similar to webpack loaders) to adjust its application order. The value of `enforce` can be either `\"pre\"` or `\"post\"`. The resolved plugins will be in the following order:\n\n- Alias\n- User plugins with `enforce: 'pre'`\n- Vite core plugins\n- User plugins without enforce value\n- Vite build plugins\n- User plugins with `enforce: 'post'`\n- Vite post build plugins (minify, manifest, reporting)\n\nNote that this is separate from hooks ordering, those are still separately subject to their [`order` attribute](https://rolldown.rs/reference/TypeAlias.ObjectHook#order) as usual for Rolldown hooks.\n\n## Conditional Application\n\nBy default plugins are invoked for both serve and build. In cases where a plugin needs to be conditionally applied only during serve or build, use the `apply` property to only invoke them during `'build'` or `'serve'`:\n\n```js\nfunction myPlugin() {\n  return {\n    name: 'build-only',\n    apply: 'build', // or 'serve'\n  }\n}\n```\n\nA function can also be used for more precise control:\n\n```js\napply(config, { command }) {\n  // apply only on build but not for SSR\n  return command === 'build' && !config.build.ssr\n}\n```\n\n## Rolldown Plugin Compatibility\n\nA fair number of Rolldown / Rollup plugins will work directly as a Vite plugin (e.g. `@rollup/plugin-alias` or `@rollup/plugin-json`), but not all of them, since some plugin hooks do not make sense in an unbundled dev server context.\n\nIn general, as long as a Rolldown / Rollup plugin fits the following criteria then it should just work as a Vite plugin:\n\n- It doesn't use the [`moduleParsed`](https://rolldown.rs/reference/Interface.Plugin#moduleparsed) hook.\n- It doesn't rely on the Rolldown specific options like [`transform.inject`](https://rolldown.rs/reference/InputOptions.transform#inject)\n- It doesn't have strong coupling between bundle-phase hooks and output-phase hooks.\n\nIf a Rolldown / Rollup plugin only makes sense for the build phase, then it can be specified under `build.rolldownOptions.plugins` instead. It will work the same as a Vite plugin with `enforce: 'post'` and `apply: 'build'`.\n\nYou can also augment an existing Rolldown / Rollup plugin with Vite-only properties:\n\n```js [vite.config.js]\nimport example from 'rolldown-plugin-example'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    {\n      ...example(),\n      enforce: 'post',\n      apply: 'build',\n    },\n  ],\n})\n```\n\n## Path Normalization\n\nVite normalizes paths while resolving ids to use POSIX separators ( / ) while preserving the volume in Windows. On the other hand, Rollup keeps resolved paths untouched by default, so resolved ids have win32 separators ( \\\\ ) in Windows. However, Rollup plugins use a [`normalizePath` utility function](https://github.com/rollup/plugins/tree/master/packages/pluginutils#normalizepath) from `@rollup/pluginutils` internally, which converts separators to POSIX before performing comparisons. This means that when these plugins are used in Vite, the `include` and `exclude` config pattern and other similar paths against resolved ids comparisons work correctly.\n\nSo, for Vite plugins, when comparing paths against resolved ids it is important to first normalize the paths to use POSIX separators. An equivalent `normalizePath` utility function is exported from the `vite` module.\n\n```js\nimport { normalizePath } from 'vite'\n\nnormalizePath('foo\\\\bar') // 'foo/bar'\nnormalizePath('foo/bar') // 'foo/bar'\n```\n\n## Filtering, include/exclude pattern\n\nVite exposes [`@rollup/pluginutils`'s `createFilter`](https://github.com/rollup/plugins/tree/master/packages/pluginutils#createfilter) function to encourage Vite specific plugins and integrations to use the standard include/exclude filtering pattern, which is also used in Vite core itself.\n\n### Hook Filters\n\nRolldown introduced a [hook filter feature](https://rolldown.rs/apis/plugin-api/hook-filters) to reduce the communication overhead between the Rust and JavaScript runtimes. This feature allows plugins to specify patterns that determine when hooks should be called, improving performance by avoiding unnecessary hook invocations.\n\nThis is also supported by Rollup 4.38.0+ and Vite 6.3.0+. To make your plugin backward compatible with older versions, make sure to also run the filter inside the hook handlers.\n\n```js\nexport default function myPlugin() {\n  const jsFileRegex = /\\.js$/\n\n  return {\n    name: 'my-plugin',\n    // Example: only call transform for .js files\n    transform: {\n      filter: {\n        id: jsFileRegex,\n      },\n      handler(code, id) {\n        // Additional check for backward compatibility\n        if (!jsFileRegex.test(id)) return null\n\n        return {\n          code: transformCode(code),\n          map: null,\n        }\n      },\n    },\n  }\n}\n```\n\n::: tip\n[`@rolldown/pluginutils`](https://www.npmjs.com/package/@rolldown/pluginutils) exports some utilities for hook filters like `exactRegex` and `prefixRegex`. These are also re-exported from `rolldown/filter` for convenience.\n:::\n\n## Client-server Communication\n\nSince Vite 2.9, we provide some utilities for plugins to help handle the communication with clients.\n\n### Server to Client\n\nOn the plugin side, we could use `server.ws.send` to broadcast events to the client:\n\n```js [vite.config.js]\nexport default defineConfig({\n  plugins: [\n    {\n      // ...\n      configureServer(server) {\n        server.ws.on('connection', () => {\n          server.ws.send('my:greetings', { msg: 'hello' })\n        })\n      },\n    },\n  ],\n})\n```\n\n::: tip NOTE\nWe recommend **always prefixing** your event names to avoid collisions with other plugins.\n:::\n\nOn the client side, use [`hot.on`](/guide/api-hmr.html#hot-on-event-cb) to listen to the events:\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\n// client side\nif (import.meta.hot) {\n  import.meta.hot.on('my:greetings', (data) => {\n    console.log(data.msg) // hello\n  })\n}\n```\n\n### Client to Server\n\nTo send events from the client to the server, we can use [`hot.send`](/guide/api-hmr.html#hot-send-event-payload):\n\n```ts\n// client side\nif (import.meta.hot) {\n  import.meta.hot.send('my:from-client', { msg: 'Hey!' })\n}\n```\n\nThen use `server.ws.on` and listen to the events on the server side:\n\n```js [vite.config.js]\nexport default defineConfig({\n  plugins: [\n    {\n      // ...\n      configureServer(server) {\n        server.ws.on('my:from-client', (data, client) => {\n          console.log('Message from client:', data.msg) // Hey!\n          // reply only to the client (if needed)\n          client.send('my:ack', { msg: 'Hi! I got your message!' })\n        })\n      },\n    },\n  ],\n})\n```\n\n### TypeScript for Custom Events\n\nInternally, vite infers the type of a payload from the `CustomEventMap` interface, it is possible to type custom events by extending the interface:\n\n:::tip Note\nMake sure to include the `.d.ts` extension when specifying TypeScript declaration files. Otherwise, Typescript may not know which file the module is trying to extend.\n:::\n\n```ts [events.d.ts]\nimport 'vite/types/customEvent.d.ts'\n\ndeclare module 'vite/types/customEvent.d.ts' {\n  interface CustomEventMap {\n    'custom:foo': { msg: string }\n    // 'event-key': payload\n  }\n}\n```\n\nThis interface extension is utilized by `InferCustomEventPayload<T>` to infer the payload type for event `T`. For more information on how this interface is utilized, refer to the [HMR API Documentation](./api-hmr#hmr-api).\n\n```ts twoslash\nimport 'vite/client'\nimport type { InferCustomEventPayload } from 'vite/types/customEvent.d.ts'\ndeclare module 'vite/types/customEvent.d.ts' {\n  interface CustomEventMap {\n    'custom:foo': { msg: string }\n  }\n}\n// ---cut---\ntype CustomFooPayload = InferCustomEventPayload<'custom:foo'>\nimport.meta.hot?.on('custom:foo', (payload) => {\n  // The type of payload will be { msg: string }\n})\nimport.meta.hot?.on('unknown:event', (payload) => {\n  // The type of payload will be any\n})\n```\n"
  },
  {
    "path": "docs/guide/assets.md",
    "content": "# Static Asset Handling\n\n- Related: [Public Base Path](./build#public-base-path)\n- Related: [`assetsInclude` config option](/config/shared-options.md#assetsinclude)\n\n## Importing Asset as URL\n\nImporting a static asset will return the resolved public URL when it is served:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport imgUrl from './img.png'\ndocument.getElementById('hero-img').src = imgUrl\n```\n\nFor example, `imgUrl` will be `/src/img.png` during development, and become `/assets/img.2d8efhg.png` in the production build.\n\nThe behavior is similar to webpack's `file-loader`. The difference is that the import can be either using absolute public paths (based on project root during dev) or relative paths.\n\n- `url()` references in CSS are handled the same way.\n\n- If using the Vue plugin, asset references in Vue SFC templates are automatically converted into imports.\n\n- Common image, media, and font filetypes are detected as assets automatically. You can extend the internal list using the [`assetsInclude` option](/config/shared-options.md#assetsinclude).\n\n- Referenced assets are included as part of the build assets graph, will get hashed file names, and can be processed by plugins for optimization.\n\n- Assets smaller in bytes than the [`assetsInlineLimit` option](/config/build-options.md#build-assetsinlinelimit) will be inlined as base64 data URLs.\n\n- Git LFS placeholders are automatically excluded from inlining because they do not contain the content of the file they represent. To get inlining, make sure to download the file contents via Git LFS before building.\n\n- TypeScript, by default, does not recognize static asset imports as valid modules. To fix this, include [`vite/client`](./features#client-types).\n\n::: tip Inlining SVGs through `url()`\nWhen passing a URL of SVG to a manually constructed `url()` by JS, the variable should be wrapped within double quotes.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport imgUrl from './img.svg'\ndocument.getElementById('hero-img').style.background = `url(\"${imgUrl}\")`\n```\n\n:::\n\n### Explicit URL Imports\n\nAssets that are not included in the internal list or in `assetsInclude` can be explicitly imported as a URL using the `?url` suffix. This is useful, for example, to import [Houdini Paint Worklets](https://developer.mozilla.org/en-US/docs/Web/API/CSS/paintWorklet_static).\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport workletURL from 'extra-scalloped-border/worklet.js?url'\nCSS.paintWorklet.addModule(workletURL)\n```\n\n### Explicit Inline Handling\n\nAssets can be explicitly imported with inlining or no inlining using the `?inline` or `?no-inline` suffix respectively.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport imgUrl1 from './img.svg?no-inline'\nimport imgUrl2 from './img.png?inline'\n```\n\n### Importing Asset as String\n\nAssets can be imported as strings using the `?raw` suffix.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport shaderString from './shader.glsl?raw'\n```\n\n### Importing Script as a Worker\n\nScripts can be imported as web workers with the `?worker` or `?sharedworker` suffix.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// Separate chunk in the production build\nimport Worker from './shader.js?worker'\nconst worker = new Worker()\n```\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// sharedworker\nimport SharedWorker from './shader.js?sharedworker'\nconst sharedWorker = new SharedWorker()\n```\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// Inlined as base64 strings\nimport InlineWorker from './shader.js?worker&inline'\n```\n\nCheck out the [Web Worker section](./features.md#web-workers) for more details.\n\n## The `public` Directory\n\nIf you have assets that are:\n\n- Never referenced in source code (e.g. `robots.txt`)\n- Must retain the exact same file name (without hashing)\n- ...or you simply don't want to have to import an asset first just to get its URL\n\nThen you can place the asset in a special `public` directory under your project root. Assets in this directory will be served at root path `/` during dev, and copied to the root of the dist directory as-is.\n\nThe directory defaults to `<root>/public`, but can be configured via the [`publicDir` option](/config/shared-options.md#publicdir).\n\nNote that you should always reference `public` assets using root absolute path - for example, `public/icon.png` should be referenced in source code as `/icon.png`.\n\n::: tip Choosing between imports and the `public` directory\n\nIn general, prefer **importing assets** unless you specifically need the guarantees provided by the `public` directory.\n\n:::\n\n## new URL(url, import.meta.url)\n\n[import.meta.url](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import.meta) is a native ESM feature that exposes the current module's URL. Combining it with the native [URL constructor](https://developer.mozilla.org/en-US/docs/Web/API/URL), we can obtain the full, resolved URL of a static asset using relative path from a JavaScript module:\n\n```js\nconst imgUrl = new URL('./img.png', import.meta.url).href\n\ndocument.getElementById('hero-img').src = imgUrl\n```\n\nThis works natively in modern browsers - in fact, Vite doesn't need to process this code at all during development!\n\nThis pattern also supports dynamic URLs via template literals:\n\n```js\nfunction getImageUrl(name) {\n  // note that this does not include files in subdirectories\n  return new URL(`./dir/${name}.png`, import.meta.url).href\n}\n```\n\nDuring the production build, Vite will perform necessary transforms so that the URLs still point to the correct location even after bundling and asset hashing. However, the URL string must be static so it can be analyzed, otherwise the code will be left as is, which can cause runtime errors if `build.target` does not support `import.meta.url`.\n\n```js\n// Vite will not transform this\nconst imgUrl = new URL(imagePath, import.meta.url).href\n```\n\n::: details How it works\n\nVite will transform the `getImageUrl` function to:\n\n```js\nimport __img0png from './dir/img0.png'\nimport __img1png from './dir/img1.png'\n\nfunction getImageUrl(name) {\n  const modules = {\n    './dir/img0.png': __img0png,\n    './dir/img1.png': __img1png,\n  }\n  return new URL(modules[`./dir/${name}.png`], import.meta.url).href\n}\n```\n\n:::\n\n::: warning Does not work with SSR\nThis pattern does not work if you are using Vite for Server-Side Rendering, because `import.meta.url` has different semantics in browsers vs. Node.js. The server bundle also cannot determine the client host URL ahead of time.\n:::\n"
  },
  {
    "path": "docs/guide/backend-integration.md",
    "content": "# Backend Integration\n\n:::tip Note\nIf you want to serve the HTML using a traditional backend (e.g. Rails, Laravel) but use Vite for serving assets, check for existing integrations listed in [Awesome Vite](https://github.com/vitejs/awesome-vite#integrations-with-backends).\n\nIf you need a custom integration, you can follow the steps in this guide to configure it manually.\n:::\n\n1. In your Vite config, configure the entry and enable build manifest:\n\n   ```js twoslash [vite.config.js]\n   import { defineConfig } from 'vite'\n   // ---cut---\n   export default defineConfig({\n     server: {\n       cors: {\n         // the origin you will be accessing via browser\n         origin: 'http://my-backend.example.com',\n       },\n     },\n     build: {\n       // generate .vite/manifest.json in outDir\n       manifest: true,\n       rollupOptions: {\n         // overwrite default .html entry\n         input: '/path/to/main.js',\n       },\n     },\n   })\n   ```\n\n   If you haven't disabled the [module preload polyfill](/config/build-options.md#build-polyfillmodulepreload), you also need to import the polyfill in your entry\n\n   ```js\n   // add the beginning of your app entry\n   import 'vite/modulepreload-polyfill'\n   ```\n\n2. For development, inject the following in your server's HTML template (substitute `http://localhost:5173` with the local URL Vite is running at):\n\n   ```html\n   <!-- if development -->\n   <script type=\"module\" src=\"http://localhost:5173/@vite/client\"></script>\n   <script type=\"module\" src=\"http://localhost:5173/main.js\"></script>\n   ```\n\n   In order to properly serve assets, you have two options:\n   - Make sure the server is configured to proxy static assets requests to the Vite server\n   - Set [`server.origin`](/config/server-options.md#server-origin) so that generated asset URLs will be resolved using the back-end server URL instead of a relative path\n\n   This is needed for assets such as images to load properly.\n\n   Note if you are using React with `@vitejs/plugin-react`, you'll also need to add this before the above scripts, since the plugin is not able to modify the HTML you are serving (substitute `http://localhost:5173` with the local URL Vite is running at):\n\n   ```html\n   <script type=\"module\">\n     import RefreshRuntime from 'http://localhost:5173/@react-refresh'\n     RefreshRuntime.injectIntoGlobalHook(window)\n     window.$RefreshReg$ = () => {}\n     window.$RefreshSig$ = () => (type) => type\n     window.__vite_plugin_react_preamble_installed__ = true\n   </script>\n   ```\n\n3. For production, after running `vite build`, a `.vite/manifest.json` file will be generated alongside other asset files. An example manifest file looks like this:\n\n   ```json [.vite/manifest.json] style:max-height:400px\n   {\n     \"_shared-B7PI925R.js\": {\n       \"file\": \"assets/shared-B7PI925R.js\",\n       \"name\": \"shared\",\n       \"css\": [\"assets/shared-ChJ_j-JJ.css\"]\n     },\n     \"_shared-ChJ_j-JJ.css\": {\n       \"file\": \"assets/shared-ChJ_j-JJ.css\",\n       \"src\": \"_shared-ChJ_j-JJ.css\"\n     },\n     \"logo.svg\": {\n       \"file\": \"assets/logo-BuPIv-2h.svg\",\n       \"src\": \"logo.svg\"\n     },\n     \"baz.js\": {\n       \"file\": \"assets/baz-B2H3sXNv.js\",\n       \"name\": \"baz\",\n       \"src\": \"baz.js\",\n       \"isDynamicEntry\": true\n     },\n     \"views/bar.js\": {\n       \"file\": \"assets/bar-gkvgaI9m.js\",\n       \"name\": \"bar\",\n       \"src\": \"views/bar.js\",\n       \"isEntry\": true,\n       \"imports\": [\"_shared-B7PI925R.js\"],\n       \"dynamicImports\": [\"baz.js\"]\n     },\n     \"views/foo.js\": {\n       \"file\": \"assets/foo-BRBmoGS9.js\",\n       \"name\": \"foo\",\n       \"src\": \"views/foo.js\",\n       \"isEntry\": true,\n       \"imports\": [\"_shared-B7PI925R.js\"],\n       \"css\": [\"assets/foo-5UjPuW-k.css\"]\n     }\n   }\n   ```\n\n   The manifest maps source files to their build outputs and dependencies:\n\n   ```dot\n   digraph manifest {\n     rankdir=TB\n     node [shape=box style=\"rounded,filled\" fontname=\"Arial\" fontsize=10 margin=\"0.2,0.1\" fontcolor=\"${#3c3c43|#ffffff}\" color=\"${#c2c2c4|#3c3f44}\"]\n     edge [color=\"${#67676c|#98989f}\" fontname=\"Arial\" fontsize=9 fontcolor=\"${#67676c|#98989f}\"]\n     bgcolor=\"transparent\"\n\n     foo [label=\"views/foo.js\\n(entry)\" fillcolor=\"${#e9eaff|#222541}\"]\n     bar [label=\"views/bar.js\\n(entry)\" fillcolor=\"${#e9eaff|#222541}\"]\n     shared [label=\"_shared-B7PI925R.js\\n(common chunk)\" fillcolor=\"${#f2ecfc|#2c273e}\"]\n     baz [label=\"baz.js\\n(dynamic import)\" fillcolor=\"${#fcf4dc|#38301a}\"]\n     foocss [label=\"foo.css\" shape=ellipse fillcolor=\"${#fde4e8|#3a1d27}\"]\n     sharedcss [label=\"shared.css\" shape=ellipse fillcolor=\"${#fde4e8|#3a1d27}\"]\n     logo [label=\"logo.svg\\n(asset)\" shape=ellipse fillcolor=\"${#def5ed|#15312d}\"]\n\n     foo -> shared [label=\"imports\"]\n     bar -> shared [label=\"imports\"]\n     bar -> baz [label=\"dynamicImports\" style=dashed]\n     foo -> foocss [label=\"css\"]\n     shared -> sharedcss [label=\"css\"]\n   }\n   ```\n\n   The manifest has a `Record<name, chunk>` structure where each chunk follows the `ManifestChunk` interface:\n\n   ```ts style:max-height:400px\n   interface ManifestChunk {\n     /**\n      * The input file name of this chunk / asset if known\n      */\n     src?: string\n     /**\n      * The output file name of this chunk / asset\n      */\n     file: string\n     /**\n      * The list of CSS files imported by this chunk\n      */\n     css?: string[]\n     /**\n      * The list of asset files imported by this chunk, excluding CSS files\n      */\n     assets?: string[]\n     /**\n      * Whether this chunk or asset is an entry point\n      */\n     isEntry?: boolean\n     /**\n      * The name of this chunk / asset if known\n      */\n     name?: string\n     /**\n      * Whether this chunk is a dynamic entry point\n      *\n      * This field is only present in JS chunks.\n      */\n     isDynamicEntry?: boolean\n     /**\n      * The list of statically imported chunks by this chunk\n      *\n      * The values are the keys of the manifest. This field is only present in JS chunks.\n      */\n     imports?: string[]\n     /**\n      * The list of dynamically imported chunks by this chunk\n      *\n      * The values are the keys of the manifest. This field is only present in JS chunks.\n      */\n     dynamicImports?: string[]\n   }\n   ```\n\n   Each entry in the manifest represents one of the following:\n   - **Entry chunks**: Generated from files specified in [`build.rollupOptions.input`](https://rollupjs.org/configuration-options/#input). These chunks have `isEntry: true` and their key is the relative src path from project root.\n   - **Dynamic entry chunks**: Generated from dynamic imports. These chunks have `isDynamicEntry: true` and their key is the relative src path from project root.\n   - **Non-entry chunks**: Their key is the base name of the generated file prefixed with `_`.\n   - **Asset chunks**: Generated from imported assets like images, fonts. Their key is the relative src path from project root.\n   - **CSS files**: When [`build.cssCodeSplit`](/config/build-options.md#build-csscodesplit) is `false`, a single CSS file is generated with the key `style.css`. When `build.cssCodeSplit` is not `false`, the key is generated similar to JS chunks (i.e. entry chunks will not have `_` prefix and non-entry chunks will have `_` prefix).\n\n   JS chunks (chunks other than assets or CSS) will contain information on their static and dynamic imports (both are keys that map to the corresponding chunk in the manifest). Chunks also list their corresponding CSS and asset files if they have any.\n\n4. You can use this file to render links or preload directives with hashed filenames.\n\n   Here is an example HTML template to render the proper links. The syntax here is for\n   explanation only, substitute with your server templating language. The `importedChunks`\n   function is for illustration and isn't provided by Vite.\n\n   ```html\n   <!-- if production -->\n\n   <!-- for cssFile of manifest[name].css -->\n   <link rel=\"stylesheet\" href=\"/{{ cssFile }}\" />\n\n   <!-- for chunk of importedChunks(manifest, name) -->\n   <!-- for cssFile of chunk.css -->\n   <link rel=\"stylesheet\" href=\"/{{ cssFile }}\" />\n\n   <script type=\"module\" src=\"/{{ manifest[name].file }}\"></script>\n\n   <!-- for chunk of importedChunks(manifest, name) -->\n   <link rel=\"modulepreload\" href=\"/{{ chunk.file }}\" />\n   ```\n\n   Specifically, a backend generating HTML should include the following tags given a manifest\n   file and an entry point. Note that following this order is recommended for optimal performance:\n   1. A `<link rel=\"stylesheet\">` tag for each file in the entry point chunk's `css` list (if it exists)\n   2. Recursively follow all chunks in the entry point's `imports` list and include a\n      `<link rel=\"stylesheet\">` tag for each CSS file of each imported chunk's `css` list (if it exists).\n   3. A tag for the `file` key of the entry point chunk. This can be `<script type=\"module\">` for JavaScript, `<link rel=\"stylesheet\">` for CSS.\n   4. Optionally, `<link rel=\"modulepreload\">` tag for the `file` of each imported JavaScript\n      chunk, again recursively following the imports starting from the entry point chunk.\n\n   Following the above example manifest, for the entry point `views/foo.js` the following tags should be included in production:\n\n   ```html\n   <link rel=\"stylesheet\" href=\"assets/foo-5UjPuW-k.css\" />\n   <link rel=\"stylesheet\" href=\"assets/shared-ChJ_j-JJ.css\" />\n   <script type=\"module\" src=\"assets/foo-BRBmoGS9.js\"></script>\n   <!-- optional -->\n   <link rel=\"modulepreload\" href=\"assets/shared-B7PI925R.js\" />\n   ```\n\n   While the following should be included for the entry point `views/bar.js`:\n\n   ```html\n   <link rel=\"stylesheet\" href=\"assets/shared-ChJ_j-JJ.css\" />\n   <script type=\"module\" src=\"assets/bar-gkvgaI9m.js\"></script>\n   <!-- optional -->\n   <link rel=\"modulepreload\" href=\"assets/shared-B7PI925R.js\" />\n   ```\n\n   ::: details Pseudo implementation of `importedChunks`\n   An example pseudo implementation of `importedChunks` in TypeScript (This will\n   need to be adapted for your programming language and templating language):\n\n   ```ts\n   import type { Manifest, ManifestChunk } from 'vite'\n\n   export default function importedChunks(\n     manifest: Manifest,\n     name: string,\n   ): ManifestChunk[] {\n     const seen = new Set<string>()\n\n     function getImportedChunks(chunk: ManifestChunk): ManifestChunk[] {\n       const chunks: ManifestChunk[] = []\n       for (const file of chunk.imports ?? []) {\n         const importee = manifest[file]\n         if (seen.has(file)) {\n           continue\n         }\n         seen.add(file)\n\n         chunks.push(...getImportedChunks(importee))\n         chunks.push(importee)\n       }\n\n       return chunks\n     }\n\n     return getImportedChunks(manifest[name])\n   }\n   ```\n\n   :::\n"
  },
  {
    "path": "docs/guide/build.md",
    "content": "# Building for Production\n\nWhen it is time to deploy your app for production, simply run the `vite build` command. By default, it uses `<root>/index.html` as the build entry point, and produces an application bundle that is suitable to be served over a static hosting service. Check out the [Deploying a Static Site](./static-deploy) for guides about popular services.\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq/~037q?via=vite\" title=\"Building for Production\">Watch an interactive lesson on Scrimba</ScrimbaLink>\n\n## Browser Compatibility\n\nBy default, the production bundle assumes a modern browser that is included in the [Baseline](https://web-platform-dx.github.io/web-features/) Widely Available targets. The default browser support range is:\n\n<!-- Search for the `ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET` constant for more information -->\n\n- Chrome >=111\n- Edge >=111\n- Firefox >=114\n- Safari >=16.4\n\nYou can specify custom targets via the [`build.target` config option](/config/build-options.md#build-target), where the lowest target is `es2015`. If a lower target is set, Vite will still require these minimum browser support ranges as it relies on [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta):\n\n<!-- Search for the `defaultEsbuildSupported` constant for more information -->\n\n- Chrome >=64\n- Firefox >=67\n- Safari >=11.1\n- Edge >=79\n\nNote that by default, Vite only handles syntax transforms and **does not cover polyfills**. You can check out https://cdnjs.cloudflare.com/polyfill/ which automatically generates polyfill bundles based on the user's browser UserAgent string.\n\nLegacy browsers can be supported via [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy), which will automatically generate legacy chunks and corresponding ES language feature polyfills. The legacy chunks are conditionally loaded only in browsers that do not have native ESM support.\n\n## Public Base Path\n\n- Related: [Asset Handling](./assets)\n\nIf you are deploying your project under a nested public path, simply specify the [`base` config option](/config/shared-options.md#base) and all asset paths will be rewritten accordingly. This option can also be specified as a command line flag, e.g. `vite build --base=/my/public/path/`.\n\nJS-imported asset URLs, CSS `url()` references, and asset references in your `.html` files are all automatically adjusted to respect this option during build.\n\nThe exception is when you need to dynamically concatenate URLs on the fly. In this case, you can use the globally injected `import.meta.env.BASE_URL` variable which will be the public base path. Note this variable is statically replaced during build so it must appear exactly as-is (i.e. `import.meta.env['BASE_URL']` won't work).\n\nFor advanced base path control, check out [Advanced Base Options](#advanced-base-options).\n\n### Relative base\n\nIf you don't know the base path in advance, you may set a relative base path with `\"base\": \"./\"` or `\"base\": \"\"`. This will make all generated URLs to be relative to each file.\n\n:::warning Support for older browsers when using relative bases\n\n`import.meta` support is required for relative bases. If you need to support [browsers that do not support `import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta), you can use [the `legacy` plugin](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy).\n\n:::\n\n## Customizing the Build\n\nThe build can be customized via various [build config options](/config/build-options.md). Specifically, you can directly adjust the underlying [Rolldown options](https://rolldown.rs/reference/) via `build.rolldownOptions`:\n\n```js [vite.config.js]\nexport default defineConfig({\n  build: {\n    rolldownOptions: {\n      // https://rolldown.rs/reference/\n    },\n  },\n})\n```\n\nFor example, you can specify multiple Rolldown outputs with plugins that are only applied during build.\n\n## Chunking Strategy\n\nYou can configure how chunks are split using [`build.rolldownOptions.output.codeSplitting`](https://rolldown.rs/reference/OutputOptions.codeSplitting) (see [Rolldown docs](https://rolldown.rs/in-depth/manual-code-splitting)). If you use a framework, refer to their documentation for configuring how chunks are split.\n\n## Load Error Handling\n\nVite emits `vite:preloadError` event when it fails to load dynamic imports. `event.payload` contains the original import error. If you call `event.preventDefault()`, the error will not be thrown.\n\n```js twoslash\nwindow.addEventListener('vite:preloadError', (event) => {\n  window.location.reload() // for example, refresh the page\n})\n```\n\nWhen a new deployment occurs, the hosting service may delete the assets from previous deployments. As a result, a user who visited your site before the new deployment might encounter an import error. This error happens because the assets running on that user's device are outdated and it tries to import the corresponding old chunk, which is deleted. This event is useful for addressing this situation. In this case, make sure to set `Cache-Control: no-cache` on the HTML file, otherwise the old assets will be still referenced.\n\n## Rebuild on Files Changes\n\nYou can enable rollup watcher with `vite build --watch`. Or, you can directly adjust the underlying [`WatcherOptions`](https://rolldown.rs/reference/InputOptions.watch) via `build.watch`:\n\n```js [vite.config.js]\nexport default defineConfig({\n  build: {\n    watch: {\n      // https://rolldown.rs/reference/InputOptions.watch\n    },\n  },\n})\n```\n\nWith the `--watch` flag enabled, changes to files to be bundled will trigger a rebuild. Note that changes to the config and its dependencies require restarting the build command.\n\n## Multi-Page App\n\nSuppose you have the following source code structure:\n\n```\n├── package.json\n├── vite.config.js\n├── index.html\n├── main.js\n└── nested\n    ├── index.html\n    └── nested.js\n```\n\nDuring dev, simply navigate or link to `/nested/` - it works as expected, just like for a normal static file server.\n\nDuring build, all you need to do is to specify multiple `.html` files as entry points:\n\n```js twoslash [vite.config.js]\nimport { dirname, resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    rolldownOptions: {\n      input: {\n        main: resolve(import.meta.dirname, 'index.html'),\n        nested: resolve(import.meta.dirname, 'nested/index.html'),\n      },\n    },\n  },\n})\n```\n\nIf you specify a different root, remember that `import.meta.dirname` will still be the folder of your `vite.config.js` file when resolving the input paths. Therefore, you will need to add your `root` entry to the arguments for `resolve`.\n\nNote that for HTML files, Vite ignores the name given to the entry in the `rolldownOptions.input` object and instead respects the resolved id of the file when generating the HTML asset in the dist folder. This ensures a consistent structure with the way the dev server works.\n\n## Library Mode\n\nWhen you are developing a browser-oriented library, you are likely spending most of the time on a test/demo page that imports your actual library. With Vite, you can use your `index.html` for that purpose to get the smooth development experience.\n\nWhen it is time to bundle your library for distribution, use the [`build.lib` config option](/config/build-options.md#build-lib). Make sure to also externalize any dependencies that you do not want to bundle into your library, e.g. `vue` or `react`:\n\n::: code-group\n\n```js twoslash [vite.config.js (single entry)]\nimport { dirname, resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: resolve(import.meta.dirname, 'lib/main.js'),\n      name: 'MyLib',\n      // the proper extensions will be added\n      fileName: 'my-lib',\n    },\n    rolldownOptions: {\n      // make sure to externalize deps that shouldn't be bundled\n      // into your library\n      external: ['vue'],\n      output: {\n        // Provide global variables to use in the UMD build\n        // for externalized deps\n        globals: {\n          vue: 'Vue',\n        },\n      },\n    },\n  },\n})\n```\n\n```js twoslash [vite.config.js (multiple entries)]\nimport { dirname, resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: {\n        'my-lib': resolve(import.meta.dirname, 'lib/main.js'),\n        secondary: resolve(import.meta.dirname, 'lib/secondary.js'),\n      },\n      name: 'MyLib',\n    },\n    rolldownOptions: {\n      // make sure to externalize deps that shouldn't be bundled\n      // into your library\n      external: ['vue'],\n      output: {\n        // Provide global variables to use in the UMD build\n        // for externalized deps\n        globals: {\n          vue: 'Vue',\n        },\n      },\n    },\n  },\n})\n```\n\n:::\n\nThe entry file would contain exports that can be imported by users of your package:\n\n```js [lib/main.js]\nimport Foo from './Foo.vue'\nimport Bar from './Bar.vue'\nexport { Foo, Bar }\n```\n\nRunning `vite build` with this config uses a Rollup preset that is oriented towards shipping libraries and produces two bundle formats:\n\n- `es` and `umd` (for single entry)\n- `es` and `cjs` (for multiple entries)\n\nThe formats can be configured with the [`build.lib.formats`](/config/build-options.md#build-lib) option.\n\n```\n$ vite build\nbuilding for production...\ndist/my-lib.js      0.08 kB / gzip: 0.07 kB\ndist/my-lib.umd.cjs 0.30 kB / gzip: 0.16 kB\n```\n\nRecommended `package.json` for your lib:\n\n::: code-group\n\n```json [package.json (single entry)]\n{\n  \"name\": \"my-lib\",\n  \"type\": \"module\",\n  \"files\": [\"dist\"],\n  \"main\": \"./dist/my-lib.umd.cjs\",\n  \"module\": \"./dist/my-lib.js\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/my-lib.js\",\n      \"require\": \"./dist/my-lib.umd.cjs\"\n    }\n  }\n}\n```\n\n```json [package.json (multiple entries)]\n{\n  \"name\": \"my-lib\",\n  \"type\": \"module\",\n  \"files\": [\"dist\"],\n  \"main\": \"./dist/my-lib.cjs\",\n  \"module\": \"./dist/my-lib.js\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/my-lib.js\",\n      \"require\": \"./dist/my-lib.cjs\"\n    },\n    \"./secondary\": {\n      \"import\": \"./dist/secondary.js\",\n      \"require\": \"./dist/secondary.cjs\"\n    }\n  }\n}\n```\n\n:::\n\n### CSS support\n\nIf your library imports any CSS, it will be bundled as a single CSS file besides the built JS files, e.g. `dist/my-lib.css`. The name defaults to `build.lib.fileName`, but can also be changed with [`build.lib.cssFileName`](/config/build-options.md#build-lib).\n\nYou can export the CSS file in your `package.json` to be imported by users:\n\n```json {12}\n{\n  \"name\": \"my-lib\",\n  \"type\": \"module\",\n  \"files\": [\"dist\"],\n  \"main\": \"./dist/my-lib.umd.cjs\",\n  \"module\": \"./dist/my-lib.js\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./dist/my-lib.js\",\n      \"require\": \"./dist/my-lib.umd.cjs\"\n    },\n    \"./style.css\": \"./dist/my-lib.css\"\n  }\n}\n```\n\n::: tip File Extensions\nIf the `package.json` does not contain `\"type\": \"module\"`, Vite will generate different file extensions for Node.js compatibility. `.js` will become `.mjs` and `.cjs` will become `.js`.\n:::\n\n::: tip Environment Variables\nIn library mode, all [`import.meta.env.*`](./env-and-mode.md) usage are statically replaced when building for production. However, `process.env.*` usage are not, so that consumers of your library can dynamically change it. If this is undesirable, you can use `define: { 'process.env.NODE_ENV': '\"production\"' }` for example to statically replace them, or use [`esm-env`](https://github.com/benmccann/esm-env) for better compatibility with bundlers and runtimes.\n:::\n\n::: warning Advanced Usage\nLibrary mode includes a simple and opinionated configuration for browser-oriented and JS framework libraries. If you are building non-browser libraries, or require advanced build flows, you can use [tsdown](https://tsdown.dev/) or [Rolldown](https://rolldown.rs/) directly.\n:::\n\n## Advanced Base Options\n\n::: warning\nThis feature is experimental. [Give Feedback](https://github.com/vitejs/vite/discussions/13834).\n:::\n\nFor advanced use cases, the deployed assets and public files may be in different paths, for example to use different cache strategies.\nA user may choose to deploy in three different paths:\n\n- The generated entry HTML files (which may be processed during SSR)\n- The generated hashed assets (JS, CSS, and other file types like images)\n- The copied [public files](assets.md#the-public-directory)\n\nA single static [base](#public-base-path) isn't enough in these scenarios. Vite provides experimental support for advanced base options during build, using `experimental.renderBuiltUrl`.\n\n```ts twoslash\nimport type { UserConfig } from 'vite'\n// prettier-ignore\nconst config: UserConfig = {\n// ---cut-before---\nexperimental: {\n  renderBuiltUrl(filename, { hostType }) {\n    if (hostType === 'js') {\n      return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` }\n    } else {\n      return { relative: true }\n    }\n  },\n},\n// ---cut-after---\n}\n```\n\nIf the hashed assets and public files aren't deployed together, options for each group can be defined independently using asset `type` included in the second `context` param given to the function.\n\n```ts twoslash\nimport type { UserConfig } from 'vite'\nimport path from 'node:path'\n// prettier-ignore\nconst config: UserConfig = {\n// ---cut-before---\nexperimental: {\n  renderBuiltUrl(filename, { hostId, hostType, type }) {\n    if (type === 'public') {\n      return 'https://www.domain.com/' + filename\n    } else if (path.extname(hostId) === '.js') {\n      return {\n        runtime: `window.__assetsPath(${JSON.stringify(filename)})`\n      }\n    } else {\n      return 'https://cdn.domain.com/assets/' + filename\n    }\n  },\n},\n// ---cut-after---\n}\n```\n\nNote that the `filename` passed is a decoded URL, and if the function returns a URL string, it should also be decoded. Vite will handle the encoding automatically when rendering the URLs. If an object with `runtime` is returned, encoding should be handled yourself where needed as the runtime code will be rendered as is.\n"
  },
  {
    "path": "docs/guide/cli.md",
    "content": "# Command Line Interface\n\n## Dev server\n\n### `vite`\n\nStart Vite dev server in the current directory. `vite dev` and `vite serve` are aliases for `vite`.\n\n#### Usage\n\n```bash\nvite [root]\n```\n\n#### Options\n\n| Options                   |                                                                                                                                                                                       |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `--host [host]`           | Specify hostname (`string`)                                                                                                                                                           |\n| `--port <port>`           | Specify port (`number`)                                                                                                                                                               |\n| `--open [path]`           | Open browser on startup (`boolean \\| string`)                                                                                                                                         |\n| `--cors`                  | Enable CORS (`boolean`)                                                                                                                                                               |\n| `--strictPort`            | Exit if specified port is already in use (`boolean`)                                                                                                                                  |\n| `--force`                 | Force the optimizer to ignore the cache and re-bundle (`boolean`)                                                                                                                     |\n| `-c, --config <file>`     | Use specified config file (`string`)                                                                                                                                                  |\n| `--base <path>`           | Public base path (default: `/`) (`string`)                                                                                                                                            |\n| `-l, --logLevel <level>`  | info \\| warn \\| error \\| silent (`string`)                                                                                                                                            |\n| `--clearScreen`           | Allow/disable clear screen when logging (`boolean`)                                                                                                                                   |\n| `--configLoader <loader>` | Use `bundle` to bundle the config with Rolldown, or `runner` (experimental) to process it on the fly, or `native` (experimental) to load using the native runtime (default: `bundle`) |\n| `--profile`               | Start built-in Node.js inspector (check [Performance bottlenecks](/guide/troubleshooting#performance-bottlenecks))                                                                    |\n| `-d, --debug [feat]`      | Show debug logs (`string \\| boolean`)                                                                                                                                                 |\n| `-f, --filter <filter>`   | Filter debug logs (`string`)                                                                                                                                                          |\n| `-m, --mode <mode>`       | Set env mode (`string`)                                                                                                                                                               |\n| `-h, --help`              | Display available CLI options                                                                                                                                                         |\n| `-v, --version`           | Display version number                                                                                                                                                                |\n\n## Build\n\n### `vite build`\n\nBuild for production.\n\n#### Usage\n\n```bash\nvite build [root]\n```\n\n#### Options\n\n| Options                        |                                                                                                                         |\n| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |\n| `--target <target>`            | Transpile target (default: `\"modules\"`) (`string`)                                                                      |\n| `--outDir <dir>`               | Output directory (default: `dist`) (`string`)                                                                           |\n| `--assetsDir <dir>`            | Directory under outDir to place assets in (default: `\"assets\"`) (`string`)                                              |\n| `--assetsInlineLimit <number>` | Static asset base64 inline threshold in bytes (default: `4096`) (`number`)                                              |\n| `--ssr [entry]`                | Build specified entry for server-side rendering (`string`)                                                              |\n| `--sourcemap [output]`         | Output source maps for build (default: `false`) (`boolean \\| \"inline\" \\| \"hidden\"`)                                     |\n| `--minify [minifier]`          | Enable/disable minification, or specify minifier to use (default: `\"esbuild\"`) (`boolean \\| \"terser\" \\| \"esbuild\"`)     |\n| `--manifest [name]`            | Emit build manifest json (`boolean \\| string`)                                                                          |\n| `--ssrManifest [name]`         | Emit ssr manifest json (`boolean \\| string`)                                                                            |\n| `--emptyOutDir`                | Force empty outDir when it's outside of root (`boolean`)                                                                |\n| `-w, --watch`                  | Rebuilds when modules have changed on disk (`boolean`)                                                                  |\n| `-c, --config <file>`          | Use specified config file (`string`)                                                                                    |\n| `--base <path>`                | Public base path (default: `/`) (`string`)                                                                              |\n| `-l, --logLevel <level>`       | Info \\| warn \\| error \\| silent (`string`)                                                                              |\n| `--clearScreen`                | Allow/disable clear screen when logging (`boolean`)                                                                     |\n| `--configLoader <loader>`      | Use `bundle` to bundle the config with Rolldown or `runner` (experimental) to process it on the fly (default: `bundle`) |\n| `--profile`                    | Start built-in Node.js inspector (check [Performance bottlenecks](/guide/troubleshooting#performance-bottlenecks))      |\n| `-d, --debug [feat]`           | Show debug logs (`string \\| boolean`)                                                                                   |\n| `-f, --filter <filter>`        | Filter debug logs (`string`)                                                                                            |\n| `-m, --mode <mode>`            | Set env mode (`string`)                                                                                                 |\n| `-h, --help`                   | Display available CLI options                                                                                           |\n| `--app`                        | Build all environments, same as `builder: {}` (`boolean`, experimental)                                                 |\n\n## Others\n\n### `vite optimize`\n\nPre-bundle dependencies.\n\n**Deprecated**: the pre-bundle process runs automatically and does not need to be called.\n\n#### Usage\n\n```bash\nvite optimize [root]\n```\n\n#### Options\n\n| Options                   |                                                                                                                         |\n| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `--force`                 | Force the optimizer to ignore the cache and re-bundle (`boolean`)                                                       |\n| `-c, --config <file>`     | Use specified config file (`string`)                                                                                    |\n| `--base <path>`           | Public base path (default: `/`) (`string`)                                                                              |\n| `-l, --logLevel <level>`  | Info \\| warn \\| error \\| silent (`string`)                                                                              |\n| `--clearScreen`           | Allow/disable clear screen when logging (`boolean`)                                                                     |\n| `--configLoader <loader>` | Use `bundle` to bundle the config with Rolldown or `runner` (experimental) to process it on the fly (default: `bundle`) |\n| `-d, --debug [feat]`      | Show debug logs (`string \\| boolean`)                                                                                   |\n| `-f, --filter <filter>`   | Filter debug logs (`string`)                                                                                            |\n| `-m, --mode <mode>`       | Set env mode (`string`)                                                                                                 |\n| `-h, --help`              | Display available CLI options                                                                                           |\n\n### `vite preview`\n\nLocally preview the production build. Do not use this as a production server as it's not designed for it.\n\nThis command starts a server in the build directory (by default `dist`). Run `vite build` beforehand to ensure that the build directory is up-to-date. Depending on the project's configured [`appType`](/config/shared-options.html#apptype), it makes use of certain middleware.\n\n#### Usage\n\n```bash\nvite preview [root]\n```\n\n#### Options\n\n| Options                   |                                                                                                                         |\n| ------------------------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `--host [host]`           | Specify hostname (`string`)                                                                                             |\n| `--port <port>`           | Specify port (`number`)                                                                                                 |\n| `--strictPort`            | Exit if specified port is already in use (`boolean`)                                                                    |\n| `--open [path]`           | Open browser on startup (`boolean \\| string`)                                                                           |\n| `--outDir <dir>`          | Output directory (default: `dist`)(`string`)                                                                            |\n| `-c, --config <file>`     | Use specified config file (`string`)                                                                                    |\n| `--base <path>`           | Public base path (default: `/`) (`string`)                                                                              |\n| `-l, --logLevel <level>`  | Info \\| warn \\| error \\| silent (`string`)                                                                              |\n| `--clearScreen`           | Allow/disable clear screen when logging (`boolean`)                                                                     |\n| `--configLoader <loader>` | Use `bundle` to bundle the config with Rolldown or `runner` (experimental) to process it on the fly (default: `bundle`) |\n| `-d, --debug [feat]`      | Show debug logs (`string \\| boolean`)                                                                                   |\n| `-f, --filter <filter>`   | Filter debug logs (`string`)                                                                                            |\n| `-m, --mode <mode>`       | Set env mode (`string`)                                                                                                 |\n| `-h, --help`              | Display available CLI options                                                                                           |\n"
  },
  {
    "path": "docs/guide/dep-pre-bundling.md",
    "content": "# Dependency Pre-Bundling\n\nWhen you run `vite` for the first time, Vite prebundles your project dependencies before loading your site locally. It is done automatically and transparently by default.\n\n## The Why\n\nThis is Vite performing what we call \"dependency pre-bundling\". This process serves two purposes:\n\n1. **CommonJS and UMD compatibility:** During development, Vite serves all code as native ESM. Therefore, Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first.\n\n   When converting CommonJS dependencies, Vite performs smart import analysis so that named imports to CommonJS modules will work as expected even if the exports are dynamically assigned (e.g. React):\n\n   ```js\n   // works as expected\n   import React, { useState } from 'react'\n   ```\n\n2. **Performance:** Vite converts ESM dependencies with many internal modules into a single module to improve subsequent page load performance.\n\n   Some packages ship their ES modules builds as many separate files importing one another. For example, [`lodash-es` has over 600 internal modules](https://unpkg.com/browse/lodash-es/)! When we do `import { debounce } from 'lodash-es'`, the browser fires off 600+ HTTP requests at the same time! Even though the server has no problem handling them, the large amount of requests create a network congestion on the browser side, causing the page to load noticeably slower.\n\n   By pre-bundling `lodash-es` into a single module, we now only need one HTTP request instead!\n\n::: tip NOTE\nDependency pre-bundling only applies in development mode.\n:::\n\n## Automatic Dependency Discovery\n\nIf an existing cache is not found, Vite will crawl your source code and automatically discover dependency imports (i.e. \"bare imports\" that expect to be resolved from `node_modules`) and use these found imports as entry points for the pre-bundle. The pre-bundling is performed with [Rolldown](https://rolldown.rs/) so it's typically very fast.\n\nAfter the server has already started, if a new dependency import is encountered that isn't already in the cache, Vite will re-run the dep bundling process and reload the page if needed.\n\n## Monorepos and Linked Dependencies\n\nIn a monorepo setup, a dependency may be a linked package from the same repo. Vite automatically detects dependencies that are not resolved from `node_modules` and treats the linked dep as source code. It will not attempt to bundle the linked dep, and will analyze the linked dep's dependency list instead.\n\nHowever, this requires the linked dep to be exported as ESM. If not, you can add the dependency to [`optimizeDeps.include`](/config/dep-optimization-options.md#optimizedeps-include) in your config.\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\n// ---cut---\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['linked-dep'],\n  },\n})\n```\n\nWhen making changes to the linked dep, restart the dev server with the `--force` command line option for the changes to take effect.\n\n## Customizing the Behavior\n\nThe default dependency discovery heuristics may not always be desirable. In cases where you want to explicitly include/exclude dependencies from the list, use the [`optimizeDeps` config options](/config/dep-optimization-options.md).\n\nA typical use case for `optimizeDeps.include` or `optimizeDeps.exclude` is when you have an import that is not directly discoverable in the source code. For example, maybe the import is created as a result of a plugin transform. This means Vite won't be able to discover the import on the initial scan - it can only discover it after the file is requested by the browser and transformed. This will cause the server to immediately re-bundle after server start.\n\nBoth `include` and `exclude` can be used to deal with this. If the dependency is large (with many internal modules) or is CommonJS, then you should include it; If the dependency is small and is already valid ESM, you can exclude it and let the browser load it directly.\n\nYou can further customize Rolldown too with the [`optimizeDeps.rolldownOptions` option](/config/dep-optimization-options.md#optimizedeps-rolldownoptions). For example, adding a Rolldown plugin to handle special files in dependencies or changing the [build `target`](https://rolldown.rs/reference/InputOptions.transform#target).\n\n## Caching\n\n### File System Cache\n\nVite caches the pre-bundled dependencies in `node_modules/.vite`. It determines whether it needs to re-run the pre-bundling step based on a few sources:\n\n- Package manager lockfile content, e.g. `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` or `bun.lock`.\n- Patches folder modification time.\n- Relevant fields in your `vite.config.js`, if present.\n- `NODE_ENV` value.\n\nThe pre-bundling step will only need to be re-run when one of the above has changed.\n\nIf for some reason you want to force Vite to re-bundle deps, you can either start the dev server with the `--force` command line option, or manually delete the `node_modules/.vite` cache directory.\n\n### Browser Cache\n\nResolved dependency requests are strongly cached with HTTP headers `max-age=31536000,immutable` to improve page reload performance during dev. Once cached, these requests will never hit the dev server again. They are auto invalidated by the appended version query if a different version is installed (as reflected in your package manager lockfile). If you want to debug your dependencies by making local edits, you can:\n\n1. Temporarily disable cache via the Network tab of your browser devtools.\n2. Restart Vite dev server with the `--force` flag to re-bundle the deps.\n3. Reload the page.\n"
  },
  {
    "path": "docs/guide/env-and-mode.md",
    "content": "# Env Variables and Modes\n\nVite exposes certain constants under the special `import.meta.env` object. These constants are defined as global variables during dev and statically replaced at build time to make tree-shaking effective.\n\n:::details Example\n\n```js\nif (import.meta.env.DEV) {\n  // code inside here will be tree-shaken in production builds\n  console.log('Dev mode')\n}\n```\n\n:::\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq/~05an?via=vite\" title=\"Env Variables in Vite\">Watch an interactive lesson on Scrimba</ScrimbaLink>\n\n## Built-in Constants\n\nSome built-in constants are available in all cases:\n\n- **`import.meta.env.MODE`**: {string} the [mode](#modes) the app is running in.\n\n- **`import.meta.env.BASE_URL`**: {string} the base url the app is being served from. This is determined by the [`base` config option](/config/shared-options.md#base).\n\n- **`import.meta.env.PROD`**: {boolean} whether the app is running in production (running the dev server with `NODE_ENV='production'` or running an app built with `NODE_ENV='production'`).\n\n- **`import.meta.env.DEV`**: {boolean} whether the app is running in development (always the opposite of `import.meta.env.PROD`)\n\n- **`import.meta.env.SSR`**: {boolean} whether the app is running in the [server](./ssr.md#conditional-logic).\n\n## Env Variables\n\nVite exposes env variables under the `import.meta.env` object as strings automatically.\n\nVariables prefixed with `VITE_` will be exposed in client-side source code after Vite bundling. To prevent accidentally leaking env variables to the client, avoid using this prefix. As an example, consider the following:\n\n```[.env]\nVITE_SOME_KEY=123\nDB_PASSWORD=foobar\n```\n\nThe parsed value of `VITE_SOME_KEY` – `\"123\"` – will be exposed on the client, but the value of `DB_PASSWORD` will not. You can test this by adding the following to your code:\n\n```js\nconsole.log(import.meta.env.VITE_SOME_KEY) // \"123\"\nconsole.log(import.meta.env.DB_PASSWORD) // undefined\n```\n\nIf you want to customize the env variables prefix, see the [envPrefix](/config/shared-options.html#envprefix) option.\n\n:::tip Env parsing\nAs shown above, `VITE_SOME_KEY` is a number but returns a string when parsed. The same would also happen for boolean env variables. Make sure to convert to the desired type when using it in your code.\n:::\n\n:::warning Protecting secrets\n\n`VITE_*` variables should _not_ contain sensitive information such as API keys. The values of these variables are bundled into your source code at build time. For production deployments, consider a backend server or serverless/edge functions to properly secure secrets.\n\n:::\n\n### `.env` Files\n\nVite uses [dotenv](https://github.com/motdotla/dotenv) to load additional environment variables from the following files in your [environment directory](/config/shared-options.md#envdir):\n\n```\n.env                # loaded in all cases\n.env.local          # loaded in all cases, ignored by git\n.env.[mode]         # only loaded in specified mode\n.env.[mode].local   # only loaded in specified mode, ignored by git\n```\n\n:::tip Env Loading Priorities\n\nAn env file for a specific mode (e.g. `.env.production`) will take higher priority than a generic one (e.g. `.env`).\n\nVite will always load `.env` and `.env.local` in addition to the mode-specific `.env.[mode]` file. Variables declared in mode-specific files will take precedence over those in generic files, but variables defined only in `.env` or `.env.local` will still be available in the environment.\n\nIn addition, environment variables that already exist when Vite is executed have the highest priority and will not be overwritten by `.env` files. For example, when running `VITE_SOME_KEY=123 vite build`.\n\n`.env` files are loaded at the start of Vite. Restart the server after making changes.\n\n:::\n\n:::warning Bun users\n\nWhen using [Bun](https://bun.sh), be aware that Bun automatically loads `.env` files before your script runs. This built-in behavior loads environment variables directly into `process.env` and can interfere with Vite's feature, as it respects existing `process.env` values. See [oven-sh/bun#5515](https://github.com/oven-sh/bun/issues/5515) for workarounds.\n\n:::\n\nAlso, Vite uses [dotenv-expand](https://github.com/motdotla/dotenv-expand) to expand variables written in env files out of the box. To learn more about the syntax, check out [their docs](https://github.com/motdotla/dotenv-expand#what-rules-does-the-expansion-engine-follow).\n\nNote that if you want to use `$` inside your environment value, you have to escape it with `\\`.\n\n```[.env]\nKEY=123\nNEW_KEY1=test$foo   # test\nNEW_KEY2=test\\$foo  # test$foo\nNEW_KEY3=test$KEY   # test123\n```\n\n::: details Expanding variables in reverse order\n\nVite supports expanding variables in reverse order.\nFor example, the `.env` below will be evaluated as `VITE_FOO=foobar`, `VITE_BAR=bar`.\n\n```[.env]\nVITE_FOO=foo${VITE_BAR}\nVITE_BAR=bar\n```\n\nThis does not work in shell scripts and other tools like `docker compose`.\nThat said, Vite supports this behavior as this has been supported by `dotenv-expand` for a long time and other tools in JavaScript ecosystem use older versions that support this behavior.\n\nTo avoid interop issues, it is recommended to avoid relying on this behavior. Vite may start emitting warnings for this behavior in the future.\n\n:::\n\n:::warning Ignoring local `.env` files\n\n`.env.*.local` files are local-only and can contain sensitive variables. You should add `*.local` to your `.gitignore` to avoid them being checked into git.\n\n:::\n\n## IntelliSense for TypeScript\n\nBy default, Vite provides type definitions for `import.meta.env` in [`vite/client.d.ts`](https://github.com/vitejs/vite/blob/main/packages/vite/client.d.ts). While you can define more custom env variables in `.env.[mode]` files, you may want to get TypeScript IntelliSense for user-defined env variables that are prefixed with `VITE_`.\n\nTo achieve this, you can create an `vite-env.d.ts` in `src` directory, then augment `ImportMetaEnv` like this:\n\n```typescript [vite-env.d.ts]\ninterface ViteTypeOptions {\n  // By adding this line, you can make the type of ImportMetaEnv strict\n  // to disallow unknown keys.\n  // strictImportMetaEnv: unknown\n}\n\ninterface ImportMetaEnv {\n  readonly VITE_APP_TITLE: string\n  // more env variables...\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv\n}\n```\n\nIf your code relies on types from browser environments such as [DOM](https://github.com/microsoft/TypeScript/blob/main/src/lib/dom.generated.d.ts) and [WebWorker](https://github.com/microsoft/TypeScript/blob/main/src/lib/webworker.generated.d.ts), you can update the [lib](https://www.typescriptlang.org/tsconfig#lib) field in `tsconfig.json`.\n\n```json [tsconfig.json]\n{\n  \"lib\": [\"WebWorker\"]\n}\n```\n\n:::warning Imports will break type augmentation\n\nIf the `ImportMetaEnv` augmentation does not work, make sure you do not have any `import` statements in `vite-env.d.ts`. See the [TypeScript documentation](https://www.typescriptlang.org/docs/handbook/2/modules.html#how-javascript-modules-are-defined) for more information.\n\n:::\n\n## HTML Constant Replacement\n\nVite also supports replacing constants in HTML files. Any properties in `import.meta.env` can be used in HTML files with a special `%CONST_NAME%` syntax:\n\n```html\n<h1>Vite is running in %MODE%</h1>\n<p>Using data from %VITE_API_URL%</p>\n```\n\nIf the env doesn't exist in `import.meta.env`, e.g. `%NON_EXISTENT%`, it will be ignored and not replaced, unlike `import.meta.env.NON_EXISTENT` in JS where it's replaced as `undefined`.\n\nGiven that Vite is used by many frameworks, it is intentionally unopinionated about complex replacements like conditionals. Vite can be extended using [an existing userland plugin](https://github.com/vitejs/awesome-vite#transformers) or a custom plugin that implements the [`transformIndexHtml` hook](./api-plugin#transformindexhtml).\n\n## Modes\n\nBy default, the dev server (`dev` command) runs in `development` mode and the `build` command runs in `production` mode.\n\nThis means when running `vite build`, it will load the env variables from `.env.production` if there is one:\n\n```[.env.production]\nVITE_APP_TITLE=My App\n```\n\nIn your app, you can render the title using `import.meta.env.VITE_APP_TITLE`.\n\nIn some cases, you may want to run `vite build` with a different mode to render a different title. You can overwrite the default mode used for a command by passing the `--mode` option flag. For example, if you want to build your app for a staging mode:\n\n```bash\nvite build --mode staging\n```\n\nAnd create a `.env.staging` file:\n\n```[.env.staging]\nVITE_APP_TITLE=My App (staging)\n```\n\nAs `vite build` runs a production build by default, you can also change this and run a development build by using a different mode and `.env` file configuration:\n\n```[.env.testing]\nNODE_ENV=development\n```\n\n### NODE_ENV and Modes\n\nIt's important to note that `NODE_ENV` (`process.env.NODE_ENV`) and modes are two different concepts. Here's how different commands affect the `NODE_ENV` and mode:\n\n| Command                                              | NODE_ENV        | Mode            |\n| ---------------------------------------------------- | --------------- | --------------- |\n| `vite build`                                         | `\"production\"`  | `\"production\"`  |\n| `vite build --mode development`                      | `\"production\"`  | `\"development\"` |\n| `NODE_ENV=development vite build`                    | `\"development\"` | `\"production\"`  |\n| `NODE_ENV=development vite build --mode development` | `\"development\"` | `\"development\"` |\n\nThe different values of `NODE_ENV` and mode also reflect on its corresponding `import.meta.env` properties:\n\n| Command                | `import.meta.env.PROD` | `import.meta.env.DEV` |\n| ---------------------- | ---------------------- | --------------------- |\n| `NODE_ENV=production`  | `true`                 | `false`               |\n| `NODE_ENV=development` | `false`                | `true`                |\n| `NODE_ENV=other`       | `false`                | `true`                |\n\n| Command              | `import.meta.env.MODE` |\n| -------------------- | ---------------------- |\n| `--mode production`  | `\"production\"`         |\n| `--mode development` | `\"development\"`        |\n| `--mode staging`     | `\"staging\"`            |\n\n:::tip `NODE_ENV` in `.env` files\n\n`NODE_ENV=...` can be set in the command, and also in your `.env` file. If `NODE_ENV` is specified in a `.env.[mode]` file, the mode can be used to control its value. However, both `NODE_ENV` and modes remain as two different concepts.\n\nThe main benefit with `NODE_ENV=...` in the command is that it allows Vite to detect the value early. It also allows you to read `process.env.NODE_ENV` in your Vite config as Vite can only load the env files once the config is evaluated.\n:::\n"
  },
  {
    "path": "docs/guide/features.md",
    "content": "# Features\n\nAt the very basic level, developing using Vite is not that different from using a static file server. However, Vite provides many enhancements over native ESM imports to support various features that are typically seen in bundler-based setups.\n\n## npm Dependency Resolving and Pre-Bundling\n\nNative ES imports do not support bare module imports like the following:\n\n```js\nimport { someMethod } from 'my-dep'\n```\n\nThe above import will throw an error in the browser. Vite will detect such bare module imports in all served source files and perform the following:\n\n1. [Pre-bundle](./dep-pre-bundling) them to improve page loading speed and convert CommonJS / UMD modules to ESM. The pre-bundling step is performed with [esbuild](https://esbuild.github.io/) and makes Vite's cold start time significantly faster than any JavaScript-based bundler.\n\n2. Rewrite the imports to valid URLs like `/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd` so that the browser can import them properly.\n\n**Dependencies are Strongly Cached**\n\nVite caches dependency requests via HTTP headers, so if you wish to locally edit/debug a dependency, follow the steps [here](./dep-pre-bundling#browser-cache).\n\n## Hot Module Replacement\n\nVite provides an [HMR API](./api-hmr) over native ESM. Frameworks with HMR capabilities can leverage the API to provide instant, precise updates without reloading the page or blowing away application state. Vite provides first-party HMR integrations for [Vue Single File Components](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue) and [React Fast Refresh](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react). There are also official integrations for Preact via [@prefresh/vite](https://github.com/JoviDeCroock/prefresh/tree/main/packages/vite).\n\nNote you don't need to manually set these up - when you [create an app via `create-vite`](./), the selected templates would have these pre-configured for you already.\n\n## TypeScript\n\nVite supports importing `.ts` files out of the box.\n\n### Transpile Only\n\nNote that Vite only performs transpilation on `.ts` files and does **NOT** perform type checking. It assumes type checking is taken care of by your IDE and build process.\n\nThe reason Vite does not perform type checking as part of the transform process is because the two jobs work fundamentally differently. Transpilation can work on a per-file basis and aligns perfectly with Vite's on-demand compile model. In comparison, type checking requires knowledge of the entire module graph. Shoe-horning type checking into Vite's transform pipeline will inevitably compromise Vite's speed benefits.\n\nVite's job is to get your source modules into a form that can run in the browser as fast as possible. To that end, we recommend separating static analysis checks from Vite's transform pipeline. This principle applies to other static analysis checks such as ESLint.\n\n- For production builds, you can run `tsc --noEmit` in addition to Vite's build command.\n\n- During development, if you need more than IDE hints, we recommend running `tsc --noEmit --watch` in a separate process, or use [vite-plugin-checker](https://github.com/fi3ework/vite-plugin-checker) if you prefer having type errors directly reported in the browser.\n\nVite uses [esbuild](https://github.com/evanw/esbuild) to transpile TypeScript into JavaScript which is about 20~30x faster than vanilla `tsc`, and HMR updates can reflect in the browser in under 50ms.\n\nUse the [Type-Only Imports and Export](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax to avoid potential problems like type-only imports being incorrectly bundled, for example:\n\n```ts\nimport type { T } from 'only/types'\nexport type { T }\n```\n\n### TypeScript Compiler Options\n\nVite respects some of the options in `tsconfig.json` and sets the corresponding esbuild options. For each file, Vite uses the `tsconfig.json` in the closest parent directory. If that `tsconfig.json` contains a [`references`](https://www.typescriptlang.org/tsconfig/#references) field, Vite will use the referenced config file that satisfies the [`include`](https://www.typescriptlang.org/tsconfig/#include) and [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) fields.\n\nWhen the options are set in both the Vite config and the `tsconfig.json`, the value in the Vite config takes precedence.\n\nSome configuration fields under `compilerOptions` in `tsconfig.json` require special attention.\n\n#### `isolatedModules`\n\n- [TypeScript documentation](https://www.typescriptlang.org/tsconfig#isolatedModules)\n\nShould be set to `true`.\n\nIt is because `esbuild` only performs transpilation without type information, it doesn't support certain features like const enum and implicit type-only imports.\n\nYou must set `\"isolatedModules\": true` in your `tsconfig.json` under `compilerOptions`, so that TS will warn you against the features that do not work with isolated transpilation.\n\nIf a dependency doesn't work well with `\"isolatedModules\": true`, you can use `\"skipLibCheck\": true` to temporarily suppress the errors until it is fixed upstream.\n\n#### `useDefineForClassFields`\n\n- [TypeScript documentation](https://www.typescriptlang.org/tsconfig#useDefineForClassFields)\n\nThe default value will be `true` if the TypeScript target is `ES2022` or newer including `ESNext`. It is consistent with the [behavior of TypeScript 4.3.2+](https://github.com/microsoft/TypeScript/pull/42663).\nOther TypeScript targets will default to `false`.\n\n`true` is the standard ECMAScript runtime behavior.\n\nIf you are using a library that heavily relies on class fields, please be careful about the library's intended usage of it.\nWhile most libraries expect `\"useDefineForClassFields\": true`, you can explicitly set `useDefineForClassFields` to `false` if your library doesn't support it.\n\n#### `target`\n\n- [TypeScript documentation](https://www.typescriptlang.org/tsconfig#target)\n\nVite ignores the `target` value in the `tsconfig.json`, following the same behavior as `esbuild`.\n\nTo specify the target in dev, the [`esbuild.target`](/config/shared-options.html#esbuild) option can be used, which defaults to `esnext` for minimal transpilation. In builds, the [`build.target`](/config/build-options.html#build-target) option takes higher priority over `esbuild.target` and can also be set if needed.\n\n#### `emitDecoratorMetadata`\n\n- [TypeScript documentation](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata)\n\nThis option is only partially supported. Full support requires type inference by the TypeScript compiler, which is not supported. See [Oxc Transformer's documentation](https://oxc.rs/docs/guide/usage/transformer/typescript#decorators) for details.\n\n#### `paths`\n\n- [TypeScript documentation](https://www.typescriptlang.org/tsconfig/#paths)\n\n`resolve.tsconfigPaths: true` can be specified to tell Vite to use the `paths` option in `tsconfig.json` to resolve imports.\n\nNote that this feature has a performance cost and is [discouraged by the TypeScript team to use this option to change the behavior of the external tools](https://www.typescriptlang.org/tsconfig/#paths:~:text=Note%20that%20this%20feature%20does%20not%20change%20how%20import%20paths%20are%20emitted%20by%20tsc%2C%20so%20paths%20should%20only%20be%20used%20to%20inform%20TypeScript%20that%20another%20tool%20has%20this%20mapping%20and%20will%20use%20it%20at%20runtime%20or%20when%20bundling.).\n\n#### Other Compiler Options Affecting the Build Result\n\n- [`extends`](https://www.typescriptlang.org/tsconfig#extends)\n- [`importsNotUsedAsValues`](https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues)\n- [`preserveValueImports`](https://www.typescriptlang.org/tsconfig#preserveValueImports)\n- [`verbatimModuleSyntax`](https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax)\n- [`jsx`](https://www.typescriptlang.org/tsconfig#jsx)\n- [`jsxFactory`](https://www.typescriptlang.org/tsconfig#jsxFactory)\n- [`jsxFragmentFactory`](https://www.typescriptlang.org/tsconfig#jsxFragmentFactory)\n- [`jsxImportSource`](https://www.typescriptlang.org/tsconfig#jsxImportSource)\n- [`experimentalDecorators`](https://www.typescriptlang.org/tsconfig#experimentalDecorators)\n\n::: tip `skipLibCheck`\nVite starter templates have `\"skipLibCheck\": \"true\"` by default to avoid typechecking dependencies, as they may choose to only support specific versions and configurations of TypeScript. You can learn more at [vuejs/vue-cli#5688](https://github.com/vuejs/vue-cli/pull/5688).\n:::\n\n### Client Types\n\nVite's default types are for its Node.js API. To shim the environment of client-side code in a Vite application, you can add `vite/client` to `compilerOptions.types` inside `tsconfig.json`:\n\n```json [tsconfig.json]\n{\n  \"compilerOptions\": {\n    \"types\": [\"vite/client\", \"some-other-global-lib\"]\n  }\n}\n```\n\nNote that if [`compilerOptions.types`](https://www.typescriptlang.org/tsconfig#types) is specified, only these packages will be included in the global scope (instead of all visible ”@types” packages). This is recommended since TS 5.9.\n\n::: details Using triple-slash directive\n\nAlternatively, you can add a `d.ts` declaration file:\n\n```typescript [vite-env.d.ts]\n/// <reference types=\"vite/client\" />\n```\n\n:::\n\n`vite/client` provides the following type shims:\n\n- Asset imports (e.g. importing an `.svg` file)\n- Types for the Vite-injected [constants](./env-and-mode#env-variables) on `import.meta.env`\n- Types for the [HMR API](./api-hmr) on `import.meta.hot`\n\n::: tip\nTo override the default typing, add a type definition file that contains your typings. Then, add the type reference before `vite/client`.\n\nFor example, to make the default import of `*.svg` a React component:\n\n- `vite-env-override.d.ts` (the file that contains your typings):\n  ```ts\n  declare module '*.svg' {\n    const content: React.FC<React.SVGProps<SVGElement>>\n    export default content\n  }\n  ```\n- If you are using `compilerOptions.types`, ensure the file is included in `tsconfig.json`:\n  ```json [tsconfig.json]\n  {\n    \"include\": [\"src\", \"./vite-env-override.d.ts\"]\n  }\n  ```\n- If you are using triple-slash directives, update the file containing the reference to `vite/client` (normally `vite-env.d.ts`):\n  ```ts\n  /// <reference types=\"./vite-env-override.d.ts\" />\n  /// <reference types=\"vite/client\" />\n  ```\n\n:::\n\n## HTML\n\nHTML files stand [front-and-center](/guide/#index-html-and-project-root) of a Vite project, serving as the entry points for your application, making it simple to build single-page and [multi-page applications](/guide/build.html#multi-page-app).\n\nAny HTML files in your project root can be directly accessed by its respective directory path:\n\n- `<root>/index.html` -> `http://localhost:5173/`\n- `<root>/about.html` -> `http://localhost:5173/about.html`\n- `<root>/blog/index.html` -> `http://localhost:5173/blog/index.html`\n\nAssets referenced by HTML elements such as `<script type=\"module\" src>` and `<link href>` are processed and bundled as part of the app. The full list of supported elements are as below:\n\n- `<audio src>`\n- `<embed src>`\n- `<img src>` and `<img srcset>`\n- `<image href>` and `<image xlink:href>`\n- `<input src>`\n- `<link href>` and `<link imagesrcset>`\n- `<object data>`\n- `<script type=\"module\" src>`\n- `<source src>` and `<source srcset>`\n- `<track src>`\n- `<use href>` and `<use xlink:href>`\n- `<video src>` and `<video poster>`\n- `<meta content>`\n  - Only if `name` attribute matches `msapplication-tileimage`, `msapplication-square70x70logo`, `msapplication-square150x150logo`, `msapplication-wide310x150logo`, `msapplication-square310x310logo`, `msapplication-config`, or `twitter:image`\n  - Or only if `property` attribute matches `og:image`, `og:image:url`, `og:image:secure_url`, `og:audio`, `og:audio:secure_url`, `og:video`, or `og:video:secure_url`\n\n```html {4-5,8-9}\n<!doctype html>\n<html>\n  <head>\n    <link rel=\"icon\" href=\"/favicon.ico\" />\n    <link rel=\"stylesheet\" href=\"/src/styles.css\" />\n  </head>\n  <body>\n    <img src=\"/src/images/logo.svg\" alt=\"logo\" />\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n```\n\nTo opt-out of HTML processing on certain elements, you can add the `vite-ignore` attribute on the element, which can be useful when referencing external assets or CDN.\n\n## Frameworks\n\nAll modern frameworks maintain integrations with Vite. Most framework plugins are maintained by each framework team, with the exception of the official Vue and React Vite plugins that are maintained in the vite org:\n\n- Vue support via [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue)\n- Vue JSX support via [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx)\n- React support via [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react)\n- React using SWC support via [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react-swc)\n- [React Server Components (RSC)](https://react.dev/reference/rsc/server-components) support via [@vitejs/plugin-rsc](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc)\n\nCheck out the [Plugins Guide](/plugins/) for more information.\n\n## JSX\n\n`.jsx` and `.tsx` files are also supported out of the box. JSX transpilation is also handled via [esbuild](https://esbuild.github.io).\n\nYour framework of choice will already configure JSX out of the box (for example, Vue users should use the official [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx) plugin, which provides Vue 3 specific features including HMR, global component resolving, directives and slots).\n\nIf using JSX with your own framework, custom `jsxFactory` and `jsxFragment` can be configured using the [`esbuild` option](/config/shared-options.md#esbuild). For example, the Preact plugin would use:\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  esbuild: {\n    jsxFactory: 'h',\n    jsxFragment: 'Fragment',\n  },\n})\n```\n\nMore details in [esbuild docs](https://esbuild.github.io/content-types/#jsx).\n\nYou can inject the JSX helpers using `jsxInject` (which is a Vite-only option) to avoid manual imports:\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  esbuild: {\n    jsxInject: `import React from 'react'`,\n  },\n})\n```\n\n## CSS\n\nImporting `.css` files will inject its content to the page via a `<style>` tag with HMR support.\n\n### `@import` Inlining and Rebasing\n\nVite is pre-configured to support CSS `@import` inlining via `postcss-import`. Vite aliases are also respected for CSS `@import`. In addition, all CSS `url()` references, even if the imported files are in different directories, are always automatically rebased to ensure correctness.\n\n`@import` aliases and URL rebasing are also supported for Sass and Less files (see [CSS Pre-processors](#css-pre-processors)).\n\n### PostCSS\n\nIf the project contains valid PostCSS config (any format supported by [postcss-load-config](https://github.com/postcss/postcss-load-config), e.g. `postcss.config.js`), it will be automatically applied to all imported CSS.\n\nNote that CSS minification will run after PostCSS and will use [`build.cssTarget`](/config/build-options.md#build-csstarget) option.\n\n### CSS Modules\n\nAny CSS file ending with `.module.css` is considered a [CSS modules file](https://github.com/css-modules/css-modules). Importing such a file will return the corresponding module object:\n\n```css [example.module.css]\n.red {\n  color: red;\n}\n```\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport classes from './example.module.css'\ndocument.getElementById('foo').className = classes.red\n```\n\nCSS modules behavior can be configured via the [`css.modules` option](/config/shared-options.md#css-modules).\n\nIf `css.modules.localsConvention` is set to enable camelCase locals (e.g. `localsConvention: 'camelCaseOnly'`), you can also use named imports:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// .apply-color -> applyColor\nimport { applyColor } from './example.module.css'\ndocument.getElementById('foo').className = applyColor\n```\n\n### CSS Pre-processors\n\nBecause Vite targets modern browsers only, it is recommended to use native CSS variables with PostCSS plugins that implement CSSWG drafts (e.g. [postcss-nesting](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting)) and author plain, future-standards-compliant CSS.\n\nThat said, Vite does provide built-in support for `.scss`, `.sass`, `.less`, `.styl` and `.stylus` files. There is no need to install Vite-specific plugins for them, but the corresponding pre-processor itself must be installed:\n\n```bash\n# .scss and .sass\nnpm add -D sass-embedded # or sass\n\n# .less\nnpm add -D less\n\n# .styl and .stylus\nnpm add -D stylus\n```\n\nIf using Vue single file components, this also automatically enables `<style lang=\"sass\">` et al.\n\nVite improves `@import` resolving for Sass and Less so that Vite aliases are also respected. In addition, relative `url()` references inside imported Sass/Less files that are in different directories from the root file are also automatically rebased to ensure correctness. Rebasing `url()` references that start with a variable or a interpolation are not supported due to its API constraints.\n\n`@import` alias and url rebasing are not supported for Stylus due to its API constraints.\n\nYou can also use CSS modules combined with pre-processors by prepending `.module` to the file extension, for example `style.module.scss`.\n\n### Disabling CSS injection into the page\n\nThe automatic injection of CSS contents can be turned off via the `?inline` query parameter. In this case, the processed CSS string is returned as the module's default export as usual, but the styles aren't injected to the page.\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport './foo.css' // will be injected into the page\nimport otherStyles from './bar.css?inline' // will not be injected\n```\n\n::: tip NOTE\nDefault and named imports from CSS files (e.g `import style from './foo.css'`) are removed since Vite 5. Use the `?inline` query instead.\n:::\n\n### Lightning CSS\n\nStarting from Vite 4.4, there is experimental support for [Lightning CSS](https://lightningcss.dev/). You can opt into it by adding [`css.transformer: 'lightningcss'`](../config/shared-options.md#css-transformer) to your config file and install the optional [`lightningcss`](https://www.npmjs.com/package/lightningcss) dependency:\n\n```bash\nnpm add -D lightningcss\n```\n\nIf enabled, CSS files will be processed by Lightning CSS instead of PostCSS. To configure it, you can pass Lightning CSS options to the [`css.lightningcss`](../config/shared-options.md#css-lightningcss) config option.\n\nTo configure CSS Modules, you'll use [`css.lightningcss.cssModules`](https://lightningcss.dev/css-modules.html) instead of [`css.modules`](../config/shared-options.md#css-modules) (which configures the way PostCSS handles CSS modules).\n\nBy default, Vite uses esbuild to minify CSS. Lightning CSS can also be used as the CSS minifier with [`build.cssMinify: 'lightningcss'`](../config/build-options.md#build-cssminify).\n\n## Static Assets\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq/~05pq?via=vite\" title=\"Static Assets in Vite\">Watch an interactive lesson on Scrimba</ScrimbaLink>\n\nImporting a static asset will return the resolved public URL when it is served:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport imgUrl from './img.png'\ndocument.getElementById('hero-img').src = imgUrl\n```\n\nSpecial queries can modify how assets are loaded:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// Explicitly load assets as URL (automatically inlined depending on the file size)\nimport assetAsURL from './asset.js?url'\n```\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// Load assets as strings\nimport assetAsString from './shader.glsl?raw'\n```\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// Load Web Workers\nimport Worker from './worker.js?worker'\n```\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// Web Workers inlined as base64 strings at build time\nimport InlineWorker from './worker.js?worker&inline'\n```\n\nMore details in [Static Asset Handling](./assets).\n\n## JSON\n\nJSON files can be directly imported - named imports are also supported:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\n// import the entire object\nimport json from './example.json'\n// import a root field as named exports - helps with tree-shaking!\nimport { field } from './example.json'\n```\n\n## Glob Import\n\nVite supports importing multiple modules from the file system via the special `import.meta.glob` function:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob('./dir/*.js')\n```\n\nThe above will be transformed into the following:\n\n```js\n// code produced by vite\nconst modules = {\n  './dir/bar.js': () => import('./dir/bar.js'),\n  './dir/foo.js': () => import('./dir/foo.js'),\n}\n```\n\nYou can then iterate over the keys of the `modules` object to access the corresponding modules:\n\n```js\nfor (const path in modules) {\n  modules[path]().then((mod) => {\n    console.log(path, mod)\n  })\n}\n```\n\nMatched files are by default lazy-loaded via dynamic import and will be split into separate chunks during build. If you'd rather import all the modules directly (e.g. relying on side-effects in these modules to be applied first), you can pass `{ eager: true }` as the second argument:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob('./dir/*.js', { eager: true })\n```\n\nThe above will be transformed into the following:\n\n```js\n// code produced by vite\nimport * as __vite_glob_0_0 from './dir/bar.js'\nimport * as __vite_glob_0_1 from './dir/foo.js'\nconst modules = {\n  './dir/bar.js': __vite_glob_0_0,\n  './dir/foo.js': __vite_glob_0_1,\n}\n```\n\n### Multiple Patterns\n\nThe first argument can be an array of globs, for example\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob(['./dir/*.js', './another/*.js'])\n```\n\n### Negative Patterns\n\nNegative glob patterns are also supported (prefixed with `!`). To ignore some files from the result, you can add exclude glob patterns to the first argument:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])\n```\n\n```js\n// code produced by vite\nconst modules = {\n  './dir/foo.js': () => import('./dir/foo.js'),\n}\n```\n\n#### Named Imports\n\nIt's possible to only import parts of the modules with the `import` options.\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob('./dir/*.js', { import: 'setup' })\n```\n\n```ts\n// code produced by vite\nconst modules = {\n  './dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),\n  './dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),\n}\n```\n\nWhen combined with `eager` it's even possible to have tree-shaking enabled for those modules.\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob('./dir/*.js', {\n  import: 'setup',\n  eager: true,\n})\n```\n\n```ts\n// code produced by vite:\nimport { setup as __vite_glob_0_0 } from './dir/bar.js'\nimport { setup as __vite_glob_0_1 } from './dir/foo.js'\nconst modules = {\n  './dir/bar.js': __vite_glob_0_0,\n  './dir/foo.js': __vite_glob_0_1,\n}\n```\n\nSet `import` to `default` to import the default export.\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob('./dir/*.js', {\n  import: 'default',\n  eager: true,\n})\n```\n\n```ts\n// code produced by vite:\nimport { default as __vite_glob_0_0 } from './dir/bar.js'\nimport { default as __vite_glob_0_1 } from './dir/foo.js'\nconst modules = {\n  './dir/bar.js': __vite_glob_0_0,\n  './dir/foo.js': __vite_glob_0_1,\n}\n```\n\n#### Custom Queries\n\nYou can also use the `query` option to provide queries to imports, for example, to import assets [as a string](/guide/assets.html#importing-asset-as-string) or [as a url](/guide/assets.html#importing-asset-as-url):\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\nconst moduleStrings = import.meta.glob('./dir/*.svg', {\n  query: '?raw',\n  import: 'default',\n})\nconst moduleUrls = import.meta.glob('./dir/*.svg', {\n  query: '?url',\n  import: 'default',\n})\n```\n\n```ts\n// code produced by vite:\nconst moduleStrings = {\n  './dir/bar.svg': () => import('./dir/bar.svg?raw').then((m) => m['default']),\n  './dir/foo.svg': () => import('./dir/foo.svg?raw').then((m) => m['default']),\n}\nconst moduleUrls = {\n  './dir/bar.svg': () => import('./dir/bar.svg?url').then((m) => m['default']),\n  './dir/foo.svg': () => import('./dir/foo.svg?url').then((m) => m['default']),\n}\n```\n\nYou can also provide custom queries for other plugins to consume:\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\nconst modules = import.meta.glob('./dir/*.js', {\n  query: { foo: 'bar', bar: true },\n})\n```\n\n#### Base Path\n\nYou can also use the `base` option to provide base path for the imports:\n\n```ts twoslash\nimport 'vite/client'\n// ---cut---\nconst modulesWithBase = import.meta.glob('./**/*.js', {\n  base: './base',\n})\n```\n\n```ts\n// code produced by vite:\nconst modulesWithBase = {\n  './dir/foo.js': () => import('./base/dir/foo.js'),\n  './dir/bar.js': () => import('./base/dir/bar.js'),\n}\n```\n\nThe base option can only be a directory path relative to the importer file or absolute against the project root. Aliases and virtual modules aren't supported.\n\nOnly the globs that are relative paths are interpreted as relative to the resolved base.\n\nAll the resulting module keys are modified to be relative to the base if provided.\n\n### Glob Import Caveats\n\nNote that:\n\n- This is a Vite-only feature and is not a web or ES standard.\n- The glob patterns are treated like import specifiers: they must be either relative (start with `./`) or absolute (start with `/`, resolved relative to project root) or an alias path (see [`resolve.alias` option](/config/shared-options.md#resolve-alias)).\n- The glob matching is done via [`tinyglobby`](https://github.com/SuperchupuDev/tinyglobby) - check out its documentation for [supported glob patterns](https://superchupu.dev/tinyglobby/comparison).\n- You should also be aware that all the arguments in the `import.meta.glob` must be **passed as literals**. You can NOT use variables or expressions in them.\n\n## Dynamic Import\n\nSimilar to [glob import](#glob-import), Vite also supports dynamic import with variables.\n\n```ts\nconst module = await import(`./dir/${file}.js`)\n```\n\nNote that variables only represent file names one level deep. If `file` is `'foo/bar'`, the import would fail. For more advanced usage, you can use the [glob import](#glob-import) feature.\n\nAlso note that the dynamic import must match the following rules to be bundled:\n\n- Imports must start with `./` or `../`: ``import(`./dir/${foo}.js`)`` is valid, but ``import(`${foo}.js`)`` is not.\n- Imports must end with a file extension: ``import(`./dir/${foo}.js`)`` is valid, but ``import(`./dir/${foo}`)`` is not.\n- Imports to the own directory must specify a file name pattern: ``import(`./prefix-${foo}.js`)`` is valid, but ``import(`./${foo}.js`)`` is not.\n\nThese rules are enforced to prevent accidentally importing files that are not intended to be bundled. For example, without these rules, `import(foo)` would bundle everything in the file system.\n\n## WebAssembly\n\nPre-compiled `.wasm` files can be imported with `?init`.\nThe default export will be an initialization function that returns a Promise of the [`WebAssembly.Instance`](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Instance):\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport init from './example.wasm?init'\n\ninit().then((instance) => {\n  instance.exports.test()\n})\n```\n\nThe init function can also take an importObject which is passed along to [`WebAssembly.instantiate`](https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/instantiate) as its second argument:\n\n```js twoslash\nimport 'vite/client'\nimport init from './example.wasm?init'\n// ---cut---\ninit({\n  imports: {\n    someFunc: () => {\n      /* ... */\n    },\n  },\n}).then(() => {\n  /* ... */\n})\n```\n\nIn the production build, `.wasm` files smaller than `assetInlineLimit` will be inlined as base64 strings. Otherwise, they will be treated as a [static asset](./assets) and fetched on-demand.\n\n::: tip NOTE\n[ES Module Integration Proposal for WebAssembly](https://github.com/WebAssembly/esm-integration) is not currently supported.\nUse [`vite-plugin-wasm`](https://github.com/Menci/vite-plugin-wasm) or other community plugins to handle this.\n:::\n\n::: warning For SSR build, Node.js compatible runtimes are only supported\n\nDue to the lack of a universal way to load a file, the internal implementation for `.wasm?init` relies on `node:fs` module. This means that this feature will only work in Node.js compatible runtimes for SSR builds.\n\n:::\n\n### Accessing the WebAssembly Module\n\nIf you need access to the `Module` object, e.g. to instantiate it multiple times, use an [explicit URL import](./assets#explicit-url-imports) to resolve the asset, and then perform the instantiation:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport wasmUrl from 'foo.wasm?url'\n\nconst main = async () => {\n  const responsePromise = fetch(wasmUrl)\n  const { module, instance } =\n    await WebAssembly.instantiateStreaming(responsePromise)\n  /* ... */\n}\n\nmain()\n```\n\n## Web Workers\n\n### Import with Constructors\n\nA web worker script can be imported using [`new Worker()`](https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker) and [`new SharedWorker()`](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker). Compared to the worker suffixes, this syntax leans closer to the standards and is the **recommended** way to create workers.\n\n```ts\nconst worker = new Worker(new URL('./worker.js', import.meta.url))\n```\n\nThe worker constructor also accepts options, which can be used to create \"module\" workers:\n\n```ts\nconst worker = new Worker(new URL('./worker.js', import.meta.url), {\n  type: 'module',\n})\n```\n\nThe worker detection will only work if the `new URL()` constructor is used directly inside the `new Worker()` declaration. Additionally, all options parameters must be static values (i.e. string literals).\n\n### Import with Query Suffixes\n\nA web worker script can be directly imported by appending `?worker` or `?sharedworker` to the import request. The default export will be a custom worker constructor:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport MyWorker from './worker?worker'\n\nconst worker = new MyWorker()\n```\n\nThe worker script can also use ESM `import` statements instead of `importScripts()`. **Note**: During development this relies on [browser native support](https://caniuse.com/?search=module%20worker), but for the production build it is compiled away.\n\nBy default, the worker script will be emitted as a separate chunk in the production build. If you wish to inline the worker as base64 strings, add the `inline` query:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport MyWorker from './worker?worker&inline'\n```\n\nIf you wish to retrieve the worker as a URL, add the `url` query:\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nimport MyWorker from './worker?worker&url'\n```\n\nSee [Worker Options](/config/worker-options.md) for details on configuring the bundling of all workers.\n\n## Content Security Policy (CSP)\n\nTo deploy CSP, certain directives or configs must be set due to Vite's internals.\n\n### [`'nonce-{RANDOM}'`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#nonce-base64-value)\n\nWhen [`html.cspNonce`](/config/shared-options#html-cspnonce) is set, Vite adds a nonce attribute with the specified value to any `<script>` and `<style>` tags, as well as `<link>` tags for stylesheets and module preloading. Additionally, when this option is set, Vite will inject a meta tag (`<meta property=\"csp-nonce\" nonce=\"PLACEHOLDER\" />`).\n\nThe nonce value of a meta tag with `property=\"csp-nonce\"` will be used by Vite whenever necessary during both dev and after build.\n\n:::warning\nEnsure that you replace the placeholder with a unique value for each request. This is important to prevent bypassing a resource's policy, which can otherwise be easily done.\n:::\n\n### [`data:`](<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#scheme-source:~:text=schemes%20(not%20recommended).-,data%3A,-Allows%20data%3A>)\n\nBy default, during build, Vite inlines small assets as data URIs. Allowing `data:` for related directives (e.g. [`img-src`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/img-src), [`font-src`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/font-src)), or, disabling it by setting [`build.assetsInlineLimit: 0`](/config/build-options#build-assetsinlinelimit) is necessary.\n\n:::warning\nDo not allow `data:` for [`script-src`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src). It will allow injection of arbitrary scripts.\n:::\n\n## License\n\nVite can generate a file of all the dependencies' licenses used in the build with the [`build.license`](/config/build-options.md#build-license) option. It can be hosted to display and acknowledge the dependencies used by the app.\n\n```js twoslash [vite.config.js]\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    license: true,\n  },\n})\n```\n\nThis will generate a `.vite/license.md` file with an output that may look like this:\n\n```md\n# Licenses\n\nThe app bundles dependencies which contain the following licenses:\n\n## dep-1 - 1.2.3 (CC0-1.0)\n\nCC0 1.0 Universal\n\n...\n\n## dep-2 - 4.5.6 (MIT)\n\nMIT License\n\n...\n```\n\nTo serve the file at a different path, you can pass `{ fileName: 'license.md' }` for example, so that it's served at `https://example.com/license.md`. See the [`build.license`](/config/build-options.md#build-license) docs for more information.\n\n## Build Optimizations\n\n> Features listed below are automatically applied as part of the build process and there is no need for explicit configuration unless you want to disable them.\n\n### CSS Code Splitting\n\nVite automatically extracts the CSS used by modules in an async chunk and generates a separate file for it. The CSS file is automatically loaded via a `<link>` tag when the associated async chunk is loaded, and the async chunk is guaranteed to only be evaluated after the CSS is loaded to avoid [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content#:~:text=A%20flash%20of%20unstyled%20content,before%20all%20information%20is%20retrieved.).\n\nIf you'd rather have all the CSS extracted into a single file, you can disable CSS code splitting by setting [`build.cssCodeSplit`](/config/build-options.md#build-csscodesplit) to `false`.\n\n### Preload Directives Generation\n\nVite automatically generates `<link rel=\"modulepreload\">` directives for entry chunks and their direct imports in the built HTML.\n\n### Async Chunk Loading Optimization\n\nIn real world applications, Rollup often generates \"common\" chunks - code that is shared between two or more other chunks. Combined with dynamic imports, it is quite common to have the following scenario:\n\n<script setup>\nimport graphSvg from '../images/graph.svg?raw'\n</script>\n<svg-image :svg=\"graphSvg\" />\n\nIn the non-optimized scenarios, when async chunk `A` is imported, the browser will have to request and parse `A` before it can figure out that it also needs the common chunk `C`. This results in an extra network roundtrip:\n\n```\nEntry ---> A ---> C\n```\n\nVite automatically rewrites code-split dynamic import calls with a preload step so that when `A` is requested, `C` is fetched **in parallel**:\n\n```\nEntry ---> (A + C)\n```\n\nIt is possible for `C` to have further imports, which will result in even more roundtrips in the un-optimized scenario. Vite's optimization will trace all the direct imports to completely eliminate the roundtrips regardless of import depth.\n"
  },
  {
    "path": "docs/guide/index.md",
    "content": "# Getting Started\n\n<audio id=\"vite-audio\">\n  <source src=\"/vite.mp3\" type=\"audio/mpeg\">\n</audio>\n\n## Overview\n\nVite (French word for \"quick\", pronounced `/viːt/`<button style=\"border:none;padding:3px;border-radius:4px;vertical-align:bottom\" id=\"play-vite-audio\" aria-label=\"pronounce\" onclick=\"document.getElementById('vite-audio').play();\"><svg style=\"height:2em;width:2em\"><use href=\"../images/voice.svg?no-inline#voice\" /></svg></button>, like \"veet\") is a build tool that aims to provide a faster and leaner development experience for modern web projects. It consists of two major parts:\n\n- A dev server that provides [rich feature enhancements](./features) over [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), for example extremely fast [Hot Module Replacement (HMR)](./features#hot-module-replacement).\n\n- A build command that bundles your code with [Rolldown](https://rolldown.rs), pre-configured to output highly optimized static assets for production.\n\nVite is opinionated and comes with sensible defaults out of the box. Read about what's possible in the [Features Guide](./features). Support for frameworks or integration with other tools is possible through [Plugins](./using-plugins). The [Config Section](../config/) explains how to adapt Vite to your project if needed.\n\nVite is also highly extensible via its [Plugin API](./api-plugin) and [JavaScript API](./api-javascript) with full typing support.\n\nYou can learn more about the rationale behind the project in the [Why Vite](./why) section.\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq?via=vite\" title=\"Free Vite Course on Scrimba\">Learn Vite through interactive tutorials on Scrimba</ScrimbaLink>\n\n## Browser Support\n\nDuring development, Vite assumes that a modern browser is used. This means the browser supports most of the latest JavaScript and CSS features. For that reason, Vite sets [`esnext` as the transform target](https://esbuild.github.io/api/#target). This prevents syntax lowering, letting Vite serve modules as close as possible to the original source code. Vite injects some runtime code to make the development server work. This code uses features included in [Baseline](https://web-platform-dx.github.io/web-features/) Newly Available at the time of each major release (2026-01-01 for this major).\n\nFor production builds, Vite by default targets [Baseline](https://web-platform-dx.github.io/web-features/) Widely Available browsers. These are browsers that were released at least 2.5 years ago. The target can be lowered via configuration. Additionally, legacy browsers can be supported via the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy). See the [Building for Production](./build) section for more details.\n\n## Trying Vite Online\n\nYou can try Vite online on [StackBlitz](https://vite.new/). It runs the Vite-based build setup directly in the browser, so it is almost identical to the local setup but doesn't require installing anything on your machine. You can navigate to `vite.new/{template}` to select which framework to use.\n\nThe supported template presets are:\n\n|             JavaScript              |                TypeScript                 |\n| :---------------------------------: | :---------------------------------------: |\n| [vanilla](https://vite.new/vanilla) | [vanilla-ts](https://vite.new/vanilla-ts) |\n|     [vue](https://vite.new/vue)     |     [vue-ts](https://vite.new/vue-ts)     |\n|   [react](https://vite.new/react)   |   [react-ts](https://vite.new/react-ts)   |\n|  [preact](https://vite.new/preact)  |  [preact-ts](https://vite.new/preact-ts)  |\n|     [lit](https://vite.new/lit)     |     [lit-ts](https://vite.new/lit-ts)     |\n|  [svelte](https://vite.new/svelte)  |  [svelte-ts](https://vite.new/svelte-ts)  |\n|   [solid](https://vite.new/solid)   |   [solid-ts](https://vite.new/solid-ts)   |\n|    [qwik](https://vite.new/qwik)    |    [qwik-ts](https://vite.new/qwik-ts)    |\n\n## Scaffolding Your First Vite Project\n\n::: code-group\n\n```bash [npm]\n$ npm create vite@latest\n```\n\n```bash [Yarn]\n$ yarn create vite\n```\n\n```bash [pnpm]\n$ pnpm create vite\n```\n\n```bash [Bun]\n$ bun create vite\n```\n\n```bash [Deno]\n$ deno init --npm vite\n```\n\n:::\n\nThen follow the prompts!\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq/~0yhj?via=vite\" title=\"Scaffolding Your First Vite Project\">Watch an interactive lesson on Scrimba</ScrimbaLink>\n\n::: tip Compatibility Note\nVite requires [Node.js](https://nodejs.org/en/) version 20.19+, 22.12+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.\n:::\n\n:::: details Using create vite with command line options\n\nYou can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run:\n\n::: code-group\n\n```bash [npm]\n# npm 7+, extra double-dash is needed:\n$ npm create vite@latest my-vue-app -- --template vue\n```\n\n```bash [Yarn]\n$ yarn create vite my-vue-app --template vue\n```\n\n```bash [pnpm]\n$ pnpm create vite my-vue-app --template vue\n```\n\n```bash [Bun]\n$ bun create vite my-vue-app --template vue\n```\n\n```bash [Deno]\n$ deno init --npm vite my-vue-app --template vue\n```\n\n:::\n\nSee [create-vite](https://github.com/vitejs/vite/tree/main/packages/create-vite) for more details on each supported template: `vanilla`, `vanilla-ts`, `vue`, `vue-ts`, `react`, `react-ts`, `react-swc`, `react-swc-ts`, `preact`, `preact-ts`, `lit`, `lit-ts`, `svelte`, `svelte-ts`, `solid`, `solid-ts`, `qwik`, `qwik-ts`.\n\nYou can use `.` for the project name to scaffold in the current directory.\n\nTo create a project without interactive prompts, you can use the `--no-interactive` flag.\n\n::::\n\n## Community Templates\n\ncreate-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for [community maintained templates](https://github.com/vitejs/awesome-vite#templates) that include other tools or target different frameworks.\n\nFor a template at `https://github.com/user/project`, you can try it out online using `https://github.stackblitz.com/user/project` (adding `.stackblitz` after `github` to the URL of the project).\n\nYou can also use a tool like [tiged](https://github.com/tiged/tiged) to scaffold your project with one of the templates. Assuming the project is on GitHub and uses `main` as the default branch, you can create a local copy using:\n\n```bash\nnpx tiged user/project my-project\ncd my-project\n\nnpm install\nnpm run dev\n```\n\n## Manual Installation\n\nIn your project, you can install the `vite` CLI using:\n\n::: code-group\n\n```bash [npm]\n$ npm install -D vite\n```\n\n```bash [Yarn]\n$ yarn add -D vite\n```\n\n```bash [pnpm]\n$ pnpm add -D vite\n```\n\n```bash [Bun]\n$ bun add -D vite\n```\n\n```bash [Deno]\n$ deno add -D npm:vite\n```\n\n:::\n\nAnd create an `index.html` file like this:\n\n```html\n<p>Hello Vite!</p>\n```\n\nThen run the appropriate CLI command in your terminal:\n\n::: code-group\n\n```bash [npm]\n$ npx vite\n```\n\n```bash [Yarn]\n$ yarn vite\n```\n\n```bash [pnpm]\n$ pnpm vite\n```\n\n```bash [Bun]\n$ bunx vite\n```\n\n```bash [Deno]\n$ deno run -A npm:vite\n```\n\n:::\n\nThe `index.html` will be served on `http://localhost:5173`.\n\n## `index.html` and Project Root\n\nOne thing you may have noticed is that in a Vite project, `index.html` is front-and-central instead of being tucked away inside `public`. This is intentional: during development Vite is a server, and `index.html` is the entry point to your application.\n\nVite treats `index.html` as source code and part of the module graph. It resolves `<script type=\"module\" src=\"...\">` that references your JavaScript source code. Even inline `<script type=\"module\">` and CSS referenced via `<link href>` also enjoy Vite-specific features. In addition, URLs inside `index.html` are automatically rebased so there's no need for special `%PUBLIC_URL%` placeholders.\n\nSimilar to static http servers, Vite has the concept of a \"root directory\" which your files are served from. You will see it referenced as `<root>` throughout the rest of the docs. Absolute URLs in your source code will be resolved using the project root as base, so you can write code as if you are working with a normal static file server (except way more powerful!). Vite is also capable of handling dependencies that resolve to out-of-root file system locations, which makes it usable even in a monorepo-based setup.\n\nVite also supports [multi-page apps](./build#multi-page-app) with multiple `.html` entry points.\n\n#### Specifying Alternative Root\n\nRunning `vite` starts the dev server using the current working directory as root. You can specify an alternative root with `vite serve some/sub/dir`.\nNote that Vite will also resolve [its config file (i.e. `vite.config.js`)](/config/#configuring-vite) inside the project root, so you'll need to move it if the root is changed.\n\n## Command Line Interface\n\nIn a project where Vite is installed, you can use the `vite` binary in your npm scripts, or run it directly with `npx vite`. Here are the default npm scripts in a scaffolded Vite project:\n\n<!-- prettier-ignore -->\n```json [package.json]\n{\n  \"scripts\": {\n    \"dev\": \"vite\", // start dev server, aliases: `vite dev`, `vite serve`\n    \"build\": \"vite build\", // build for production\n    \"preview\": \"vite preview\" // locally preview production build\n  }\n}\n```\n\nYou can specify additional CLI options like `--port` or `--open`. For a full list of CLI options, run `npx vite --help` in your project.\n\nLearn more about the [Command Line Interface](./cli.md)\n\n## Using Unreleased Commits\n\nIf you can't wait for a new release to test the latest features, you can install a specific commit of Vite with https://pkg.pr.new:\n\n::: code-group\n\n```bash [npm]\n$ npm install -D https://pkg.pr.new/vite@SHA\n```\n\n```bash [Yarn]\n$ yarn add -D https://pkg.pr.new/vite@SHA\n```\n\n```bash [pnpm]\n$ pnpm add -D https://pkg.pr.new/vite@SHA\n```\n\n```bash [Bun]\n$ bun add -D https://pkg.pr.new/vite@SHA\n```\n\n:::\n\nReplace `SHA` with any of [Vite's commit SHAs](https://github.com/vitejs/vite/commits/main/). Note that only commits within the last month will work, as older commit releases are purged.\n\nAlternatively, you can also clone the [vite repo](https://github.com/vitejs/vite) to your local machine and then build and link it yourself ([pnpm](https://pnpm.io/) is required):\n\n```bash\ngit clone https://github.com/vitejs/vite.git\ncd vite\npnpm install\ncd packages/vite\npnpm run build\npnpm link # use your preferred package manager for this step\n```\n\nThen go to your Vite based project and run `pnpm link vite` (or the package manager that you used to link `vite` globally). Now restart the development server to ride on the bleeding edge!\n\nTo learn more about how and when Vite does releases, check out the [Releases](../releases.md) documentation.\n\n::: tip Dependencies using Vite\nTo replace the Vite version used by dependencies transitively, you should use [npm overrides](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#overrides) or [pnpm overrides](https://pnpm.io/9.x/package_json#pnpmoverrides).\n:::\n\n## Community\n\nIf you have questions or need help, reach out to the community at [Discord](https://chat.vite.dev) and [GitHub Discussions](https://github.com/vitejs/vite/discussions).\n"
  },
  {
    "path": "docs/guide/migration.md",
    "content": "# Migration from v7\n\nIf you are migrating from `rolldown-vite`, the technical preview release for Rolldown integrated Vite for v6 & v7, only the sections with <Badge text=\"NRV\" type=\"warning\" /> in the title are applicable.\n\n## Default Browser Target Change [<Badge text=\"NRV\" type=\"warning\" />](#migration-from-v7)\n\nThe default browser value of `build.target` and `'baseline-widely-available'`, is updated to newer browser version:\n\n- Chrome 107 → 111\n- Edge 107 → 111\n- Firefox 104 → 114\n- Safari 16.0 → 16.4\n\nThese browser versions align with [Baseline Widely Available](https://web-platform-dx.github.io/web-features/) feature sets as of 2026-01-01. In other words, they were all released about two and a half years ago.\n\n## Rolldown\n\nVite 8 uses [Rolldown](https://rolldown.rs/) and [Oxc](https://oxc.rs/) based tools instead of [esbuild](https://esbuild.github.io/) and [Rollup](https://rollupjs.org/).\n\n### Gradual Migration\n\nThe `rolldown-vite` package implements Vite 7 with Rolldown, without other Vite 8 changes. This can be used as a intermediate step to migrate to Vite 8. See [the Rolldown Integration guide](https://v7.vite.dev/guide/rolldown) in the Vite 7 docs to switch to `rolldown-vite` from Vite 7.\n\nFor users migrating from `rolldown-vite` to Vite 8, you can undo the dependency changes in `package.json` and update to Vite 8:\n\n```json\n{\n  \"devDependencies\": {\n    \"vite\": \"npm:rolldown-vite@7.2.2\" // [!code --]\n    \"vite\": \"^8.0.0\" // [!code ++]\n  }\n}\n```\n\n### Dependency Optimizer Now Uses Rolldown\n\nRolldown is now used for dependency optimization instead of esbuild. Vite still supports [`optimizeDeps.esbuildOptions`](/config/dep-optimization-options#optimizedeps-esbuildoptions) for backward compatibility by converting it to [`optimizeDeps.rolldownOptions`](/config/dep-optimization-options#optimizedeps-rolldownoptions) automatically. `optimizeDeps.esbuildOptions` is now deprecated and will be removed in the future and we encourage you to migrate to `optimizeDeps.rolldownOptions`.\n\nThe following options are converted automatically:\n\n- [`esbuildOptions.minify`](https://esbuild.github.io/api/#minify) -> [`rolldownOptions.output.minify`](https://rolldown.rs/reference/OutputOptions.minify)\n- [`esbuildOptions.treeShaking`](https://esbuild.github.io/api/#tree-shaking) -> [`rolldownOptions.treeshake`](https://rolldown.rs/reference/InputOptions.treeshake)\n- [`esbuildOptions.define`](https://esbuild.github.io/api/#define) -> [`rolldownOptions.transform.define`](https://rolldown.rs/reference/InputOptions.transform#define)\n- [`esbuildOptions.loader`](https://esbuild.github.io/api/#loader) -> [`rolldownOptions.moduleTypes`](https://rolldown.rs/reference/InputOptions.moduleTypes)\n- [`esbuildOptions.preserveSymlinks`](https://esbuild.github.io/api/#preserve-symlinks) -> [`!rolldownOptions.resolve.symlinks`](https://rolldown.rs/reference/InputOptions.resolve#symlinks)\n- [`esbuildOptions.resolveExtensions`](https://esbuild.github.io/api/#resolve-extensions) -> [`rolldownOptions.resolve.extensions`](https://rolldown.rs/reference/InputOptions.resolve#extensions)\n- [`esbuildOptions.mainFields`](https://esbuild.github.io/api/#main-fields) -> [`rolldownOptions.resolve.mainFields`](https://rolldown.rs/reference/InputOptions.resolve#mainfields)\n- [`esbuildOptions.conditions`](https://esbuild.github.io/api/#conditions) -> [`rolldownOptions.resolve.conditionNames`](https://rolldown.rs/reference/InputOptions.resolve#conditionnames)\n- [`esbuildOptions.keepNames`](https://esbuild.github.io/api/#keep-names) -> [`rolldownOptions.output.keepNames`](https://rolldown.rs/reference/OutputOptions.keepNames)\n- [`esbuildOptions.platform`](https://esbuild.github.io/api/#platform) -> [`rolldownOptions.platform`](https://rolldown.rs/reference/InputOptions.platform)\n- [`esbuildOptions.plugins`](https://esbuild.github.io/plugins/) -> [`rolldownOptions.plugins`](https://rolldown.rs/reference/InputOptions.plugins) (partial support)\n\nYou can get the options set by the compatibility layer from the `configResolved` hook:\n\n```js\nconst plugin = {\n  name: 'log-config',\n  configResolved(config) {\n    console.log('options', config.optimizeDeps.rolldownOptions)\n  },\n},\n```\n\n### JavaScript Transforms by Oxc\n\nOxc is now used for JavaScript transformation instead of esbuild. Vite still supports the [`esbuild`](/config/shared-options#esbuild) option for backward compatibility by converting it to [`oxc`](/config/shared-options#oxc) automatically. `esbuild` is now deprecated and will be removed in the future and we encourage you to migrate to `oxc`.\n\nThe following options are converted automatically:\n\n- `esbuild.jsxInject` -> `oxc.jsxInject`\n- `esbuild.include` -> `oxc.include`\n- `esbuild.exclude` -> `oxc.exclude`\n- [`esbuild.jsx`](https://esbuild.github.io/api/#jsx) -> [`oxc.jsx`](https://oxc.rs/docs/guide/usage/transformer/jsx)\n  - `esbuild.jsx: 'preserve'` -> `oxc.jsx: 'preserve'`\n  - `esbuild.jsx: 'automatic'` -> `oxc.jsx: { runtime: 'automatic' }`\n    - [`esbuild.jsxImportSource`](https://esbuild.github.io/api/#jsx-import-source) -> `oxc.jsx.importSource`\n  - `esbuild.jsx: 'transform'` -> `oxc.jsx: { runtime: 'classic' }`\n    - [`esbuild.jsxFactory`](https://esbuild.github.io/api/#jsx-factory) -> `oxc.jsx.pragma`\n    - [`esbuild.jsxFragment`](https://esbuild.github.io/api/#jsx-fragment) -> `oxc.jsx.pragmaFrag`\n  - [`esbuild.jsxDev`](https://esbuild.github.io/api/#jsx-dev) -> `oxc.jsx.development`\n  - [`esbuild.jsxSideEffects`](https://esbuild.github.io/api/#jsx-side-effects) -> `oxc.jsx.pure`\n- [`esbuild.define`](https://esbuild.github.io/api/#define) -> [`oxc.define`](https://oxc.rs/docs/guide/usage/transformer/global-variable-replacement#define)\n- [`esbuild.banner`](https://esbuild.github.io/api/#banner) -> custom plugin using transform hook\n- [`esbuild.footer`](https://esbuild.github.io/api/#footer) -> custom plugin using transform hook\n\nThe [`esbuild.supported`](https://esbuild.github.io/api/#supported) option is not supported by Oxc. If you need this option, please see [oxc-project/oxc#15373](https://github.com/oxc-project/oxc/issues/15373).\n\nYou can get the options set by the compatibility layer from the `configResolved` hook:\n\n```js\nconst plugin = {\n  name: 'log-config',\n  configResolved(config) {\n    console.log('options', config.oxc)\n  },\n},\n```\n\nCurrently, the Oxc transformer does not support lowering native decorators as we are waiting for the specification to progress, see ([oxc-project/oxc#9170](https://github.com/oxc-project/oxc/issues/9170)).\n\n:::: details Workaround for lowering native decorators\n\nYou can use [Babel](https://babeljs.io/) or [SWC](https://swc.rs/) to lower native decorators for the time being. While SWC is faster than Babel, it does **not support the latest decorator spec** that esbuild supports.\n\nThe decorator spec has been updated multiple times since it reached stage 3. The versions supported by each tool are:\n\n- `\"2023-11\"` (esbuild, TypeScript 5.4+ and Babel support this version)\n- `\"2023-05\"` (TypeScript 5.2+ supports this version)\n- `\"2023-01\"` (TypeScript 5.0+ supports this version)\n- `\"2022-03\"` (SWC supports this version)\n\nSee the [Babel decorators versions guide](https://babeljs.io/docs/babel-plugin-proposal-decorators#version) for differences between each version.\n\n**Using Babel:**\n\n::: code-group\n\n```bash [npm]\n$ npm install -D @rolldown/plugin-babel @babel/plugin-proposal-decorators\n```\n\n```bash [Yarn]\n$ yarn add -D @rolldown/plugin-babel @babel/plugin-proposal-decorators\n```\n\n```bash [pnpm]\n$ pnpm add -D @rolldown/plugin-babel @babel/plugin-proposal-decorators\n```\n\n```bash [Bun]\n$ bun add -D @rolldown/plugin-babel @babel/plugin-proposal-decorators\n```\n\n```bash [Deno]\n$ deno add -D npm:@rolldown/plugin-babel npm:@babel/plugin-proposal-decorators\n```\n\n:::\n\n```ts [vite.config.ts]\nimport { defineConfig } from 'vite'\nimport babel from '@rolldown/plugin-babel'\n\nfunction decoratorPreset(options: Record<string, unknown>) {\n  return {\n    preset: () => ({\n      plugins: [['@babel/plugin-proposal-decorators', options]],\n    }),\n    rolldown: {\n      // Only run this transform if the file contains a decorator.\n      filter: {\n        code: '@',\n      },\n    },\n  }\n}\n\nexport default defineConfig({\n  plugins: [babel({ presets: [decoratorPreset({ version: '2023-11' })] })],\n})\n```\n\n**Using SWC:**\n\n::: code-group\n\n```bash [npm]\n$ npm install -D @rollup/plugin-swc @swc/core\n```\n\n```bash [Yarn]\n$ yarn add -D @rollup/plugin-swc @swc/core\n```\n\n```bash [pnpm]\n$ pnpm add -D @rollup/plugin-swc @swc/core\n```\n\n```bash [Bun]\n$ bun add -D @rollup/plugin-swc @swc/core\n```\n\n```bash [Deno]\n$ deno add -D npm:@rollup/plugin-swc npm:@swc/core\n```\n\n:::\n\n```js\nimport { defineConfig, withFilter } from 'vite'\n\nexport default defineConfig({\n  // ...\n  plugins: [\n    withFilter(\n      swc({\n        swc: {\n          jsc: {\n            parser: { decorators: true, decoratorsBeforeExport: true },\n            // NOTE: SWC doesn't support the '2023-11' version yet.\n            transform: { decoratorVersion: '2022-03' },\n          },\n        },\n      }),\n      // Only run this transform if the file contains a decorator.\n      { transform: { code: '@' } },\n    ),\n  ],\n})\n```\n\n::::\n\n#### esbuild Fallbacks\n\n`esbuild` is no longer directly used by Vite and is now an optional dependency. If you are using a plugin that uses the `transformWithEsbuild` function, you need to install `esbuild` as a `devDependency`. The `transformWithEsbuild` function is deprecated and will be removed in the future. We recommend migrating to the new `transformWithOxc` function instead.\n\n### JavaScript Minification by Oxc\n\nThe Oxc Minifier is now used for JavaScript minification instead of esbuild. You can use the deprecated [`build.minify: 'esbuild'`](/config/build-options#build-minify) option to switch back to esbuild. This configuration option will be removed in the future and you need install `esbuild` as a `devDependency` as Vite no longer relies on esbuild directly.\n\nIf you were using the `esbuild.minify*` options to control minification behavior, you can now use `build.rolldownOptions.output.minify` instead. If you were using the `esbuild.drop` option, you can now use [`build.rolldownOptions.output.minify.compress.drop*` options](https://oxc.rs/docs/guide/usage/minifier/dead-code-elimination).\n\nProperty mangling and its related options ([`mangleProps`, `reserveProps`, `mangleQuoted`, `mangleCache`](https://esbuild.github.io/api/#mangle-props)) are not supported by Oxc. If you need these options, please see [oxc-project/oxc#15375](https://github.com/oxc-project/oxc/issues/15375).\n\nesbuild and Oxc Minifier make slightly different assumptions about source code. In case you suspect the minifier is causing breakage in your code, you can compare these assumptions here:\n\n- [esbuild minify assumptions](https://esbuild.github.io/api/#minify-considerations)\n- [Oxc Minifier assumptions](https://oxc.rs/docs/guide/usage/minifier.html#assumptions)\n\nPlease report any issues you find related to minification in your JavaScript apps.\n\n### CSS Minification by Lightning CSS\n\n[Lightning CSS](https://lightningcss.dev/) is now used for CSS minification by default. You can use the [`build.cssMinify: 'esbuild'`](/config/build-options#build-cssminify) option to switch back to esbuild. Note that you need to install `esbuild` as a `devDependency`.\n\nLightning CSS supports better syntax lowering and your CSS bundle size might increase slightly.\n\n### Consistent CommonJS Interop\n\nThe `default` import from a CommonJS (CJS) module is now handled in a consistent way.\n\nIf it matches one of the following conditions, the `default` import is the `module.exports` value of the importee CJS module. Otherwise, the `default` import is the `module.exports.default` value of the importee CJS module:\n\n- The importer is `.mjs` or `.mts`.\n- The closest `package.json` for the importer has a `type` field set to `module`.\n- The `module.exports.__esModule` value of the importee CJS module is not set to true.\n\n::: details The previous behavior\n\nIn development, if it matches one of the following conditions, the `default` import is the `module.exports` value of the importee CJS module. Otherwise, the `default` import is the `module.exports.default` value of the importee CJS module:\n\n- _The importer is included in the dependency optimization_ and `.mjs` or `.mts`.\n- _The importer is included in the dependency optimization_ and the closest `package.json` for the importer has a `type` field set to `module`.\n- The `module.exports.__esModule` value of the importee CJS module is not set to true.\n\nIn build, the conditions were:\n\n- The `module.exports.__esModule` value of the importee CJS module is not set to true.\n- _`default` property of `module.exports` does not exist_.\n\n(assuming [`build.commonjsOptions.defaultIsModuleExports`](https://github.com/rollup/plugins/tree/master/packages/commonjs#defaultismoduleexports) is not changed from the default `'auto'`)\n\n:::\n\nSee Rolldown's docs about this problem for more details: [Ambiguous `default` import from CJS modules - Bundling CJS | Rolldown](https://rolldown.rs/in-depth/bundling-cjs#ambiguous-default-import-from-cjs-modules).\n\nThis change may break some existing code importing CJS modules. You can use the deprecated `legacy.inconsistentCjsInterop: true` option to temporarily restore the previous behavior. If you find a package that is affected by this change, please report it to the package author or send them a pull request. Make sure to link to the Rolldown documentation above so that the author can understand the context.\n\n### Removed Module Resolution Using Format Sniffing\n\nWhen both `browser` and `module` fields are present in `package.json`, Vite used to resolve the field based on the content of the file and it used to pick the ESM file for browsers. This was introduced because some packages were using the `module` field to point to ESM files for Node.js and some other packages were using the `browser` field to point to UMD files for browsers. Given that the modern `exports` field solved this problem and is now adopted by many packages, Vite no longer uses this heuristic and always respects the order of the [`resolve.mainFields`](/config/shared-options#resolve-mainfields) option. If you were relying on this behavior, you can use the [`resolve.alias`](/config/shared-options#resolve-alias) option to map the field to the desired file or apply a patch with your package manager (e.g. `patch-package`, `pnpm patch`).\n\n### Require Calls For Externalized Modules\n\n`require` calls for externalized modules are now preserved as `require` calls and not converted to `import` statements. This is to preserve the semantics of `require` calls. If you want to convert them to `import` statements, you can use [Rolldown's built-in `esmExternalRequirePlugin`](https://rolldown.rs/builtin-plugins/esm-external-require), which is re-exported from `vite`.\n\n```js\nimport { defineConfig, esmExternalRequirePlugin } from 'vite'\n\nexport default defineConfig({\n  // ...\n  plugins: [\n    esmExternalRequirePlugin({\n      external: ['react', 'vue', /^node:/],\n    }),\n  ],\n})\n```\n\nSee Rolldown's docs for more details: [`require` external modules - Bundling CJS | Rolldown](https://rolldown.rs/in-depth/bundling-cjs#require-external-modules).\n\n### `import.meta.url` in UMD / IIFE\n\n`import.meta.url` is no longer polyfilled in UMD / IIFE output formats. It will be replaced with `undefined` by default. If you prefer the previous behavior, you can use the [`define`](/config/shared-options#define) option with [`build.rolldownOptions.output.intro`](https://rolldown.rs/reference/OutputOptions.intro) option. See Rolldown's docs for more details: [Well-known `import.meta` properties - Non ESM Output Formats | Rolldown](https://rolldown.rs/in-depth/non-esm-output-formats#well-known-import-meta-properties).\n\n### Removed `build.rollupOptions.watch.chokidar` option\n\nThe `build.rollupOptions.watch.chokidar` option was removed. Please migrate to the [`build.rolldownOptions.watch.watcher`](https://rolldown.rs/reference/InputOptions.watch#watcher) option.\n\n### Removed object form `build.rollupOptions.output.manualChunks` and deprecate function form one\n\nThe object form `output.manualChunks` option is not supported anymore. The function form `output.manualChunks` is deprecated. Rolldown has the more flexible [`codeSplitting`](https://rolldown.rs/reference/OutputOptions.codeSplitting) option. See Rolldown's docs for more details about `codeSplitting`: [Manual Code Splitting - Rolldown](https://rolldown.rs/in-depth/manual-code-splitting).\n\n### `build()` Throws `BundleError`\n\n_This change only affects JS API users._\n\n`build()` now throws a [`BundleError`](https://rolldown.rs/reference/TypeAlias.BundleError) instead of the raw error thrown in the plugin. `BundleError` is typed as `Error & { errors?: RolldownError[] }` and it wraps the individual errors in an `errors` array. If you need the individual errors, you need to access `.errors`:\n\n```js\ntry {\n  await build()\n} catch (e) {\n  if (e.errors) {\n    for (const error of e.errors) {\n      console.log(error.code) // error code\n    }\n  }\n}\n```\n\n### Module Type Support and Auto Detection\n\n_This change only affects plugin authors._\n\nRolldown has experimental support for [Module types](https://rolldown.rs/guide/notable-features#module-types), similar to [esbuild's `loader` option](https://esbuild.github.io/api/#loader). Due to this, Rolldown automatically sets a module type based on the extension of the resolved id. If you are converting content from other module types to JavaScript in `load` or `transform` hooks, you may need to add `moduleType: 'js'` to the returned value:\n\n```js\nconst plugin = {\n  name: 'txt-loader',\n  load(id) {\n    if (id.endsWith('.txt')) {\n      const content = fs.readFile(id, 'utf-8')\n      return {\n        code: `export default ${JSON.stringify(content)}`,\n        moduleType: 'js', // [!code ++]\n      }\n    }\n  },\n}\n```\n\n### Other Related Deprecations\n\nThe following options are deprecated and will be removed in the future:\n\n- `build.rollupOptions`: renamed to `build.rolldownOptions`\n- `worker.rollupOptions`: renamed to `worker.rolldownOptions`\n- `build.commonjsOptions`: it is now no-op\n- `build.dynamicImportVarsOptions.warnOnError`: it is now no-op\n- `resolve.alias[].customResolver`: Use a custom plugin with `resolveId` hook and `enforce: 'pre'` instead\n\n## Removed Deprecated Features [<Badge text=\"NRV\" type=\"warning\" />](#migration-from-v7)\n\n- Passing an URL to `import.meta.hot.accept` is no longer supported. Please pass an id instead. ([#21382](https://github.com/vitejs/vite/pull/21382))\n\n## Advanced\n\nThese breaking changes are expected to only affect a minority of use cases:\n\n- [Extglobs](https://github.com/micromatch/picomatch/blob/master/README.md#extglobs) are not supported yet ([rolldown-vite#365](https://github.com/vitejs/rolldown-vite/issues/365))\n- TypeScript legacy namespace is only supported partially. See [Oxc Transformer's related documentation](https://oxc.rs/docs/guide/usage/transformer/typescript.html#partial-namespace-support) for more details.\n- `define` does not share reference for objects: When you pass an object as a value to `define`, each variable will have a separate copy of the object. See [Oxc Transformer's related documentation](https://oxc.rs/docs/guide/usage/transformer/global-variable-replacement#define) for more details.\n- `bundle` object changes (`bundle` is an object passed in `generateBundle` / `writeBundle` hooks, returned by `build` function):\n  - Assigning to `bundle[foo]` is not supported. This is discouraged by Rollup as well. Please use `this.emitFile()` instead.\n  - the reference is not shared across the hooks ([rolldown-vite#410](https://github.com/vitejs/rolldown-vite/issues/410))\n  - `structuredClone(bundle)` errors with `DataCloneError: #<Object> could not be cloned`. This is not supported anymore. Please clone it with `structuredClone({ ...bundle })`. ([rolldown-vite#128](https://github.com/vitejs/rolldown-vite/issues/128))\n- All parallel hooks in Rollup works as sequential hooks. See [Rolldown's documentation](https://rolldown.rs/apis/plugin-api#sequential-hook-execution) for more details.\n- `\"use strict\";` is not injected sometimes. See [Rolldown's documentation](https://rolldown.rs/in-depth/directives) for more details.\n- Transforming to ES5 and below with plugin-legacy is not supported ([rolldown-vite#452](https://github.com/vitejs/rolldown-vite/issues/452))\n- Passing the same browser with multiple versions of it to `build.target` option now errors: esbuild selects the latest version of it, which was probably not what you intended.\n- Missing support by Rolldown: The following features are not supported by Rolldown and is no longer supported by Vite.\n  - `build.rollupOptions.output.format: 'system'` ([rolldown#2387](https://github.com/rolldown/rolldown/issues/2387))\n  - `build.rollupOptions.output.format: 'amd'` ([rolldown#2387](https://github.com/rolldown/rolldown/issues/2528))\n  - `shouldTransformCachedModule` hook ([rolldown#4389](https://github.com/rolldown/rolldown/issues/4389))\n  - `resolveImportMeta` hook ([rolldown#1010](https://github.com/rolldown/rolldown/issues/1010))\n  - `renderDynamicImport` hook ([rolldown#4532](https://github.com/rolldown/rolldown/issues/4532))\n  - `resolveFileUrl` hook\n- `parseAst` / `parseAstAsync` functions are now deprecated in favor of `parseSync` / `parse` functions which have more features.\n\n## Migration from v6\n\nCheck the [Migration from v6 Guide](https://v7.vite.dev/guide/migration) in the Vite v7 docs first to see the needed changes to port your app to Vite 7, and then proceed with the changes on this page.\n"
  },
  {
    "path": "docs/guide/performance.md",
    "content": "# Performance\n\nWhile Vite is fast by default, performance issues can creep in as the project's requirements grow. This guide aims to help you identify and fix common performance issues, such as:\n\n- Slow server starts\n- Slow page loads\n- Slow builds\n\n## Review Your Browser Setup\n\nSome browser extensions may interfere with requests and slow down startup and reload times for large apps, especially when using browser dev tools. We recommend creating a dev-only profile without extensions, or switch to incognito mode, while using Vite's dev server in these cases. Incognito mode should also be faster than a regular profile without extensions.\n\nThe Vite dev server does hard caching of pre-bundled dependencies and implements fast 304 responses for source code. Disabling the cache while the Browser Dev Tools are open can have a big impact on startup and full-page reload times. Please check that \"Disable Cache\" isn't enabled while you work with the Vite server.\n\n## Audit Configured Vite Plugins\n\nVite's internal and official plugins are optimized to do the least amount of work possible while providing compatibility with the broader ecosystem. For example, code transformations use regex in dev, but do a complete parse in build to ensure correctness.\n\nHowever, the performance of community plugins is out of Vite's control, which may affect the developer experience. Here are a few things you can look out for when using additional Vite plugins:\n\n1. Large dependencies that are only used in certain cases should be dynamically imported to reduce the Node.js startup time. Example refactors: [vite-plugin-react#212](https://github.com/vitejs/vite-plugin-react/pull/212) and [vite-plugin-pwa#224](https://github.com/vite-pwa/vite-plugin-pwa/pull/244).\n\n2. The `buildStart`, `config`, and `configResolved` hooks should not run long and extensive operations. These hooks are awaited during dev server startup, which delays when you can access the site in the browser.\n\n3. The `resolveId`, `load`, and `transform` hooks may cause some files to load slower than others. While sometimes unavoidable, it's still worth checking for possible areas to optimize. For example, checking if the `code` contains a specific keyword, or the `id` matches a specific extension, before doing the full transformation.\n\n   The longer it takes to transform a file, the more significant the request waterfall will be when loading the site in the browser.\n\n   You can inspect the duration it takes to transform a file using `vite --debug plugin-transform` or [vite-plugin-inspect](https://github.com/antfu/vite-plugin-inspect). Note that as asynchronous operations tend to provide inaccurate timings, you should treat the numbers as a rough estimate, but it should still reveal the more expensive operations.\n\n::: tip Profiling\nYou can run `vite --profile`, visit the site, and press `p + enter` in your terminal to record a `.cpuprofile`. A tool like [speedscope](https://www.speedscope.app) can then be used to inspect the profile and identify the bottlenecks. You can also [share the profiles](https://chat.vite.dev) with the Vite team to help us identify performance issues.\n:::\n\n## Reduce Resolve Operations\n\nResolving import paths can be an expensive operation when hitting its worst case often. For example, Vite supports \"guessing\" import paths with the [`resolve.extensions`](/config/shared-options.md#resolve-extensions) option, which defaults to `['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']`.\n\nWhen you try to import `./Component.jsx` with `import './Component'`, Vite will run these steps to resolve it:\n\n1. Check if `./Component` exists, no.\n2. Check if `./Component.mjs` exists, no.\n3. Check if `./Component.js` exists, no.\n4. Check if `./Component.mts` exists, no.\n5. Check if `./Component.ts` exists, no.\n6. Check if `./Component.jsx` exists, yes!\n\nAs shown, a total of 6 filesystem checks is required to resolve an import path. The more implicit imports you have, the more time it adds up to resolve the paths.\n\nHence, it's usually better to be explicit with your import paths, e.g. `import './Component.jsx'`. You can also narrow down the list for `resolve.extensions` to reduce the general filesystem checks, but you have to make sure it works for files in `node_modules` too.\n\nIf you're a plugin author, make sure to only call [`this.resolve`](https://rollupjs.org/plugin-development/#this-resolve) when needed to reduce the number of checks above.\n\n::: tip TypeScript\nIf you are using TypeScript, enable `\"moduleResolution\": \"bundler\"` and `\"allowImportingTsExtensions\": true` in your `tsconfig.json`'s `compilerOptions` to use `.ts` and `.tsx` extensions directly in your code.\n:::\n\n## Avoid Barrel Files\n\nBarrel files are files that re-export the APIs of other files in the same directory. For example:\n\n```js [src/utils/index.js]\nexport * from './color.js'\nexport * from './dom.js'\nexport * from './slash.js'\n```\n\nWhen you only import an individual API, e.g. `import { slash } from './utils'`, all the files in that barrel file need to be fetched and transformed as they may contain the `slash` API and may also contain side-effects that run on initialization. This means you're loading more files than required on the initial page load, resulting in a slower page load.\n\nIf possible, you should avoid barrel files and import the individual APIs directly, e.g. `import { slash } from './utils/slash.js'`. You can read [issue #8237](https://github.com/vitejs/vite/issues/8237) for more information.\n\n## Warm Up Frequently Used Files\n\nThe Vite dev server only transforms files as requested by the browser, which allows it to start up quickly and only apply transformations for used files. It can also pre-transform files if it anticipates certain files will be requested shortly. However, request waterfalls may still happen if some files take longer to transform than others. For example:\n\nGiven an import graph where the left file imports the right file:\n\n```\nmain.js -> BigComponent.vue -> big-utils.js -> large-data.json\n```\n\nThe import relationship can only be known after the file is transformed. If `BigComponent.vue` takes some time to transform, `big-utils.js` has to wait for its turn, and so on. This causes an internal waterfall even with pre-transformation built-in.\n\nVite allows you to warm up files that you know are frequently used, e.g. `big-utils.js`, using the [`server.warmup`](/config/server-options.md#server-warmup) option. This way `big-utils.js` will be ready and cached to be served immediately when requested.\n\nYou can find files that are frequently used by running `vite --debug transform` and inspect the logs:\n\n```bash\nvite:transform 28.72ms /@vite/client +1ms\nvite:transform 62.95ms /src/components/BigComponent.vue +1ms\nvite:transform 102.54ms /src/utils/big-utils.js +1ms\n```\n\n```js [vite.config.js]\nexport default defineConfig({\n  server: {\n    warmup: {\n      clientFiles: [\n        './src/components/BigComponent.vue',\n        './src/utils/big-utils.js',\n      ],\n    },\n  },\n})\n```\n\nNote that you should only warm up files that are frequently used to not overload the Vite dev server on startup. Check the [`server.warmup`](/config/server-options.md#server-warmup) option for more information.\n\nUsing [`--open` or `server.open`](/config/server-options.html#server-open) also provides a performance boost, as Vite will automatically warm up the entry point of your app or the provided URL to open.\n\n## Use Lesser or Native Tooling\n\nKeeping Vite fast with a growing codebase is about reducing the amount of work for the source files (JS/TS/CSS).\n\nExamples of doing less work:\n\n- Use CSS instead of Sass/Less/Stylus when possible (nesting can be handled by PostCSS / Lightning CSS)\n- Don't transform SVGs into UI framework components (React, Vue, etc.). Import them as strings or URLs instead.\n\nExamples of using native tooling:\n\nWhile Vite core is based on native tooling, some features still use non-native tooling by default to provide better compatibility and feature set. But it may be worth the cost for larger applications.\n\n- Try out the experimental support for [LightningCSS](https://github.com/vitejs/vite/discussions/13835)\n"
  },
  {
    "path": "docs/guide/philosophy.md",
    "content": "# Project Philosophy\n\n## Lean Extendable Core\n\nVite aims to support the most common patterns to build Web apps out-of-the-box, while keeping [Vite core](https://github.com/vitejs/vite) lean and maintainable long-term. We believe the best way to support diverse use cases is to provide strong primitives and APIs that plugins can build on, and we actively expand the core to make Vite more extensible. [Vite's plugin system](./api-plugin.md) is based on a superset of Rollup's plugin API, and it enables plugins like [vite-plugin-pwa](https://vite-pwa-org.netlify.app/) and the many [well maintained plugins](https://registry.vite.dev/plugins) available to cover your needs. Vite's bundler, [Rolldown](https://rolldown.rs/), maintains compatibility with Rollup's plugin interface, so plugins can often be used across both Vite and plain Rollup projects.\n\n## Pushing the Modern Web\n\nVite provides opinionated features that push writing modern code. For example:\n\n- The source code can only be written in ESM, where non-ESM dependencies need to be [pre-bundled as ESM](./dep-pre-bundling) in order to work.\n- Web workers are encouraged to be written with the [`new Worker` syntax](./features#web-workers) to follow modern standards.\n- Node.js modules cannot be used in the browser.\n\nWhen adding new features, these patterns are followed to create a future-proof API, which may not always be compatible with other build tools.\n\n## A Pragmatic Approach to Performance\n\nVite has been focused on performance since its [origins](./why.md). Its dev server architecture allows HMR that stays fast as projects scale. Vite is based on native tools that include the [Oxc toolchain](https://oxc.rs/) and [Rolldown](https://rolldown.rs/) to implement intensive tasks but keeps the rest of the code in JS to balance speed with flexibility. When needed, framework plugins will tap into [Babel](https://babeljs.io/) to compile user code. Thanks to Rolldown's Rollup plugin compatibility, Vite has access to a wide ecosystem of plugins.\n\n## Building Frameworks on Top of Vite\n\nAlthough Vite can be used by users directly, it shines as a tool to create frameworks. Vite core is framework agnostic, but there are polished plugins for each UI framework. Its [JS API](./api-javascript.md) allows App Framework authors to use Vite features to create tailored experiences for their users. Vite includes support for [SSR primitives](./ssr.md), usually present in higher-level tools but fundamental to building modern web frameworks. And Vite plugins complete the picture by offering a way to share between frameworks. Vite is also a great fit when paired with [Backend frameworks](./backend-integration.md) like [Ruby](https://vite-ruby.netlify.app/) and [Laravel](https://laravel.com/docs/vite).\n\n## An Active Ecosystem\n\nVite evolution is a cooperation between framework and plugin maintainers, users, and the Vite team. We encourage active participation in Vite's Core development once a project adopts Vite. We work closely with the main projects in the ecosystem to minimize regressions on each release, aided by tools like [vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci). It allows us to run the CI of major projects using Vite on selected PRs and gives us a clear status of how the Ecosystem would react to a release. We strive to fix regressions before they hit users and allow projects to update to the next versions as soon as they are released. If you are working with Vite, we invite you to join [Vite's Discord](https://chat.vite.dev) and get involved in the project too.\n"
  },
  {
    "path": "docs/guide/ssr.md",
    "content": "# Server-Side Rendering (SSR)\n\n:::tip Note\nSSR specifically refers to front-end frameworks (for example React, Preact, Vue, and Svelte) that support running the same application in Node.js, pre-rendering it to HTML, and finally hydrating it on the client. If you are looking for integration with traditional server-side frameworks, check out the [Backend Integration guide](./backend-integration) instead.\n\nThe following guide also assumes prior experience working with SSR in your framework of choice, and will only focus on Vite-specific integration details.\n:::\n\n:::warning Low-level API\nThis is a low-level API meant for library and framework authors. If your goal is to create an application, make sure to check out the higher-level SSR plugins and tools at [Awesome Vite SSR section](https://github.com/vitejs/awesome-vite#ssr) first. That said, many applications are successfully built directly on top of Vite's native low-level API.\n\nCurrently, Vite is working on an improved SSR API with the [Environment API](https://github.com/vitejs/vite/discussions/16358). Check out the link for more details.\n:::\n\n## Example Projects\n\nVite provides built-in support for server-side rendering (SSR). [`create-vite-extra`](https://github.com/bluwy/create-vite-extra) contains example SSR setups you can use as references for this guide:\n\n- [Vanilla](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-vanilla)\n- [Vue](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-vue)\n- [React](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-react)\n- [Preact](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-preact)\n- [Svelte](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-svelte)\n- [Solid](https://github.com/bluwy/create-vite-extra/tree/master/template-ssr-solid)\n\nYou can also scaffold these projects locally by [running `create-vite`](./index.md#scaffolding-your-first-vite-project) and choose `Others > create-vite-extra` under the framework option.\n\n## Source Structure\n\nA typical SSR application will have the following source file structure:\n\n```\n- index.html\n- server.js # main application server\n- src/\n  - main.js          # exports env-agnostic (universal) app code\n  - entry-client.js  # mounts the app to a DOM element\n  - entry-server.js  # renders the app using the framework's SSR API\n```\n\nThe `index.html` will need to reference `entry-client.js` and include a placeholder where the server-rendered markup should be injected:\n\n```html [index.html]\n<div id=\"app\"><!--ssr-outlet--></div>\n<script type=\"module\" src=\"/src/entry-client.js\"></script>\n```\n\nYou can use any placeholder you prefer instead of `<!--ssr-outlet-->`, as long as it can be precisely replaced.\n\n## Conditional Logic\n\nIf you need to perform conditional logic based on SSR vs. client, you can use\n\n```js twoslash\nimport 'vite/client'\n// ---cut---\nif (import.meta.env.SSR) {\n  // ... server only logic\n}\n```\n\nThis is statically replaced during build so it will allow tree-shaking of unused branches.\n\n## Setting Up the Dev Server\n\nWhen building an SSR app, you likely want to have full control over your main server and decouple Vite from the production environment. It is therefore recommended to use Vite in middleware mode. Here is an example with [express](https://expressjs.com/):\n\n```js{15-18} twoslash [server.js]\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\nimport { createServer as createViteServer } from 'vite'\n\nasync function createServer() {\n  const app = express()\n\n  // Create Vite server in middleware mode and configure the app type as\n  // 'custom', disabling Vite's own HTML serving logic so parent server\n  // can take control\n  const vite = await createViteServer({\n    server: { middlewareMode: true },\n    appType: 'custom'\n  })\n\n  // Use vite's connect instance as middleware. If you use your own\n  // express router (express.Router()), you should use router.use\n  // When the server restarts (for example after the user modifies\n  // vite.config.js), `vite.middlewares` is still going to be the same\n  // reference (with a new internal stack of Vite and plugin-injected\n  // middlewares). The following is valid even after restarts.\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res) => {\n    // serve index.html - we will tackle this next\n  })\n\n  app.listen(5173)\n}\n\ncreateServer()\n```\n\nHere `vite` is an instance of [ViteDevServer](./api-javascript#vitedevserver). `vite.middlewares` is a [Connect](https://github.com/senchalabs/connect) instance which can be used as a middleware in any connect-compatible Node.js framework.\n\nThe next step is implementing the `*` handler to serve server-rendered HTML:\n\n```js twoslash [server.js]\n// @noErrors\nimport fs from 'node:fs'\nimport path from 'node:path'\n\n/** @type {import('express').Express} */\nvar app\n/** @type {import('vite').ViteDevServer}  */\nvar vite\n\n// ---cut---\napp.use('*all', async (req, res, next) => {\n  const url = req.originalUrl\n\n  try {\n    // 1. Read index.html\n    let template = fs.readFileSync(\n      path.resolve(import.meta.dirname, 'index.html'),\n      'utf-8',\n    )\n\n    // 2. Apply Vite HTML transforms. This injects the Vite HMR client,\n    //    and also applies HTML transforms from Vite plugins, e.g. global\n    //    preambles from @vitejs/plugin-react\n    template = await vite.transformIndexHtml(url, template)\n\n    // 3. Load the server entry. ssrLoadModule automatically transforms\n    //    ESM source code to be usable in Node.js! There is no bundling\n    //    required, and provides efficient invalidation similar to HMR.\n    const { render } = await vite.ssrLoadModule('/src/entry-server.js')\n\n    // 4. render the app HTML. This assumes entry-server.js's exported\n    //     `render` function calls appropriate framework SSR APIs,\n    //    e.g. ReactDOMServer.renderToString()\n    const appHtml = await render(url)\n\n    // 5. Inject the app-rendered HTML into the template.\n    const html = template.replace(`<!--ssr-outlet-->`, () => appHtml)\n\n    // 6. Send the rendered HTML back.\n    res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n  } catch (e) {\n    // If an error is caught, let Vite fix the stack trace so it maps back\n    // to your actual source code.\n    vite.ssrFixStacktrace(e)\n    next(e)\n  }\n})\n```\n\nThe `dev` script in `package.json` should also be changed to use the server script instead:\n\n```diff [package.json]\n  \"scripts\": {\n-   \"dev\": \"vite\"\n+   \"dev\": \"node server\"\n  }\n```\n\n## Building for Production\n\nTo ship an SSR project for production, we need to:\n\n1. Produce a client build as normal;\n2. Produce an SSR build, which can be directly loaded via `import()` so that we don't have to go through Vite's `ssrLoadModule`;\n\nOur scripts in `package.json` will look like this:\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"build:client\": \"vite build --outDir dist/client\",\n    \"build:server\": \"vite build --outDir dist/server --ssr src/entry-server.js\"\n  }\n}\n```\n\nNote the `--ssr` flag which indicates this is an SSR build. It should also specify the SSR entry.\n\nThen, in `server.js` we need to add some production specific logic by checking `process.env.NODE_ENV`:\n\n- Instead of reading the root `index.html`, use the `dist/client/index.html` as the template, since it contains the correct asset links to the client build.\n\n- Instead of `await vite.ssrLoadModule('/src/entry-server.js')`, use `import('./dist/server/entry-server.js')` (this file is the result of the SSR build).\n\n- Move the creation and all usage of the `vite` dev server behind dev-only conditional branches, then add static file serving middlewares to serve files from `dist/client`.\n\nRefer to the [example projects](#example-projects) for a working setup.\n\n## Generating Preload Directives\n\n`vite build` supports the `--ssrManifest` flag which will generate `.vite/ssr-manifest.json` in build output directory:\n\n```diff\n- \"build:client\": \"vite build --outDir dist/client\",\n+ \"build:client\": \"vite build --outDir dist/client --ssrManifest\",\n```\n\nThe above script will now generate `dist/client/.vite/ssr-manifest.json` for the client build (Yes, the SSR manifest is generated from the client build because we want to map module IDs to client files). The manifest contains mappings of module IDs to their associated chunks and asset files.\n\nTo leverage the manifest, frameworks need to provide a way to collect the module IDs of the components that were used during a server render call.\n\n`@vitejs/plugin-vue` supports this out of the box and automatically registers used component module IDs on to the associated Vue SSR context:\n\n```js [src/entry-server.js]\nconst ctx = {}\nconst html = await vueServerRenderer.renderToString(app, ctx)\n// ctx.modules is now a Set of module IDs that were used during the render\n```\n\nIn the production branch of `server.js` we need to read and pass the manifest to the `render` function exported by `src/entry-server.js`. This would provide us with enough information to render preload directives for files used by async routes! See [demo source](https://github.com/vitejs/vite-plugin-vue/blob/main/playground/ssr-vue/src/entry-server.js) for a full example. You can also use this information for [103 Early Hints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103).\n\n## Pre-Rendering / SSG\n\nIf the routes and the data needed for certain routes are known ahead of time, we can pre-render these routes into static HTML using the same logic as production SSR. This can also be considered a form of Static-Site Generation (SSG). See [demo pre-render script](https://github.com/vitejs/vite-plugin-vue/blob/main/playground/ssr-vue/prerender.js) for working example.\n\n## SSR Externals\n\nDependencies are \"externalized\" from Vite's SSR transform module system by default when running SSR. This speeds up both dev and build.\n\nIf a dependency needs to be transformed by Vite's pipeline, for example, because Vite features are used untranspiled in them, they can be added to [`ssr.noExternal`](../config/ssr-options.md#ssr-noexternal).\n\nFor linked dependencies, they are not externalized by default to take advantage of Vite's HMR. If this isn't desired, for example, to test dependencies as if they aren't linked, you can add it to [`ssr.external`](../config/ssr-options.md#ssr-external).\n\n:::warning Working with Aliases\nIf you have configured aliases that redirect one package to another, you may want to alias the actual `node_modules` packages instead to make it work for SSR externalized dependencies. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.io/aliases/) support aliasing via the `npm:` prefix.\n:::\n\n## SSR-specific Plugin Logic\n\nSome frameworks such as Vue or Svelte compile components into different formats based on client vs. SSR. To support conditional transforms, Vite passes an additional `ssr` property in the `options` object of the following plugin hooks:\n\n- `resolveId`\n- `load`\n- `transform`\n\n**Example:**\n\n```js twoslash\n/** @type {() => import('vite').Plugin} */\n// ---cut---\nexport function mySSRPlugin() {\n  return {\n    name: 'my-ssr',\n    transform(code, id, options) {\n      if (options?.ssr) {\n        // perform ssr-specific transform...\n      }\n    },\n  }\n}\n```\n\nThe options object in `load` and `transform` is optional, Rollup is not currently using this object but may extend these hooks with additional metadata in the future.\n\n:::tip Note\nBefore Vite 2.7, this was informed to plugin hooks with a positional `ssr` param instead of using the `options` object. All major frameworks and plugins are updated but you may find outdated posts using the previous API.\n:::\n\n## SSR Target\n\nThe default target for the SSR build is a node environment, but you can also run the server in a Web Worker. Packages entry resolution is different for each platform. You can configure the target to be Web Worker using the `ssr.target` set to `'webworker'`.\n\n## SSR Bundle\n\nIn some cases like `webworker` runtimes, you might want to bundle your SSR build into a single JavaScript file. You can enable this behavior by setting `ssr.noExternal` to `true`. This will do two things:\n\n- Treat all dependencies as `noExternal`\n- Throw an error if any Node.js built-ins are imported\n\n## SSR Resolve Conditions\n\nBy default package entry resolution will use the conditions set in [`resolve.conditions`](../config/shared-options.md#resolve-conditions) for the SSR build. You can use [`ssr.resolve.conditions`](../config/ssr-options.md#ssr-resolve-conditions) and [`ssr.resolve.externalConditions`](../config/ssr-options.md#ssr-resolve-externalconditions) to customize this behavior.\n\n## Vite CLI\n\nThe CLI commands `$ vite dev` and `$ vite preview` can also be used for SSR apps. You can add your SSR middlewares to the development server with [`configureServer`](/guide/api-plugin#configureserver) and to the preview server with [`configurePreviewServer`](/guide/api-plugin#configurepreviewserver).\n\n:::tip Note\nUse a post hook so that your SSR middleware runs _after_ Vite's middlewares.\n:::\n"
  },
  {
    "path": "docs/guide/static-deploy-github-pages.yaml",
    "content": "# Imported in static-deploy.md\n# This file is extracted as a separate file so that renovate can update the action versions\n#\n#region content\n# Simple workflow for deploying static content to GitHub Pages\nname: Deploy static content to Pages\n\non:\n  # Runs on pushes targeting the default branch\n  push:\n    branches: ['main']\n\n  # Allows you to run this workflow manually from the Actions tab\n  workflow_dispatch:\n\n# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\n# Allow one concurrent deployment\nconcurrency:\n  group: 'pages'\n  cancel-in-progress: true\n\njobs:\n  # Single deploy job since we're just deploying\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Set up Node\n        uses: actions/setup-node@v6\n        with:\n          node-version: lts/*\n          cache: 'npm'\n      - name: Install dependencies\n        run: npm ci\n      - name: Build\n        run: npm run build\n      - name: Setup Pages\n        uses: actions/configure-pages@v5\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v4\n        with:\n          # Upload dist folder\n          path: './dist'\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4\n#endregion content\n"
  },
  {
    "path": "docs/guide/static-deploy.md",
    "content": "<!--\n  READ THIS IF YOU WANT TO ADD A NEW DEPLOYMENT PLATFORM.\n\n  Feel free to submit a PR that adds a new section with a link to your platform's\n  deployment guide, as long as it meets these criteria:\n\n  1. Users should be able to deploy their site for free.\n  2. Free tier offerings should host the site indefinitely and are not time-bound.\n     Offering a limited number of computation resource or site counts in exchange is fine.\n  3. The linked guides should not contain any malicious content.\n\n  New sections should be added last in the file. Please reference the existing sections at\n  the bottom of this file for examples of how to format the new section.\n\n  The Vite team may change the criteria and audit the current list from time to time.\n  If a section is removed, we will ping the original PR authors before doing so.\n-->\n\n# Deploying a Static Site\n\nThe following guides are based on some shared assumptions:\n\n- You are using the default build output location (`dist`). This location [can be changed using `build.outDir`](/config/build-options.md#build-outdir), and you can extrapolate instructions from these guides in that case.\n- You are using npm. You can use equivalent commands to run the scripts if you are using Yarn or other package managers.\n- Vite is installed as a local dev dependency in your project, and you have setup the following npm scripts:\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n```\n\nIt is important to note that `vite preview` is intended for previewing the build locally and not meant as a production server.\n\n::: tip NOTE\nThese guides provide instructions for performing a static deployment of your Vite site. Vite also supports Server-Side Rendering. SSR refers to front-end frameworks that support running the same application in Node.js, pre-rendering it to HTML, and finally hydrating it on the client. Check out the [SSR Guide](./ssr) to learn about this feature. On the other hand, if you are looking for integration with traditional server-side frameworks, check out the [Backend Integration guide](./backend-integration) instead.\n:::\n\n## Building the App\n\nYou may run `npm run build` command to build the app.\n\n```bash\n$ npm run build\n```\n\nBy default, the build output will be placed at `dist`. You may deploy this `dist` folder to any of your preferred platforms.\n\n### Testing the App Locally\n\nOnce you've built the app, you may test it locally by running `npm run preview` command.\n\n```bash\n$ npm run preview\n```\n\nThe `vite preview` command will boot up a local static web server that serves the files from `dist` at `http://localhost:4173`. It's an easy way to check if the production build looks OK in your local environment.\n\nYou may configure the port of the server by passing the `--port` flag as an argument.\n\n```json [package.json]\n{\n  \"scripts\": {\n    \"preview\": \"vite preview --port 8080\"\n  }\n}\n```\n\nNow the `preview` command will launch the server at `http://localhost:8080`.\n\n## GitHub Pages\n\n1. **Update Vite Config**\n\n   Set the correct `base` in `vite.config.js`.\n\n   If you are deploying to `https://<USERNAME>.github.io/`, or to a custom domain through GitHub Pages (eg. `www.example.com`), set `base` to `'/'`. Alternatively, you can remove `base` from the configuration, as it defaults to `'/'`.\n\n   If you are deploying to `https://<USERNAME>.github.io/<REPO>/` (eg. your repository is at `https://github.com/<USERNAME>/<REPO>`), then set `base` to `'/<REPO>/'`.\n\n2. **Enable GitHub Pages**\n\n   In your repository, go to **Settings → Pages**. Under **Build and deployment**, open the **Source** dropdown, and select **GitHub Actions**.\n\n   GitHub will now deploy your site using a GitHub Actions [workflow](https://docs.github.com/en/actions/concepts/workflows-and-actions/workflows), which is necessary since Vite requires a build step for deployment.\n\n3. **Create a Workflow**\n\n   Create a new file in your repository at `.github/workflows/deploy.yml`. You can also click on **“create your own”** from the previous step, which will generate a starter workflow file for you.\n\n   Here’s a sample workflow that installs dependencies with npm, builds the site, and deploys it whenever you push changes to the `main` branch:\n\n   <<< ./static-deploy-github-pages.yaml#content [.github/workflows/deploy.yml]\n\n## GitLab Pages and GitLab CI\n\n1. Set the correct `base` in `vite.config.js`.\n\n   If you are deploying to `https://<USERNAME or GROUP>.gitlab.io/`, you can omit `base` as it defaults to `'/'`.\n\n   If you are deploying to `https://<USERNAME or GROUP>.gitlab.io/<REPO>/`, for example your repository is at `https://gitlab.com/<USERNAME>/<REPO>`, then set `base` to `'/<REPO>/'`.\n\n2. Create a file called `.gitlab-ci.yml` in the root of your project with the content below. This will build and deploy your site whenever you make changes to your content:\n\n   ```yaml [.gitlab-ci.yml]\n   image: node:lts\n   pages:\n     stage: deploy\n     cache:\n       key:\n         files:\n           - package-lock.json\n         prefix: npm\n       paths:\n         - node_modules/\n     script:\n       - npm install\n       - npm run build\n       - cp -a dist/. public/\n     artifacts:\n       paths:\n         - public\n     rules:\n       - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n   ```\n\n## Netlify\n\n### Netlify CLI\n\n1. Install the [Netlify CLI](https://docs.netlify.com/api-and-cli-guides/cli-guides/get-started-with-cli/) via `npm install -g netlify-cli`.\n2. Create a new site using `netlify init`.\n3. Deploy using `netlify deploy`.\n\nThe Netlify CLI will share with you a preview URL to inspect. When you are ready to go into production, use the `prod` flag: `netlify deploy --prod`.\n\n### Netlify with Git\n\n1. Push your code to a git repository (GitHub, GitLab, BitBucket, Azure DevOps).\n2. [Import the project](https://app.netlify.com/start) to Netlify.\n3. Choose the branch, output directory, and set up environment variables if applicable.\n4. Click on **Deploy**.\n5. Your Vite app is deployed!\n\nAfter your project has been imported and deployed, all subsequent pushes to branches other than the production branch along with pull requests will generate [Preview Deployments](https://docs.netlify.com/deploy/deploy-types/deploy-previews/), and all changes made to the Production Branch (commonly “main”) will result in a [Production Deployment](https://docs.netlify.com/deploy/deploy-overview/#definitions).\n\n## Vercel\n\n### Vercel CLI\n\n1. Install the [Vercel CLI](https://vercel.com/cli) via `npm i -g vercel` and run `vercel` to deploy.\n2. Vercel will detect that you are using Vite and will enable the correct settings for your deployment.\n3. Your application is deployed! (e.g. [vite-vue-template.vercel.app](https://vite-vue-template.vercel.app/))\n\n### Vercel with Git\n\n1. Push your code to your git repository (GitHub, GitLab, Bitbucket).\n2. [Import your Vite project](https://vercel.com/new) into Vercel.\n3. Vercel will detect that you are using Vite and will enable the correct settings for your deployment.\n4. Your application is deployed! (e.g. [vite-vue-template.vercel.app](https://vite-vue-template.vercel.app/))\n\nAfter your project has been imported and deployed, all subsequent pushes to branches will generate [Preview Deployments](https://vercel.com/docs/concepts/deployments/environments#preview), and all changes made to the Production Branch (commonly “main”) will result in a [Production Deployment](https://vercel.com/docs/concepts/deployments/environments#production).\n\nLearn more about Vercel’s [Git Integration](https://vercel.com/docs/concepts/git).\n\n## Cloudflare\n\n### Cloudflare Workers\n\nThe [Cloudflare Vite plugin](https://developers.cloudflare.com/workers/vite-plugin/) provides integration with Cloudflare Workers and uses Vite's Environment API to run your server-side code in the Cloudflare Workers runtime during development.\n\nTo add Cloudflare Workers to an existing Vite project, install the plugin and add it to your config:\n\n```bash\n$ npm install --save-dev @cloudflare/vite-plugin\n```\n\n```js [vite.config.js]\nimport { defineConfig } from 'vite'\nimport { cloudflare } from '@cloudflare/vite-plugin'\n\nexport default defineConfig({\n  plugins: [cloudflare()],\n})\n```\n\n```jsonc [wrangler.jsonc]\n{\n  \"name\": \"my-vite-app\",\n}\n```\n\nAfter running `npm run build`, your application can now be deployed with `npx wrangler deploy`.\n\nYou can also easily add backend APIs to your Vite application to securely communicate with Cloudflare resources. This runs in the Workers runtime during development and deploys alongside your frontend. See the [Cloudflare Vite plugin tutorial](https://developers.cloudflare.com/workers/vite-plugin/tutorial/) for a complete walkthrough.\n\n### Cloudflare Pages\n\n#### Cloudflare Pages with Git\n\nCloudflare Pages gives you a way to deploy directly to Cloudflare without having to manage a Wrangler file.\n\n1. Push your code to your git repository (GitHub, GitLab).\n2. Log in to the Cloudflare dashboard and select your account in **Account Home** > **Workers & Pages**.\n3. Select **Create a new Project** and the **Pages** option, then select Git.\n4. Select the git project you want to deploy and click **Begin setup**\n5. Select the corresponding framework preset in the build setting depending on the Vite framework you have selected. Otherwise enter your build commands for your project and your expected output directory.\n6. Then save and deploy!\n7. Your application is deployed! (e.g `https://<PROJECTNAME>.pages.dev/`)\n\nAfter your project has been imported and deployed, all subsequent pushes to branches will generate [Preview Deployments](https://developers.cloudflare.com/pages/platform/preview-deployments/) unless specified not to in your [branch build controls](https://developers.cloudflare.com/pages/platform/branch-build-controls/). All changes to the Production Branch (commonly \"main\") will result in a Production Deployment.\n\nYou can also add custom domains and handle custom build settings on Pages. Learn more about [Cloudflare Pages Git Integration](https://developers.cloudflare.com/pages/get-started/#manage-your-site).\n\n## Google Firebase\n\n1. Install [firebase-tools](https://www.npmjs.com/package/firebase-tools) via `npm i -g firebase-tools`.\n\n2. Create the following files at the root of your project:\n\n   ::: code-group\n\n   ```json [firebase.json]\n   {\n     \"hosting\": {\n       \"public\": \"dist\",\n       \"ignore\": [],\n       \"rewrites\": [\n         {\n           \"source\": \"**\",\n           \"destination\": \"/index.html\"\n         }\n       ]\n     }\n   }\n   ```\n\n   ```js [.firebaserc]\n   {\n     \"projects\": {\n       \"default\": \"<YOUR_FIREBASE_ID>\"\n     }\n   }\n   ```\n\n   :::\n\n3. After running `npm run build`, deploy using the command `firebase deploy`.\n\n## Surge\n\n1. Install [surge](https://www.npmjs.com/package/surge) via `npm i -g surge`.\n2. Run `npm run build`.\n3. Deploy to surge by typing `surge dist`.\n\nYou can also deploy to a [custom domain](https://surge.sh/help/adding-a-custom-domain) by adding `surge dist yourdomain.com`.\n\n## Azure Static Web Apps\n\nYou can quickly deploy your Vite app with Microsoft Azure [Static Web Apps](https://aka.ms/staticwebapps) service. You need:\n\n- An Azure account and a subscription key. You can create a [free Azure account here](https://azure.microsoft.com/free).\n- Your app code pushed to [GitHub](https://github.com).\n- The [SWA Extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestaticwebapps) in [Visual Studio Code](https://code.visualstudio.com).\n\nInstall the extension in VS Code and navigate to your app root. Open the Static Web Apps extension, sign in to Azure, and click the '+' sign to create a new Static Web App. You will be prompted to designate which subscription key to use.\n\nFollow the wizard started by the extension to give your app a name, choose a framework preset, and designate the app root (usually `/`) and built file location `/dist`. The wizard will run and will create a GitHub action in your repo in a `.github` folder.\n\nThe action will work to deploy your app (watch its progress in your repo's Actions tab) and, when successfully completed, you can view your app in the address provided in the extension's progress window by clicking the 'Browse Website' button that appears when the GitHub action has run.\n\n## Render\n\nYou can deploy your Vite app as a Static Site on [Render](https://render.com/).\n\n1. Create a [Render account](https://dashboard.render.com/register).\n\n2. In the [Dashboard](https://dashboard.render.com/), click the **New** button and select **Static Site**.\n\n3. Connect your GitHub/GitLab account or use a public repository.\n\n4. Specify a project name and branch.\n   - **Build Command**: `npm install && npm run build`\n   - **Publish Directory**: `dist`\n\n5. Click **Create Static Site**. Your app should be deployed at `https://<PROJECTNAME>.onrender.com/`.\n\nBy default, any new commit pushed to the specified branch will automatically trigger a new deployment. [Auto-Deploy](https://render.com/docs/deploys#toggling-auto-deploy-for-a-service) can be configured in the project settings.\n\nYou can also add a [custom domain](https://render.com/docs/custom-domains) to your project.\n\n## Flightcontrol\n\nDeploy your static site using [Flightcontrol](https://www.flightcontrol.dev/?ref=docs-vite) by following these [instructions](https://www.flightcontrol.dev/docs/reference/examples/vite?ref=docs-vite).\n\n## Kinsta Static Site Hosting\n\nDeploy your static site using [Kinsta](https://kinsta.com/static-site-hosting/) by following these [instructions](https://kinsta.com/docs/static-site-hosting/static-site-quick-start/react-static-site-examples/#react-with-vite).\n\n## xmit Static Site Hosting\n\nDeploy your static site using [xmit](https://xmit.co) by following this [guide](https://xmit.dev/posts/vite-quickstart/).\n\n## Zephyr Cloud\n\n[Zephyr Cloud](https://zephyr-cloud.io) is a deployment platform that integrates directly into your build process and provides global edge distribution for module federation and other kind of applications.\n\nZephyr follows a different approach than other cloud providers. It integrates directly with Vite build process, so every time you build or run the dev server for your application, it will be automatically deployed with Zephyr Cloud.\n\nFollow the steps in [the Vite deployment guide](https://docs.zephyr-cloud.io/bundlers/vite) to get started.\n\n## EdgeOne Pages\n\nDeploy your static site using [EdgeOne Pages](https://edgeone.ai/products/pages) by following these [instructions](https://pages.edgeone.ai/document/vite).\n"
  },
  {
    "path": "docs/guide/troubleshooting.md",
    "content": "# Troubleshooting\n\nSee [Rollup's troubleshooting guide](https://rollupjs.org/troubleshooting/) for more information too.\n\nIf the suggestions here don't work, please try posting questions on [GitHub Discussions](https://github.com/vitejs/vite/discussions) or in the `#help` channel of [Vite Land Discord](https://chat.vite.dev).\n\n## CLI\n\n### `Error: Cannot find module 'C:\\foo\\bar&baz\\vite\\bin\\vite.js'`\n\nThe path to your project folder may include `&`, which doesn't work with `npm` on Windows ([npm/cmd-shim#45](https://github.com/npm/cmd-shim/issues/45)).\n\nYou will need to either:\n\n- Switch to another package manager (e.g. `pnpm`, `yarn`)\n- Remove `&` from the path to your project\n\n## Config\n\n### This package is ESM only\n\nWhen importing an ESM only package by `require`, the following error happens.\n\n> Failed to resolve \"foo\". This package is ESM only but it was tried to load by `require`.\n\n> Error [ERR_REQUIRE_ESM]: require() of ES Module /path/to/dependency.js from /path/to/vite.config.js not supported.\n> Instead change the require of index.js in /path/to/vite.config.js to a dynamic import() which is available in all CommonJS modules.\n\nIn Node.js <=22, ESM files cannot be loaded by [`require`](https://nodejs.org/docs/latest-v22.x/api/esm.html#require) by default.\n\nWhile it may work using [`--experimental-require-module`](https://nodejs.org/docs/latest-v22.x/api/modules.html#loading-ecmascript-modules-using-require), or Node.js >22, or in other runtimes, we still recommend converting your config to ESM by either:\n\n- adding `\"type\": \"module\"` to the nearest `package.json`\n- renaming `vite.config.js`/`vite.config.ts` to `vite.config.mjs`/`vite.config.mts`\n\n## Dev Server\n\n### Requests are stalled forever\n\nIf you are using Linux, file descriptor limits and inotify limits may be causing the issue. As Vite does not bundle most of the files, browsers may request many files which require many file descriptors, going over the limit.\n\nTo solve this:\n\n- Increase file descriptor limit by `ulimit`\n\n  ```shell\n  # Check current limit\n  $ ulimit -Sn\n  # Change limit (temporary)\n  $ ulimit -Sn 10000 # You might need to change the hard limit too\n  # Restart your browser\n  ```\n\n- Increase the following inotify related limits by `sysctl`\n\n  ```shell\n  # Check current limits\n  $ sysctl fs.inotify\n  # Change limits (temporary)\n  $ sudo sysctl fs.inotify.max_queued_events=16384\n  $ sudo sysctl fs.inotify.max_user_instances=8192\n  $ sudo sysctl fs.inotify.max_user_watches=524288\n  ```\n\nIf the above steps don't work, you can try adding `DefaultLimitNOFILE=65536` as an un-commented config to the following files:\n\n- /etc/systemd/system.conf\n- /etc/systemd/user.conf\n\nFor Ubuntu Linux, you may need to add the line `* - nofile 65536` to the file `/etc/security/limits.conf` instead of updating systemd config files.\n\nNote that these settings persist but a **restart is required**.\n\nAlternatively, if the server is running inside a VS Code devcontainer, the request may appear to be stalled. To fix this issue, see\n[Dev Containers / VS Code Port Forwarding](#dev-containers-vs-code-port-forwarding).\n\n### Vite crashes with ENOSPC error\n\nIf you see an error like this on Linux:\n\n> Error: ENOSPC: System limit for number of file watchers reached\n\nThis happens when you have too many files in your project directory (e.g., many images or assets) and exceed the system's file watcher limit. Linux has a default limit of around 8,192-10,000 file watchers.\n\nTo solve this, you can:\n\n- Increase the system file watcher limit:\n\n  ```shell\n  # Check current limit\n  $ cat /proc/sys/fs/inotify/max_user_watches\n  # Increase limit (temporary)\n  $ sudo sysctl fs.inotify.max_user_watches=524288\n  # Make it permanent - add to /etc/sysctl.conf (or edit if it already exists)\n  $ echo \"fs.inotify.max_user_watches=524288\" | sudo tee -a /etc/sysctl.conf\n  $ sudo sysctl -p\n  ```\n\n- Exclude directories with many files from file watching using [`server.watch.ignored`](/config/server-options#server-watch)\n- Use polling instead of file system events with [`server.watch.usePolling`](/config/server-options#server-watch). Note that polling uses more CPU resources\n\n### Network requests stop loading\n\nWhen using a self-signed SSL certificate, Chrome ignores all caching directives and reloads the content. Vite relies on these caching directives.\n\nTo resolve the problem use a trusted SSL cert.\n\nSee: [Cache problems](https://helpx.adobe.com/mt/experience-manager/kb/cache-problems-on-chrome-with-SSL-certificate-errors.html), [Chrome issue](https://bugs.chromium.org/p/chromium/issues/detail?id=110649#c8)\n\n#### macOS\n\nYou can install a trusted cert via the CLI with this command:\n\n```\nsecurity add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain-db your-cert.cer\n```\n\nOr, by importing it into the Keychain Access app and updating the trust of your cert to \"Always Trust.\"\n\n### 431 Request Header Fields Too Large\n\nWhen the server / WebSocket server receives a large HTTP header, the request will be dropped and the following warning will be shown.\n\n> Server responded with status code 431. See https://vite.dev/guide/troubleshooting.html#_431-request-header-fields-too-large.\n\nThis is because Node.js limits request header size to mitigate [CVE-2018-12121](https://www.cve.org/CVERecord?id=CVE-2018-12121).\n\nTo avoid this, try to reduce your request header size. For example, if the cookie is long, delete it. Or you can use [`--max-http-header-size`](https://nodejs.org/api/cli.html#--max-http-header-sizesize) to change max header size.\n\n### Dev Containers / VS Code Port Forwarding\n\nIf you are using a Dev Container or port forwarding feature in VS Code, you may need to set the [`server.host`](/config/server-options.md#server-host) option to `127.0.0.1` in the config to make it work.\n\nThis is because [the port forwarding feature in VS Code does not support IPv6](https://github.com/microsoft/vscode-remote-release/issues/7029).\n\nSee [#16522](https://github.com/vitejs/vite/issues/16522) for more details.\n\n## HMR\n\n### Vite detects a file change but the HMR is not working\n\nYou may be importing a file with a different case. For example, `src/foo.js` exists and `src/bar.js` contains:\n\n```js\nimport './Foo.js' // should be './foo.js'\n```\n\nRelated issue: [#964](https://github.com/vitejs/vite/issues/964)\n\n### Vite does not detect a file change\n\nIf you are running Vite with WSL2, Vite cannot watch file changes in some conditions. See [`server.watch` option](/config/server-options.md#server-watch).\n\n### A full reload happens instead of HMR\n\nIf HMR is not handled by Vite or a plugin, a full reload will happen as it's the only way to refresh the state.\n\nIf HMR is handled but it is within a circular dependency, a full reload will also happen to recover the execution order. To solve this, try breaking the loop. You can run `vite --debug hmr` to log the circular dependency path if a file change triggered it.\n\n## Build\n\n### Built file does not work because of CORS error\n\nIf the HTML file output was opened with `file` protocol, the scripts won't run with the following error.\n\n> Access to script at 'file:///foo/bar.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.\n\n> Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///foo/bar.js. (Reason: CORS request not http).\n\nSee [Reason: CORS request not HTTP - HTTP | MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSRequestNotHttp) for more information about why this happens.\n\nYou will need to access the file with `http` protocol. The easiest way to achieve this is to run `npx vite preview`.\n\n### No such file or directory error due to case sensitivity\n\nIf you encounter errors like `ENOENT: no such file or directory` or `Module not found`, this often occurs when your project was developed on a case-insensitive filesystem (Windows / macOS) but built on a case-sensitive one (Linux). Please make sure that the imports have the correct casing.\n\n### `Failed to fetch dynamically imported module` error\n\n> TypeError: Failed to fetch dynamically imported module\n\nThis error occurs in several cases:\n\n- Version skew\n- Poor network conditions\n- Browser extensions blocking requests\n\n#### Version skew\n\nWhen you deploy a new version of your application, the HTML file and the JS files still reference old chunk names that were deleted in the new deployment. This happens when:\n\n1. Users have an old version of your app cached in their browser\n2. You deploy a new version with different chunk names (due to code changes)\n3. The cached HTML tries to load chunks that no longer exist\n\nIf you are using a framework, refer to their documentation first as it may have a built-in solution for this problem.\n\nTo resolve this, you can:\n\n- **Keep old chunks temporarily**: Consider keeping the previous deployment's chunks for a period to allow cached users to transition smoothly.\n- **Use a service worker**: Implement a service worker that will prefetch all the assets and cache them.\n- **Prefetch the dynamic chunks**: Note that this does not help if your HTML file is cached by the browser due to `Cache-Control` headers.\n- **Implement a graceful fallback**: Implement error handling for dynamic imports to reload the page when chunks are missing. See [Load Error Handling](./build.md#load-error-handling) for more details.\n\n#### Poor network conditions\n\nThis error may occur in unstable network environments. For example, when the request fails due to network errors or server downtime.\n\nNote that you cannot retry the dynamic import due to browser limitations ([whatwg/html#6768](https://github.com/whatwg/html/issues/6768)).\n\n#### Browser extensions blocking requests\n\nThe error may also occur if the browser extensions (like ad-blockers) are blocking that request.\n\nIt might be possible to work around by selecting a different chunk name by [`build.rolldownOptions.output.chunkFileNames`](../config/build-options.md#build-rolldownoptions), as these extensions often block requests based on file names (e.g. names containing `ad`, `track`).\n\n## Optimized Dependencies\n\n### Outdated pre-bundled deps when linking to a local package\n\nThe hash key used to invalidate optimized dependencies depends on the package lock contents, the patches applied to dependencies, and the options in the Vite config file that affects the bundling of node modules. This means that Vite will detect when a dependency is overridden using a feature as [npm overrides](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides), and re-bundle your dependencies on the next server start. Vite won't invalidate the dependencies when you use a feature like [npm link](https://docs.npmjs.com/cli/v9/commands/npm-link). In case you link or unlink a dependency, you'll need to force re-optimization on the next server start by using `vite --force`. We recommend using overrides instead, which are supported now by every package manager (see also [pnpm overrides](https://pnpm.io/9.x/package_json#pnpmoverrides) and [yarn resolutions](https://yarnpkg.com/configuration/manifest/#resolutions)).\n\n## Performance Bottlenecks\n\nIf you suffer any application performance bottlenecks resulting in slow load times, you can start the built-in Node.js inspector with your Vite dev server or when building your application to create the CPU profile:\n\n::: code-group\n\n```bash [dev server]\nvite --profile --open\n```\n\n```bash [build]\nvite build --profile\n```\n\n:::\n\n::: tip Vite Dev Server\nOnce your application is opened in the browser, just await finish loading it and then go back to the terminal and press `p` key (will stop the Node.js inspector) then press `q` key to stop the dev server.\n:::\n\nNode.js inspector will generate `vite-profile-0.cpuprofile` in the root folder, go to https://www.speedscope.app/, and upload the CPU profile using the `BROWSE` button to inspect the result.\n\nYou can install [vite-plugin-inspect](https://github.com/antfu/vite-plugin-inspect), which lets you inspect the intermediate state of Vite plugins and can also help you to identify which plugins or middlewares are the bottleneck in your applications. The plugin can be used in both dev and build modes. Check the readme file for more details.\n\n## Others\n\n### Module externalized for browser compatibility\n\nWhen you use a Node.js module in the browser, Vite will output the following warning.\n\n> Module \"fs\" has been externalized for browser compatibility. Cannot access \"fs.readFile\" in client code.\n\nThis is because Vite does not automatically polyfill Node.js modules.\n\nWe recommend avoiding Node.js modules for browser code to reduce the bundle size, although you can add polyfills manually. If the module is imported from a third-party library (that's meant to be used in the browser), it's advised to report the issue to the respective library.\n\n### Syntax Error / Type Error happens\n\nVite cannot handle and does not support code that only runs on non-strict mode (sloppy mode). This is because Vite uses ESM and it is always [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) inside ESM.\n\nFor example, you might see these errors.\n\n> [ERROR] With statements cannot be used with the \"esm\" output format due to strict mode\n\n> TypeError: Cannot create property 'foo' on boolean 'false'\n\nIf these codes are used inside dependencies, you could use [`patch-package`](https://github.com/ds300/patch-package) (or [`yarn patch`](https://yarnpkg.com/cli/patch) or [`pnpm patch`](https://pnpm.io/cli/patch)) for an escape hatch.\n\n### Browser extensions\n\nSome browser extensions (like ad-blockers) may prevent the Vite client from sending requests to the Vite dev server. You may see a white screen without logged errors in this case. You may also see the following error:\n\n> TypeError: Failed to fetch dynamically imported module\n\nTry disabling extensions if you have this issue.\n\n### Cross drive links on Windows\n\nIf there's a cross drive links in your project on Windows, Vite may not work.\n\nAn example of cross drive links are:\n\n- a virtual drive linked to a folder by `subst` command\n- a symlink/junction to a different drive by `mklink` command (e.g. Yarn global cache)\n\nRelated issue: [#10802](https://github.com/vitejs/vite/issues/10802)\n\n<script setup lang=\"ts\">\n// redirect old links with hash to old version docs\nif (typeof window !== \"undefined\") {\n  const hashForOldVersion = {\n    'vite-cjs-node-api-deprecated': 6\n  }\n\n  const version = hashForOldVersion[location.hash.slice(1)]\n  if (version) {\n    // update the scheme and the port as well so that it works in local preview (it is http and 4173 locally)\n    location.href = `https://v${version}.vite.dev` + location.pathname + location.search + location.hash\n  }\n}\n</script>\n"
  },
  {
    "path": "docs/guide/using-plugins.md",
    "content": "# Using Plugins\n\nVite can be extended using plugins, which are based on Rollup's well-designed plugin interface with a few extra Vite-specific options. This means that Vite users can rely on the mature ecosystem of Rollup plugins, while also being able to extend the dev server and SSR functionality as needed.\n\n<ScrimbaLink href=\"https://scrimba.com/intro-to-vite-c03p6pbbdq/~0y4g?via=vite\" title=\"Using Plugins in Vite\">Watch an interactive lesson on Scrimba</ScrimbaLink>\n\n## Adding a Plugin\n\nTo use a plugin, it needs to be added to the `devDependencies` of the project and included in the `plugins` array in the `vite.config.js` config file. For example, to provide support for legacy browsers, the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) can be used:\n\n```\n$ npm add -D @vitejs/plugin-legacy\n```\n\n```js twoslash [vite.config.js]\nimport legacy from '@vitejs/plugin-legacy'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    legacy({\n      targets: ['defaults', 'not IE 11'],\n    }),\n  ],\n})\n```\n\n`plugins` also accepts presets including several plugins as a single element. This is useful for complex features (like framework integration) that are implemented using several plugins. The array will be flattened internally.\n\nFalsy plugins will be ignored, which can be used to easily activate or deactivate plugins.\n\n## Finding Plugins\n\n:::tip NOTE\nVite aims to provide out-of-the-box support for common web development patterns. Before searching for a Vite or compatible Rollup plugin, check out the [Features Guide](../guide/features.md). A lot of the cases where a plugin would be needed in a Rollup project are already covered in Vite.\n:::\n\nCheck out the [Plugins section](../plugins/) for information about official plugins. Community plugins that are published to npm are listed in [Vite Plugin Registry](https://registry.vite.dev/plugins).\n\n## Enforcing Plugin Ordering\n\nFor compatibility with some Rollup plugins, it may be needed to enforce the order of the plugin or only apply at build time. This should be an implementation detail for Vite plugins. You can enforce the position of a plugin with the `enforce` modifier:\n\n- `pre`: invoke plugin before Vite core plugins\n- default: invoke plugin after Vite core plugins\n- `post`: invoke plugin after Vite build plugins\n\n```js twoslash [vite.config.js]\nimport image from '@rollup/plugin-image'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    {\n      ...image(),\n      enforce: 'pre',\n    },\n  ],\n})\n```\n\nCheck out [Plugins API Guide](./api-plugin.md#plugin-ordering) for detailed information.\n\n## Conditional Application\n\nBy default, plugins are invoked for both serve and build. In cases where a plugin needs to be conditionally applied only during serve or build, use the `apply` property to only invoke them during `'build'` or `'serve'`:\n\n```js twoslash [vite.config.js]\nimport typescript2 from 'rollup-plugin-typescript2'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    {\n      ...typescript2(),\n      apply: 'build',\n    },\n  ],\n})\n```\n\n## Building Plugins\n\nCheck out the [Plugins API Guide](./api-plugin.md) for documentation about creating plugins.\n"
  },
  {
    "path": "docs/guide/why.md",
    "content": "# Why Vite\n\nAs web applications have grown in size and complexity, the tools used to build them have struggled to keep up. Developers working on large projects have experienced painfully slow dev server startups, sluggish hot updates, and long production build times. Each generation of build tooling has improved on the last, but these problems have persisted.\n\nVite was created to address this. Rather than incrementally improving existing approaches, it rethought how code should be served during development. Since then, Vite has evolved through multiple major versions, each time adapting to new capabilities in the ecosystem: from leveraging native ES modules in the browser, to adopting a fully Rust-powered toolchain.\n\nToday, Vite powers many frameworks and tools. Its architecture is designed to evolve with the web platform rather than lock into any single approach, making it a foundation you can build on for the long term.\n\n## The Origins\n\nWhen Vite was first created, browsers had just gained wide support for [ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) (ESM), a way to load JavaScript files directly, without needing a tool to bundle them into a single file first. Traditional build tools (often called _bundlers_) would process your entire application upfront before anything could be shown in the browser. The larger the app, the longer you waited.\n\nVite took a different approach. It split the work into two parts:\n\n- **Dependencies** (libraries that rarely change) are [pre-bundled](./dep-pre-bundling.md) once using fast native tooling, so they're ready instantly.\n- **Source code** (your application code that changes frequently) is served on-demand over native ESM. The browser loads only what it needs for the current page, and Vite transforms each file as it's requested.\n\nThis meant dev server startup was nearly instant, regardless of application size. When you edited a file, Vite used [Hot Module Replacement](./features.md#hot-module-replacement) (HMR) over native ESM to update just that module in the browser, without a full page reload or waiting for a rebuild.\n\n<script setup>\nimport bundlerSvg from '../images/bundler.svg?raw'\nimport esmSvg from '../images/esm.svg?raw'\n</script>\n<svg-image :svg=\"bundlerSvg\" />\n\n_In a bundle-based dev server, the entire application is bundled before it can be served._\n\n<svg-image :svg=\"esmSvg\" />\n\n_In an ESM-based dev server, modules are served on-demand as the browser requests them._\n\nVite was not the first tool to explore this approach. [Snowpack](https://www.snowpack.dev/) pioneered unbundled development and inspired Vite's dependency pre-bundling. [WMR](https://github.com/preactjs/wmr) by the Preact team inspired the universal plugin API that works in both dev and build. [@web/dev-server](https://modern-web.dev/docs/dev-server/overview/) influenced Vite 1.0's server architecture. Vite built on these ideas and carried them forward.\n\nEven though unbundled ESM works well during development, shipping it in production is still inefficient due to additional network round trips from nested imports. That's [why bundling is still necessary](https://rolldown.rs/in-depth/why-bundlers) for optimized production builds.\n\n## Growing with the Ecosystem\n\nAs Vite matured, frameworks began adopting it as their build layer. Its [plugin API](./api-plugin.md), based on Rollup's conventions, made integration natural without requiring frameworks to work around Vite's internals. [Nuxt](https://nuxt.com/), [SvelteKit](https://svelte.dev/docs/kit), [Astro](https://astro.build/), [React Router](https://reactrouter.com/), [Analog](https://analogjs.org/), [SolidStart](https://start.solidjs.com/), and others chose Vite as their foundation. Tools like [Vitest](https://vitest.dev/) and [Storybook](https://storybook.js.org/) built on it too, extending Vite's reach beyond app bundling. Backend frameworks like [Laravel](https://laravel.com/docs/vite) and [Ruby on Rails](https://vite-ruby.netlify.app/) integrated Vite for their frontend asset pipelines.\n\nThis growth was not one-directional. The ecosystem shaped Vite as much as Vite shaped the ecosystem. The Vite team runs [vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci), which tests major ecosystem projects against every Vite change. Ecosystem health is not an afterthought. It is part of the release process.\n\n## A Unified Toolchain\n\nVite originally relied on two separate tools under the hood: [esbuild](https://esbuild.github.io/) for fast compilation during development, and [Rollup](https://rollupjs.org/) for thorough optimization in production builds. This worked, but maintaining two pipelines introduced inconsistencies: different transformation behaviors, separate plugin systems, and growing glue code to keep them aligned.\n\n[Rolldown](https://rolldown.rs/) was built to unify both into a single bundler: written in Rust for native speed, and compatible with the same plugin API the ecosystem already relied on. It uses [Oxc](https://oxc.rs/) for parsing, transforming, and minifying. This gives Vite an end-to-end toolchain where the build tool, bundler, and compiler are maintained together and evolve as a unit.\n\nThe result is one consistent pipeline from development to [production](./build.md). The migration was done carefully: a [technical preview](https://voidzero.dev/posts/announcing-rolldown-vite) shipped first so early adopters could validate the change, ecosystem CI caught compatibility issues early, and a compatibility layer preserved existing configurations.\n\n## Where Vite is Heading\n\nVite's architecture continues to evolve. Several efforts are shaping its future:\n\n- **Full bundle mode**: Unbundled ESM was the right tradeoff when Vite was created because no tool was both fast enough and had the HMR and plugin capabilities needed to bundle during dev. Rolldown changes that. Since exceptionally large codebases can experience slow page loads due to the high number of unbundled network requests, the team is exploring a mode where the dev server bundles code similarly to production, reducing network overhead.\n\n- **Environment API**: Instead of treating \"client\" and \"SSR\" as the only two build targets, the [Environment API](./api-environment-instances.md) lets frameworks define custom environments (edge runtimes, service workers, and other deployment targets), each with their own module resolution and execution rules. As where and how code runs continues to diversify, Vite's model expands with it.\n\n- **Evolving with JavaScript**: With Oxc and Rolldown closely collaborating with Vite, new language features and standards can be adopted quickly across the entire toolchain, without waiting on upstream dependencies.\n\nVite's goal is not to be the final tool, but to be one that keeps evolving with the web platform, and with the developers building on it.\n"
  },
  {
    "path": "docs/index.md",
    "content": "---\ntitle: Vite\ntitleTemplate: Next Generation Frontend Tooling\nlayout: home\ntheme: dark\n---\n\n<script setup>\nimport Home from './.vitepress/theme/landing/Layout.vue'\n</script>\n\n<Home />\n"
  },
  {
    "path": "docs/live.md",
    "content": "---\ntitle: 5th anniversary of the Vite Team Creation\nlayout: home\ntheme: dark\ndescription: \"Vite: The Documentary re-premiere. Join the ecosystem this March 19th at 3 PM UTC to remember the story we wrote together. And participate in the live stage to discuss our past, present, and future. We'll be waiting for you!\"\nhead:\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:title\n      content: 5th anniversary of the Vite Team Creation\n  - - meta\n    - property: og:description\n      content: \"Vite: The Documentary re-premiere. Join the ecosystem this March 19th at 3 PM UTC to remember the story we wrote together. And participate in the live stage to discuss our past, present, and future. We'll be waiting for you!\"\n  - - meta\n    - property: og:type\n      content: website\n  - - meta\n    - property: og:image\n      content: https://vite.dev/og-image-5-anniversary-live.webp\n  - - meta\n    - property: og:url\n      content: https://vite.dev/live\n  - - meta\n    - name: twitter:card\n      content: summary_large_image\n---\n\n<script setup>\nimport Live from './.vitepress/theme/live/Layout.vue'\n</script>\n\n<Live />\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"@vitejs/monorepo-docs\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"docs\": \"vitepress dev\",\n    \"docs-build\": \"vitepress build\",\n    \"docs-serve\": \"vitepress serve\"\n  },\n  \"devDependencies\": {\n    \"@iconify/vue\": \"^5.0.0\",\n    \"@shikijs/vitepress-twoslash\": \"^4.0.2\",\n    \"@types/express\": \"^5.0.6\",\n    \"@voidzero-dev/vitepress-theme\": \"^4.8.3\",\n    \"feed\": \"^5.2.0\",\n    \"markdown-it-image-size\": \"^15.0.1\",\n    \"oxc-minify\": \"^0.120.0\",\n    \"vitepress\": \"^2.0.0-alpha.16\",\n    \"vitepress-plugin-graphviz\": \"^0.0.1\",\n    \"vitepress-plugin-group-icons\": \"^1.7.1\",\n    \"vitepress-plugin-llms\": \"^1.11.0\",\n    \"vue\": \"^3.5.30\",\n    \"vue-tsc\": \"^3.2.5\"\n  }\n}\n"
  },
  {
    "path": "docs/plugins/index.md",
    "content": "# Plugins\n\n:::tip NOTE\nVite aims to provide out-of-the-box support for common web development patterns. Before searching for a Vite or Compatible Rollup plugin, check out the [Features Guide](../guide/features.md). A lot of the cases where a plugin would be needed in a Rollup project are already covered in Vite.\n:::\n\nCheck out [Using Plugins](../guide/using-plugins) for information on how to use plugins.\n\n## Official Plugins\n\n### [@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue)\n\nProvides Vue 3 Single File Components support.\n\n### [@vitejs/plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx)\n\nProvides Vue 3 JSX support (via [dedicated Babel transform](https://github.com/vuejs/babel-plugin-jsx)).\n\n### [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react)\n\nProvides React Fast Refresh support via [Oxc Transformer](https://oxc.rs/docs/guide/usage/transformer).\n\n### [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react-swc)\n\nReplaces Oxc with [SWC](https://swc.rs/) during development for SWC plugin usage. During production builds, SWC+Oxc Transformer are used when using plugins. For big projects that require custom plugins, cold start and Hot Module Replacement (HMR) can be significantly faster, if the plugin is also available for SWC.\n\n### [@vitejs/plugin-rsc](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc)\n\nVite supports [React Server Components (RSC)](https://react.dev/reference/rsc/server-components) through the plugin. It utilizes the [Environment API](/guide/api-environment) to provide low-level primitives that React frameworks can use to integrate RSC features. You can try a minimal standalone RSC application with:\n\n```bash\nnpm create vite@latest -- --template rsc\n```\n\nRead the [plugin documentation](https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-rsc) to learn more.\n\n### [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy)\n\nProvides legacy browsers support for the production build.\n\n## Community Plugins\n\nCheck out [Vite Plugin Registry](https://registry.vite.dev/plugins) for the list of plugins published to npm.\n\n## Rolldown Builtin Plugins\n\nVite uses [Rolldown](https://rolldown.rs/) under the hood and it provides a few builtin plugins for common use cases.\n\nRead the [Rolldown Builtin Plugins section](https://rolldown.rs/builtin-plugins/) for more information.\n\n## Rolldown / Rollup Plugins\n\n[Vite plugins](../guide/api-plugin) are an extension of Rollup's plugin interface. Check out the [Rollup Plugin Compatibility section](../guide/api-plugin#rolldown-plugin-compatibility) for more information.\n"
  },
  {
    "path": "docs/public/_headers",
    "content": "/assets/*\n  cache-control: max-age=31536000\n  cache-control: immutable\n\n/*.svg\n  cache-control: max-age=604800\n  cache-control: immutable\n\n/*.png\n  cache-control: max-age=604800\n  cache-control: immutable\n\n/*.webp\n  cache-control: max-age=604800\n  cache-control: immutable\n"
  },
  {
    "path": "docs/public/_redirects",
    "content": "# temporary, we'll flip this around some day\nhttps://vitejs.dev/* https://vite.dev/:splat 301!\n\n/guide/api-vite-runtime /guide/api-environment 301\n/guide/api-vite-runtime.html /guide/api-environment 301\n/guide/api-vite-environment /guide/api-environment 301\n/guide/api-vite-environment.html /guide/api-environment 301\n/guide/comparisons /guide/why#how-vite-relates-to-other-unbundled-build-tools 301\n/guide/comparisons.html /guide/why#how-vite-relates-to-other-unbundled-build-tools 301\n/guide/rolldown https://v7.vite.dev/guide/rolldown 301\n/guide/rolldown.html https://v7.vite.dev/guide/rolldown 301\n\n# llms.txt\n/*.txt           /:splat.md 301\n/llms.md         /llms.txt 301\n/llms.txt        /llms.txt 200!\n/llms-full.txt   /llms-full.txt 200!\n\n# short links\n/rolldown /guide/rolldown 301\n"
  },
  {
    "path": "docs/releases.md",
    "content": "<script setup>\nimport SupportedVersions from './.vitepress/theme/components/SupportedVersions.vue';\n</script>\n\n# Releases\n\nVite releases follow [Semantic Versioning](https://semver.org/). You can see the latest stable version of Vite in the [Vite npm package page](https://www.npmjs.com/package/vite).\n\nA full changelog of past releases is [available on GitHub](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md).\n\n## Release Cycle\n\nVite does not have a fixed release cycle.\n\n- **Patch** releases are released as needed (usually every week).\n- **Minor** releases always contain new features and are released as needed. Minor releases always have a beta pre-release phase (usually every two months).\n- **Major** releases generally align with [Node.js EOL schedule](https://endoflife.date/nodejs), and will be announced ahead of time. These releases will go through long-term discussions with the ecosystem, and have alpha and beta pre-release phases (usually every year).\n\n## Supported Versions\n\nIn summary, the current supported Vite versions are:\n\n<SupportedVersions />\n\n<br>\n\nThe supported version ranges are automatically determined by:\n\n- **Current Minor** gets regular fixes.\n- **Previous Major** (only for its latest minor) and **Previous Minor** receives important fixes and security patches.\n- **Second-to-last Major** (only for its latest minor) and **Second-to-last Minor** receives security patches.\n- All versions before these are no longer supported.\n\nWe recommend updating Vite regularly. Check out the [Migration Guides](https://vite.dev/guide/migration.html) when you update to each Major. The Vite team works closely with the main projects in the ecosystem to ensure the quality of new versions. We test new Vite versions before releasing them through the [vite-ecosystem-ci project](https://github.com/vitejs/vite-ecosystem-ci). Most projects using Vite should be able to quickly offer support or migrate to new versions as soon as they are released.\n\n## Semantic Versioning Edge Cases\n\n### TypeScript Definitions\n\nWe may ship incompatible changes to TypeScript definitions between minor versions. This is because:\n\n- Sometimes TypeScript itself ships incompatible changes between minor versions, and we may have to adjust types to support newer versions of TypeScript.\n- Occasionally we may need to adopt features that are only available in a newer version of TypeScript, raising the minimum required version of TypeScript.\n- If you are using TypeScript, you can use a semver range that locks the current minor and manually upgrade when a new minor version of Vite is released.\n\n### Node.js non-LTS versions\n\nNon-LTS Node.js versions (odd-numbered) are not tested as part of Vite's CI, but they should still work before their [EOL](https://endoflife.date/nodejs).\n\n## Pre Releases\n\nMinor releases typically go through a non-fixed number of beta releases. Major releases will go through an alpha phase and a beta phase.\n\nPre-releases allow early adopters and maintainers from the Ecosystem to do integration and stability testing, and provide feedback. Do not use pre-releases in production. All pre-releases are considered unstable and may ship breaking changes in between. Always pin to exact versions when using pre-releases.\n\n## Deprecations\n\nWe periodically deprecate features that have been superseded by better alternatives in Minor releases. Deprecated features will continue to work with a type or logged warning. They will be removed in the next major release after entering deprecated status. The [Migration Guide](https://vite.dev/guide/migration.html) for each major will list these removals and document an upgrade path for them.\n\n## Experimental Features\n\nSome features are marked as experimental when released in a stable version of Vite. Experimental features allow us to gather real-world experience to influence their final design. The goal is to let users provide feedback by testing them in production. Experimental features themselves are considered unstable, and should only be used in a controlled manner. These features may change between Minors, so users must pin their Vite version when they rely on them. We will create [a GitHub discussion](https://github.com/vitejs/vite/discussions/categories/feedback?discussions_q=is%3Aopen+label%3Aexperimental+category%3AFeedback) for each experimental feature.\n"
  },
  {
    "path": "docs/team.md",
    "content": "---\nlayout: page\ntitle: Meet the Team\ndescription: The development of Vite is guided by an international team.\n---\n\n<script setup>\nimport {\n  VPTeamPage,\n  VPTeamPageTitle,\n  VPTeamPageSection,\n  VPTeamMembers\n} from '@voidzero-dev/vitepress-theme'\nimport { core, emeriti } from './_data/team'\n</script>\n\n<VPTeamPage>\n  <VPTeamPageTitle>\n    <template #title>Meet the Team</template>\n    <template #lead>\n      The development of Vite is guided by an international team, some of whom\n      have chosen to be featured below.\n    </template>\n  </VPTeamPageTitle>\n  <VPTeamMembers :members=\"core\" />\n  <VPTeamPageSection>\n    <template #title>Team Emeriti</template>\n    <template #lead>\n      Here we honor some no-longer-active team members who have made valuable\n      contributions in the past.\n    </template>\n    <template #members>\n      <VPTeamMembers size=\"small\" :members=\"emeriti\" />\n    </template>\n  </VPTeamPageSection>\n</VPTeamPage>\n"
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n    \"types\": [\"vite/client\"],\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"**/*.ts\", \".vitepress/**/*.ts\", \".vitepress/**/*.vue\"]\n}\n"
  },
  {
    "path": "eslint.config.js",
    "content": "// @ts-check\nimport { createRequire } from 'node:module'\nimport eslint from '@eslint/js'\nimport pluginN from 'eslint-plugin-n'\nimport pluginImportX from 'eslint-plugin-import-x'\nimport pluginRegExp from 'eslint-plugin-regexp'\nimport tseslint from 'typescript-eslint'\nimport { defineConfig } from 'eslint/config'\nimport globals from 'globals'\n\nconst require = createRequire(import.meta.url)\nconst pkgVite = require('./packages/vite/package.json')\n\n// Some rules work better with typechecking enabled, but as enabling it is slow,\n// we only do so when linting in IDEs for now. If you want to lint with typechecking\n// explicitly, set this to `true` manually.\nconst shouldTypeCheck = typeof process.env.VSCODE_PID === 'string'\n\nexport default defineConfig(\n  {\n    ignores: [\n      'packages/create-vite/template-*',\n      '**/dist/**',\n      '**/fixtures/**',\n      '**/playground-temp/**',\n      '**/temp/**',\n      '**/.vitepress/cache/**',\n      '**/*.snap',\n    ],\n  },\n  eslint.configs.recommended,\n  ...tseslint.configs.recommended,\n  ...tseslint.configs.stylistic,\n  pluginRegExp.configs['flat/recommended'],\n  {\n    name: 'main',\n    languageOptions: {\n      parser: tseslint.parser,\n      parserOptions: {\n        sourceType: 'module',\n        ecmaVersion: 2022,\n        isolatedDeclarations: true,\n        project: shouldTypeCheck\n          ? [\n              './packages/*/tsconfig.json',\n              './packages/vite/src/*/tsconfig.json',\n            ]\n          : undefined,\n      },\n      globals: {\n        ...globals.es2023,\n        ...globals.node,\n      },\n    },\n    settings: {\n      node: {\n        version: '^20.19.0 || >=22.12.0',\n      },\n    },\n    plugins: {\n      n: pluginN,\n      'import-x': pluginImportX,\n    },\n    rules: {\n      'n/no-exports-assign': 'error',\n      'n/no-unpublished-bin': 'error',\n      'n/no-unsupported-features/es-builtins': 'error',\n      'n/no-unsupported-features/node-builtins': [\n        'error',\n        {\n          // TODO: remove this when we don't support Node 20 anymore\n          ignores: ['Response', 'Request', 'fetch'],\n        },\n      ],\n      'n/process-exit-as-throw': 'error',\n      'n/hashbang': 'error',\n\n      eqeqeq: ['warn', 'always', { null: 'never' }],\n      'no-debugger': ['error'],\n      'no-empty': ['warn', { allowEmptyCatch: true }],\n      'no-process-exit': 'off',\n      'prefer-const': [\n        'warn',\n        {\n          destructuring: 'all',\n        },\n      ],\n\n      'n/no-missing-require': [\n        'error',\n        {\n          // for try-catching yarn pnp\n          allowModules: ['pnpapi', 'vite'],\n          tryExtensions: ['.ts', '.js', '.jsx', '.tsx', '.d.ts'],\n        },\n      ],\n      'n/no-extraneous-import': [\n        'error',\n        {\n          allowModules: [\n            'vite',\n            'esbuild',\n            'rolldown',\n            'less',\n            'sass',\n            'sass-embedded',\n            'terser',\n            'lightningcss',\n            'vitest',\n            'unbuild',\n          ],\n        },\n      ],\n      'n/no-extraneous-require': [\n        'error',\n        {\n          allowModules: ['vite'],\n        },\n      ],\n      'n/prefer-node-protocol': 'error',\n\n      '@typescript-eslint/ban-ts-comment': 'error',\n      '@typescript-eslint/no-unsafe-function-type': 'off',\n      '@typescript-eslint/explicit-module-boundary-types': [\n        'error',\n        { allowArgumentsExplicitlyTypedAsAny: true },\n      ],\n      '@typescript-eslint/no-empty-function': [\n        'error',\n        { allow: ['arrowFunctions'] },\n      ],\n      '@typescript-eslint/no-empty-object-type': [\n        'error',\n        { allowInterfaces: 'with-single-extends' },\n      ],\n      '@typescript-eslint/no-empty-interface': 'off',\n      '@typescript-eslint/no-explicit-any': 'off',\n      'no-extra-semi': 'off',\n      '@typescript-eslint/no-extra-semi': 'off', // conflicts with prettier\n      '@typescript-eslint/no-inferrable-types': 'off',\n      '@typescript-eslint/no-unused-vars': [\n        'error',\n        {\n          args: 'all',\n          argsIgnorePattern: '^_',\n          caughtErrors: 'all',\n          caughtErrorsIgnorePattern: '^_',\n          destructuredArrayIgnorePattern: '^_',\n          varsIgnorePattern: '^_',\n          ignoreRestSiblings: true,\n        },\n      ],\n      '@typescript-eslint/no-require-imports': 'off',\n      '@typescript-eslint/consistent-type-imports': [\n        'error',\n        { prefer: 'type-imports', disallowTypeAnnotations: false },\n      ],\n      // disable rules set in @typescript-eslint/stylistic which conflict with current code\n      // we should discuss if we want to enable these as they encourage consistent code\n      '@typescript-eslint/array-type': 'off',\n      '@typescript-eslint/consistent-type-definitions': 'off',\n      '@typescript-eslint/prefer-for-of': 'off',\n      '@typescript-eslint/prefer-function-type': 'off',\n\n      'import-x/no-duplicates': 'error',\n      'import-x/order': [\n        'error',\n        {\n          groups: [\n            'builtin',\n            'external',\n            'internal',\n            'parent',\n            'sibling',\n            'index',\n          ],\n        },\n      ],\n      'sort-imports': [\n        'error',\n        {\n          ignoreDeclarationSort: true,\n        },\n      ],\n\n      'regexp/prefer-regexp-exec': 'error',\n      'regexp/prefer-regexp-test': 'error',\n      // in some cases using explicit letter-casing is more performant than the `i` flag\n      'regexp/use-ignore-case': 'off',\n    },\n  },\n  {\n    name: 'vite/globals',\n    files: ['packages/**/*.?([cm])[jt]s?(x)'],\n    ignores: ['**/__tests__/**'],\n    rules: {\n      'no-restricted-globals': ['error', 'require', '__dirname', '__filename'],\n    },\n  },\n  {\n    name: 'vite/node',\n    files: ['packages/vite/src/node/**/*.?([cm])[jt]s?(x)'],\n    rules: {\n      'no-console': ['error'],\n      'n/no-restricted-require': [\n        'error',\n        Object.keys(pkgVite.devDependencies).map((d) => ({\n          name: d,\n          message:\n            `devDependencies can only be imported using ESM syntax so ` +\n            `that they are included in the rolldown bundle. If you are trying to ` +\n            `lazy load a dependency, use (await import('dependency')).default instead.`,\n        })),\n      ],\n    },\n  },\n  {\n    name: 'playground/enforce-esm',\n    files: ['playground/**/*.?([cm])[jt]s?(x)'],\n    ignores: [\n      'playground/ssr-resolve/**',\n      'playground/**/*{commonjs,cjs}*/**',\n      'playground/**/*{commonjs,cjs}*',\n      'playground/**/*dep*/**',\n      'playground/resolve/browser-module-field2/index.web.js',\n      'playground/resolve/browser-field/**',\n    ],\n    rules: {\n      'import-x/no-commonjs': 'error',\n    },\n  },\n  {\n    name: 'tests',\n    files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'],\n    rules: {\n      'n/no-unsupported-features/node-builtins': [\n        'error',\n        {\n          // ideally we would like to allow all experimental features\n          // https://github.com/eslint-community/eslint-plugin-n/issues/199\n          ignores: ['fetch', 'import.meta.dirname'],\n        },\n      ],\n    },\n  },\n  {\n    name: 'configs',\n    files: [\n      'packages/create-vite/tsdown.config.ts',\n      'packages/plugin-legacy/tsdown.config.ts',\n    ],\n    rules: {\n      'n/no-unsupported-features/node-builtins': [\n        'error',\n        {\n          // ideally we would like to allow all experimental features\n          // https://github.com/eslint-community/eslint-plugin-n/issues/199\n          ignores: ['fetch', 'import.meta.dirname'],\n        },\n      ],\n    },\n  },\n\n  {\n    name: 'disables/vite/client',\n    files: ['packages/vite/src/client/**/*.?([cm])[jt]s?(x)'],\n    ignores: ['**/__tests__/**'],\n    rules: {\n      'n/no-unsupported-features/node-builtins': 'off',\n    },\n  },\n  {\n    name: 'disables/vite/types',\n    files: [\n      'packages/vite/src/types/**/*.?([cm])[jt]s?(x)',\n      'packages/vite/scripts/**/*.?([cm])[jt]s?(x)',\n      '**/*.spec.ts',\n    ],\n    rules: {\n      'n/no-extraneous-import': 'off',\n    },\n  },\n  {\n    name: 'disables/vite/cjs',\n    files: ['packages/vite/index.cjs'],\n    rules: {\n      'no-restricted-globals': 'off',\n      'n/no-missing-require': 'off',\n    },\n  },\n  {\n    name: 'disables/create-vite/templates',\n    files: [\n      'packages/create-vite/template-*/**/*.?([cm])[jt]s?(x)',\n      '**/build.config.ts',\n    ],\n    rules: {\n      'no-undef': 'off',\n      'n/no-missing-import': 'off',\n      'n/no-extraneous-import': 'off',\n      'n/no-extraneous-require': 'off',\n      '@typescript-eslint/explicit-module-boundary-types': 'off',\n    },\n  },\n  {\n    name: 'disables/playground',\n    files: ['playground/**/*.?([cm])[jt]s?(x)', 'docs/**/*.?([cm])[jt]s?(x)'],\n    rules: {\n      'n/no-extraneous-import': 'off',\n      'n/no-extraneous-require': 'off',\n      'n/no-missing-import': 'off',\n      'n/no-missing-require': 'off',\n      'n/no-unsupported-features/es-builtins': 'off',\n      'n/no-unsupported-features/node-builtins': 'off',\n      '@typescript-eslint/explicit-module-boundary-types': 'off',\n      '@typescript-eslint/no-unused-expressions': 'off',\n      '@typescript-eslint/no-unused-vars': 'off',\n      'no-undef': 'off',\n      'no-empty': 'off',\n      'no-constant-condition': 'off',\n      '@typescript-eslint/no-empty-function': 'off',\n    },\n  },\n  {\n    name: 'disables/playground/tsconfig-json',\n    files: [\n      'playground/tsconfig-json/**/*.?([cm])[jt]s?(x)',\n      'playground/tsconfig-json-load-error/**/*.?([cm])[jt]s?(x)',\n    ],\n    ignores: ['**/__tests__/**'],\n    rules: {\n      '@typescript-eslint/ban-ts-comment': 'off',\n    },\n  },\n  {\n    name: 'disables/js',\n    files: ['**/*.js', '**/*.mjs', '**/*.cjs'],\n    rules: {\n      '@typescript-eslint/explicit-module-boundary-types': 'off',\n    },\n  },\n  {\n    name: 'disables/dts',\n    files: ['**/*.d.ts'],\n    rules: {\n      '@typescript-eslint/consistent-indexed-object-style': 'off',\n      '@typescript-eslint/triple-slash-reference': 'off',\n    },\n  },\n  {\n    name: 'disables/test',\n    files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'],\n    rules: {\n      'no-console': 'off',\n      '@typescript-eslint/ban-ts-comment': 'off',\n    },\n  },\n  {\n    name: 'disables/typechecking',\n    files: [\n      '**/*.js',\n      '**/*.mjs',\n      '**/*.cjs',\n      '**/*.d.ts',\n      '**/*.d.cts',\n      '**/__tests__/**',\n      'docs/**',\n      'playground/**',\n      'scripts/**',\n      'vitest.config.ts',\n      'vitest.config.e2e.ts',\n    ],\n    languageOptions: {\n      parserOptions: {\n        project: false,\n      },\n    },\n  },\n)\n"
  },
  {
    "path": "netlify.toml",
    "content": "[build.environment]\n  NODE_VERSION = \"24\"\n  # don't need playwright for docs build\n  PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD = \"1\"\n[build]\n  publish = \"docs/.vitepress/dist\"\n  command = \"pnpm ci-docs\"\n  ignore = \"./scripts/docs-check.sh\"\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@vitejs/vite-monorepo\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"engines\": {\n    \"node\": \"^20.19.0 || >=22.12.0\"\n  },\n  \"homepage\": \"https://vite.dev/\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitejs/vite.git\"\n  },\n  \"keywords\": [\n    \"frontend\",\n    \"hmr\",\n    \"dev-server\",\n    \"build-tool\",\n    \"vite\"\n  ],\n  \"scripts\": {\n    \"preinstall\": \"npx only-allow pnpm\",\n    \"postinstall\": \"simple-git-hooks\",\n    \"format\": \"prettier --write --cache . --experimental-cli\",\n    \"lint\": \"eslint --cache . --concurrency auto\",\n    \"typecheck\": \"tsc -p scripts && pnpm -r --parallel run typecheck\",\n    \"test\": \"pnpm test-unit && pnpm test-serve && pnpm test-build\",\n    \"test-serve\": \"vitest run -c vitest.config.e2e.ts\",\n    \"test-build\": \"VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts\",\n    \"test-unit\": \"vitest run\",\n    \"test-docs\": \"pnpm run docs-build\",\n    \"debug-serve\": \"VITE_DEBUG_SERVE=1 vitest run -c vitest.config.e2e.ts\",\n    \"debug-build\": \"VITE_TEST_BUILD=1 VITE_PRESERVE_BUILD_ARTIFACTS=1 vitest run -c vitest.config.e2e.ts\",\n    \"docs\": \"pnpm --filter=./docs run docs\",\n    \"docs-build\": \"pnpm --filter=./docs run docs-build\",\n    \"docs-serve\": \"pnpm --filter=./docs run docs-serve\",\n    \"build\": \"pnpm -r --filter='./packages/*' run build\",\n    \"dev\": \"pnpm -r --parallel --filter='./packages/*' run dev\",\n    \"release\": \"tsx scripts/release.ts\",\n    \"ci-publish\": \"tsx scripts/publishCI.ts\",\n    \"ci-docs\": \"pnpm build && pnpm docs-build\",\n    \"merge-changelog\": \"tsx scripts/mergeChangelog.ts\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.39.4\",\n    \"@type-challenges/utils\": \"^0.1.1\",\n    \"@types/babel__core\": \"^7.20.5\",\n    \"@types/babel__preset-env\": \"^7.10.0\",\n    \"@types/convert-source-map\": \"^2.0.3\",\n    \"@types/cross-spawn\": \"^6.0.6\",\n    \"@types/etag\": \"^1.8.4\",\n    \"@types/less\": \"^3.0.8\",\n    \"@types/node\": \"^24.12.0\",\n    \"@types/picomatch\": \"^4.0.2\",\n    \"@types/stylus\": \"^0.48.43\",\n    \"@types/ws\": \"^8.18.1\",\n    \"@vitejs/release-scripts\": \"^1.6.0\",\n    \"eslint\": \"^9.39.4\",\n    \"eslint-plugin-import-x\": \"^4.16.2\",\n    \"eslint-plugin-n\": \"^17.24.0\",\n    \"eslint-plugin-regexp\": \"^3.1.0\",\n    \"execa\": \"^9.6.1\",\n    \"globals\": \"^17.4.0\",\n    \"lint-staged\": \"^16.4.0\",\n    \"picocolors\": \"^1.1.1\",\n    \"playwright-chromium\": \"^1.58.2\",\n    \"prettier\": \"3.8.1\",\n    \"rolldown\": \"1.0.0-rc.10\",\n    \"rollup\": \"^4.59.0\",\n    \"simple-git-hooks\": \"^2.13.1\",\n    \"tsx\": \"^4.21.0\",\n    \"typescript\": \"~5.9.3\",\n    \"typescript-eslint\": \"^8.57.0\",\n    \"vite\": \"workspace:*\",\n    \"vitest\": \"^4.1.0\"\n  },\n  \"simple-git-hooks\": {\n    \"pre-commit\": \"pnpm exec lint-staged --concurrent false\"\n  },\n  \"lint-staged\": {\n    \"*\": [\n      \"prettier --write --cache --ignore-unknown --experimental-cli\"\n    ],\n    \"packages/*/{src,types}/**/*.ts\": [\n      \"eslint --cache --fix --concurrency auto\"\n    ],\n    \"packages/**/*.d.ts\": [\n      \"eslint --cache --fix --concurrency auto\"\n    ],\n    \"playground/**/__tests__/**/*.ts\": [\n      \"eslint --cache --fix --concurrency auto\"\n    ]\n  },\n  \"packageManager\": \"pnpm@10.32.1\",\n  \"stackblitz\": {\n    \"startCommand\": \"pnpm --filter='./packages/vite' run dev\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/CHANGELOG.md",
    "content": "## <small>[9.0.3](https://github.com/vitejs/vite/compare/create-vite@9.0.2...create-vite@9.0.3) (2026-03-19)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#21878](https://github.com/vitejs/vite/issues/21878)) ([6dbbd7f](https://github.com/vitejs/vite/commit/6dbbd7f072b1e13abd96489b0016b3d93d937999))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#21787](https://github.com/vitejs/vite/issues/21787)) ([1af1d3a](https://github.com/vitejs/vite/commit/1af1d3a3a4fd62fa581392b2dec9052efe8485b3))\n\n## <small>[9.0.2](https://github.com/vitejs/vite/compare/create-vite@9.0.1...create-vite@9.0.2) (2026-03-13)</small>\n### Bug Fixes\n\n* **create-vue:** add `lang=\"ts\"` to vue files to fix type errors in vue-ts template ([#21838](https://github.com/vitejs/vite/issues/21838)) ([1b8592d](https://github.com/vitejs/vite/commit/1b8592d2754da20e9ca4c4ba39c318b9168da893))\n\n## <small>[9.0.1](https://github.com/vitejs/vite/compare/create-vite@9.0.0...create-vite@9.0.1) (2026-03-12)</small>\n### Bug Fixes\n\n* **create-vite:** add `@babel/core` and `@types/babel__core` for react compiler template ([#21833](https://github.com/vitejs/vite/issues/21833)) ([e818474](https://github.com/vitejs/vite/commit/e818474496746d9f386f9ed00c93200b083a16ad))\n\n## [9.0.0](https://github.com/vitejs/vite/compare/create-vite@8.2.0...create-vite@9.0.0) (2026-03-12)\n### ⚠ BREAKING CHANGES\n\n* update default browser target (#21193)\n\n### Features\n\n* **create-vite:** add AI agent experience (AX) support ([#21116](https://github.com/vitejs/vite/issues/21116)) ([38d6011](https://github.com/vitejs/vite/commit/38d6011b7b6e23e113d22bfabdd034ea182d18ea))\n* **create-vite:** add ember ([#20069](https://github.com/vitejs/vite/issues/20069)) ([2f9428d](https://github.com/vitejs/vite/commit/2f9428d1ffd988e30cb253d5bb84844fb1654e86))\n* **create-vite:** make vitePreprocess not the default in svelte ([#21637](https://github.com/vitejs/vite/issues/21637)) ([2a2c8a4](https://github.com/vitejs/vite/commit/2a2c8a4b05208d786ff4630e6917d3975b304787))\n* **create-vite:** remove react-swc variants ([#21633](https://github.com/vitejs/vite/issues/21633)) ([14fcb60](https://github.com/vitejs/vite/commit/14fcb60cf376e0c7b93d84dad19851ac985f59c4))\n* **create-vite:** show description for template variants ([#21403](https://github.com/vitejs/vite/issues/21403)) ([cb85e5c](https://github.com/vitejs/vite/commit/cb85e5ce939ce04b9a37c06bba23b7cb2d0cb1e1))\n* **create-vite:** update framework starter templates to align the new theme ([#21432](https://github.com/vitejs/vite/issues/21432)) ([520d13b](https://github.com/vitejs/vite/commit/520d13bfb14c4cf4fd8d3620e1fc5e6e815c9606))\n* **create-vite:** update react template for new plugin-react ([#21742](https://github.com/vitejs/vite/issues/21742)) ([0b4242e](https://github.com/vitejs/vite/commit/0b4242e2edfe094de5f8ebfcc2bbb676a0222715))\n* **create-vite:** update vanilla starter templates to align the new theme ([#21425](https://github.com/vitejs/vite/issues/21425)) ([7453556](https://github.com/vitejs/vite/commit/7453556f5cbacad2ea4d216f4d0c92826b49f466))\n* **deps:** bump plugin versions in create-vite templates ([#21832](https://github.com/vitejs/vite/issues/21832)) ([ebb041e](https://github.com/vitejs/vite/commit/ebb041eaadefb7fdbd42428d40537e07f640720d))\n* update default browser target ([#21193](https://github.com/vitejs/vite/issues/21193)) ([8c3dd06](https://github.com/vitejs/vite/commit/8c3dd06bd9903bf0e6bc51f3554eea8cb6b26903))\n\n### Bug Fixes\n\n* **create-vite:** do not create empty directory for custom commands ([#21367](https://github.com/vitejs/vite/issues/21367)) ([df767ed](https://github.com/vitejs/vite/commit/df767edeaecc73d0e78cdadb42d7fb1646955951))\n* **create-vite:** handle double dash for `npm exec` ([#21830](https://github.com/vitejs/vite/issues/21830)) ([e4bcd59](https://github.com/vitejs/vite/commit/e4bcd59b2549801e55bbf41a92bd295288e27d0d))\n* **create-vite:** skip irrelevant \"immediate\" prompt for external commands ([#21410](https://github.com/vitejs/vite/issues/21410)) ([33e74e5](https://github.com/vitejs/vite/commit/33e74e5ad29342668ebc20c48e5ac2214d3ac8d2))\n* **create-vite:** strip invalid characters in project name ([#21553](https://github.com/vitejs/vite/issues/21553)) ([4bba787](https://github.com/vitejs/vite/commit/4bba787083393bdc79f5f49da9c0e86a497eee64))\n* **create-vite:** tanstack cli `--template` is deprecated ([#21831](https://github.com/vitejs/vite/issues/21831)) ([1527f35](https://github.com/vitejs/vite/commit/1527f358182de0dfde1eea905edb0f87a9b808b9))\n* **create-vite:** update deprecated tsrouter-app to `@tanstack/cli` ([#21527](https://github.com/vitejs/vite/issues/21527)) ([ddecf2b](https://github.com/vitejs/vite/commit/ddecf2bf5cf7bdcabad63e300cf9f80c5f6e0ca4))\n* **create-vite:** update QwikCity custom command to \"empty\" template ([#21279](https://github.com/vitejs/vite/issues/21279)) ([9890dd6](https://github.com/vitejs/vite/commit/9890dd6cddc5a3940c7fde2ec7966923f43e3957))\n* **deps:** update `@clack/prompts` to 1.0.0-alpha.9 ([#21421](https://github.com/vitejs/vite/issues/21421)) ([6864c27](https://github.com/vitejs/vite/commit/6864c2727a19270339b9693b8abdd4c26c92d1c3))\n* **deps:** update all non-major dependencies ([#21146](https://github.com/vitejs/vite/issues/21146)) ([a3cd262](https://github.com/vitejs/vite/commit/a3cd262f37228967e455617e982b35fccc49ffe9))\n* **deps:** update all non-major dependencies ([#21175](https://github.com/vitejs/vite/issues/21175)) ([72e398a](https://github.com/vitejs/vite/commit/72e398a46d8d2f54fbcbeb9ff0dceab346aeb642))\n* **deps:** update all non-major dependencies ([#21231](https://github.com/vitejs/vite/issues/21231)) ([859789c](https://github.com/vitejs/vite/commit/859789c856412dfa67969232ddda1df754febf40))\n* **deps:** update all non-major dependencies ([#21285](https://github.com/vitejs/vite/issues/21285)) ([4635b2e](https://github.com/vitejs/vite/commit/4635b2e90f833d1048d76381e20208c0e0841e97))\n* **deps:** update all non-major dependencies ([#21321](https://github.com/vitejs/vite/issues/21321)) ([9bc7c2e](https://github.com/vitejs/vite/commit/9bc7c2ed4f387fb982b84d1988a26af8990096f7))\n* **deps:** update all non-major dependencies ([#21389](https://github.com/vitejs/vite/issues/21389)) ([30f48df](https://github.com/vitejs/vite/commit/30f48df33ec9e9bd0b8164461eede5574398370b))\n* **deps:** update all non-major dependencies ([#21440](https://github.com/vitejs/vite/issues/21440)) ([1835995](https://github.com/vitejs/vite/commit/18359959cb2960a2fb2b9a340e5ae27d122a1501))\n* **deps:** update all non-major dependencies ([#21488](https://github.com/vitejs/vite/issues/21488)) ([2b32ca2](https://github.com/vitejs/vite/commit/2b32ca24fe9d742901c2cb5c88e6b1fd734f8c73))\n* **deps:** update all non-major dependencies ([#21540](https://github.com/vitejs/vite/issues/21540)) ([9ebaeaa](https://github.com/vitejs/vite/commit/9ebaeaac094db996b1d12665052633c20ac8a9cf))\n* **deps:** update all non-major dependencies ([#21594](https://github.com/vitejs/vite/issues/21594)) ([becdc5d](https://github.com/vitejs/vite/commit/becdc5dcc49efa3769c92e9929fb2280fd776206))\n* **deps:** update all non-major dependencies ([#21691](https://github.com/vitejs/vite/issues/21691)) ([521fdc0](https://github.com/vitejs/vite/commit/521fdc0ced51ddee7f728e6f891f36ebc6c0e1ce))\n* **deps:** update all non-major dependencies ([#21732](https://github.com/vitejs/vite/issues/21732)) ([5c921ca](https://github.com/vitejs/vite/commit/5c921ca9bfe64327df82b04ae34ccfe0a7cfa297))\n* **deps:** update all non-major dependencies ([#21786](https://github.com/vitejs/vite/issues/21786)) ([eaa4352](https://github.com/vitejs/vite/commit/eaa4352af8f8658e3a10a9945ad9c227fcb2f28a))\n\n### Documentation\n\n* correct \"it's\" to \"its\" for possessive usage ([#21645](https://github.com/vitejs/vite/issues/21645)) ([2b90b39](https://github.com/vitejs/vite/commit/2b90b39c4592f386639410175263d35d0651ff33))\n* **degit:** switch to recommending tiged ([#21148](https://github.com/vitejs/vite/issues/21148)) ([977d9ee](https://github.com/vitejs/vite/commit/977d9ee28df7b2a95db5ec3b1fde27033c485199))\n\n### Miscellaneous Chores\n\n* changes to merge back to vite repo ([35b3cae](https://github.com/vitejs/vite/commit/35b3cae772419409872e1afd8d51a303e3504d2d))\n* **create-vite:** update logo ([#21405](https://github.com/vitejs/vite/issues/21405)) ([80840d3](https://github.com/vitejs/vite/commit/80840d37d88f3f4344d6317a087dde3469273917))\n* **deps:** update dependency globals to v17 ([#21441](https://github.com/vitejs/vite/issues/21441)) ([526a687](https://github.com/vitejs/vite/commit/526a687e4150e4ffa9301c8329c397afe379f2dc))\n* **deps:** update dependency tsdown to ^0.16.6 ([#21145](https://github.com/vitejs/vite/issues/21145)) ([d9ac204](https://github.com/vitejs/vite/commit/d9ac20406cca3b32fc37c32a1c081881bf1ee897))\n* **deps:** update dependency tsdown to ^0.17.4 ([#21284](https://github.com/vitejs/vite/issues/21284)) ([43f061a](https://github.com/vitejs/vite/commit/43f061adc677d40ce226de4dd07ee9a1f5e4ca73))\n* **deps:** update dependency tsdown to ^0.18.4 ([#21344](https://github.com/vitejs/vite/issues/21344)) ([964c718](https://github.com/vitejs/vite/commit/964c718a382ff46ec1f906d7d6bc3f135a6dcd3f))\n* **deps:** update dependency tsdown to ^0.20.3 ([#21593](https://github.com/vitejs/vite/issues/21593)) ([e3f6ac9](https://github.com/vitejs/vite/commit/e3f6ac9326bf7c31a916e7c5dd90277de4c262c0))\n* **deps:** update rolldown-related dependencies ([#21174](https://github.com/vitejs/vite/issues/21174)) ([74559c9](https://github.com/vitejs/vite/commit/74559c947483a8ee24da052ac2d9568f7cb3546a))\n* **deps:** update rolldown-related dependencies ([#21230](https://github.com/vitejs/vite/issues/21230)) ([9349446](https://github.com/vitejs/vite/commit/9349446e9344bd81ccfb37af482f479cd1b59bbc))\n* **deps:** update rolldown-related dependencies ([#21390](https://github.com/vitejs/vite/issues/21390)) ([be9dd4e](https://github.com/vitejs/vite/commit/be9dd4e08d899f9ed27f2bdcb81bf27d018377a6))\n* **deps:** update rolldown-related dependencies ([#21487](https://github.com/vitejs/vite/issues/21487)) ([5863e51](https://github.com/vitejs/vite/commit/5863e513fab6b481cfb42da86202f9db728c077d))\n* update create-vite versions ([6556550](https://github.com/vitejs/vite/commit/6556550a81d4b87023057aaf106b2560c1b84adb))\n\n### Code Refactoring\n\n* **create-vite:** remove `rolldown` boolean flag ([#21596](https://github.com/vitejs/vite/issues/21596)) ([e8c9334](https://github.com/vitejs/vite/commit/e8c9334c4843324f760ec3a862f2778d0be9ea4a))\n* **create-vite:** remove extra brackets in React Compiler babel plugins ([#21674](https://github.com/vitejs/vite/issues/21674)) ([fe949f7](https://github.com/vitejs/vite/commit/fe949f78c0ef057bf59dc46d97ac0ed11d251ed7))\n* use `import.meta.dirname` everywhere ([#21509](https://github.com/vitejs/vite/issues/21509)) ([7becf5f](https://github.com/vitejs/vite/commit/7becf5f8fe9041cff60f495ef975faaba68f9eb2))\n\n## [8.2.0](https://github.com/vitejs/vite/compare/create-vite@8.1.0...create-vite@8.2.0) (2025-11-20)\n### Features\n\n* **create-vite:** add Vike ([#21132](https://github.com/vitejs/vite/issues/21132)) ([0a86262](https://github.com/vitejs/vite/commit/0a86262cb253a6a38bb02d72a39805fe552b944b))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#21128](https://github.com/vitejs/vite/issues/21128)) ([4f8171e](https://github.com/vitejs/vite/commit/4f8171eb3046bd70c83964689897dab4c6b58bc0))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#21127](https://github.com/vitejs/vite/issues/21127)) ([5029720](https://github.com/vitejs/vite/commit/50297208452241061cb44d09a4bbdf77a11ac01e))\n\n## [8.1.0](https://github.com/vitejs/vite/compare/create-vite@8.0.3...create-vite@8.1.0) (2025-11-12)\n### Features\n\n* **create-vite:** update React Compiler dep to 1.0.0 ([#20911](https://github.com/vitejs/vite/issues/20911)) ([6cf3304](https://github.com/vitejs/vite/commit/6cf3304c83586cf547d0b706d2e58ae647b93218))\n* **create-vite:** updated eslint-plugin-react-hooks to v7 and updated the config ([#20914](https://github.com/vitejs/vite/issues/20914)) ([0ec8aeb](https://github.com/vitejs/vite/commit/0ec8aeba479bb42d37521cf8d256286abc06c129))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#21095](https://github.com/vitejs/vite/issues/21095)) ([39a0a15](https://github.com/vitejs/vite/commit/39a0a15fd24ed37257c48b795097a3794e54d255))\n\n## <small>[8.0.3](https://github.com/vitejs/vite/compare/create-vite@8.0.2...create-vite@8.0.3) (2025-11-10)</small>\n### Bug Fixes\n\n* **create-vite:** use `create-rwsdk` for redwood template ([#21091](https://github.com/vitejs/vite/issues/21091)) ([9aefcb6](https://github.com/vitejs/vite/commit/9aefcb6b9138942068eee074afb4c9dec71c4735))\n* **deps:** update all non-major dependencies ([879de86](https://github.com/vitejs/vite/commit/879de86935a31b4e47ab907ddd859366518ce268))\n* **deps:** update all non-major dependencies ([#20894](https://github.com/vitejs/vite/issues/20894)) ([3213f90](https://github.com/vitejs/vite/commit/3213f90ff0d8f274bcec65f40aac6dfcff1ac244))\n* **deps:** update all non-major dependencies ([#21008](https://github.com/vitejs/vite/issues/21008)) ([185641e](https://github.com/vitejs/vite/commit/185641e3cdae29277c41eb8028f6eac542215f01))\n* **deps:** update all non-major dependencies ([#21096](https://github.com/vitejs/vite/issues/21096)) ([6a34ac3](https://github.com/vitejs/vite/commit/6a34ac3422686e7cf7cc9a25d299cb8e5a8d92a0))\n* revert \"refactor: use fs.cpSync ([#21019](https://github.com/vitejs/vite/issues/21019))\" ([#21081](https://github.com/vitejs/vite/issues/21081)) ([728c8ee](https://github.com/vitejs/vite/commit/728c8eeebc0ad7ba48e680f46bbdb55020b2e152))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#20966](https://github.com/vitejs/vite/issues/20966)) ([6fb41a2](https://github.com/vitejs/vite/commit/6fb41a260bda443685e719ea4765d3faca3db944))\n* **deps:** update dependency tsdown to ^0.15.6 ([#20893](https://github.com/vitejs/vite/issues/20893)) ([3dfe8a1](https://github.com/vitejs/vite/commit/3dfe8a1572ae8ad247814c3d041f0421906eaaf7))\n* **deps:** update rolldown-related dependencies ([#20923](https://github.com/vitejs/vite/issues/20923)) ([a5e3b06](https://github.com/vitejs/vite/commit/a5e3b064fa7ca981cb6f15f8e88806b36a99b8bf))\n* **deps:** update rolldown-related dependencies ([#20965](https://github.com/vitejs/vite/issues/20965)) ([6ad5424](https://github.com/vitejs/vite/commit/6ad5424f0bcabd8943c34d341cf9ed2e64b3d53c))\n* **deps:** update rolldown-related dependencies ([#21009](https://github.com/vitejs/vite/issues/21009)) ([7cec1ad](https://github.com/vitejs/vite/commit/7cec1addc257eb5bd0856adbe1e4306f0bb83e22))\n* **deps:** update rolldown-related dependencies ([#21047](https://github.com/vitejs/vite/issues/21047)) ([e3a6a83](https://github.com/vitejs/vite/commit/e3a6a83406943bc59a9916cae3f25ab33c2b5802))\n\n### Code Refactoring\n\n* use `fs.cpSync` ([#21019](https://github.com/vitejs/vite/issues/21019)) ([a2df778](https://github.com/vitejs/vite/commit/a2df77812814b927880bc4d68aafa8c8fa47daf0))\n\n### Build System\n\n* normalize license repo url ([#21010](https://github.com/vitejs/vite/issues/21010)) ([bb65468](https://github.com/vitejs/vite/commit/bb65468f3c6213fdd870c085610ec575af66b03c))\n\n## <small>[8.0.2](https://github.com/vitejs/vite/compare/create-vite@8.0.1...create-vite@8.0.2) (2025-10-02)</small>\n### Features\n\n* **create-vite:** add @types/node to typescript templates ([#18642](https://github.com/vitejs/vite/issues/18642)) ([302f809](https://github.com/vitejs/vite/commit/302f8091b2a5e342f90d98c97331d2177bb48336))\n* **create-vite:** bump TS to 5.9 ([#20870](https://github.com/vitejs/vite/issues/20870)) ([4e35c9d](https://github.com/vitejs/vite/commit/4e35c9dfcf948e333f22add061b84b9e9603cafd))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20855](https://github.com/vitejs/vite/issues/20855)) ([788a183](https://github.com/vitejs/vite/commit/788a183afce57de13f5656f0cf42cdf6fdc3ebaa))\n\n### Documentation\n\n* **create-vite:** mention oxc in React templates ([#20871](https://github.com/vitejs/vite/issues/20871)) ([c1caacd](https://github.com/vitejs/vite/commit/c1caacdfae2917e91d26d3cb4d3a80d9fa11634f))\n* **create-vite:** provide deno example ([#20747](https://github.com/vitejs/vite/issues/20747)) ([fdb758a](https://github.com/vitejs/vite/commit/fdb758a51796b1ab605437b2eee778a84e87e169))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20854](https://github.com/vitejs/vite/issues/20854)) ([4dd06fd](https://github.com/vitejs/vite/commit/4dd06fdc8d643059c2abf88188eae7c4877aab6e))\n\n## <small>[8.0.1](https://github.com/vitejs/vite/compare/create-vite@8.0.0...create-vite@8.0.1) (2025-09-23)</small>\n### Bug Fixes\n\n* **create-vite:** fix installing dependencies ([#20826](https://github.com/vitejs/vite/issues/20826)) ([01ae663](https://github.com/vitejs/vite/commit/01ae66387cf1f44e029c427251af7d09b9eb2567))\n\n## [8.0.0](https://github.com/vitejs/vite/compare/create-vite@8.0.0-beta.0...create-vite@8.0.0) (2025-09-23)\n### Features\n\n* **create-vite:** ask rolldown-vite before asking auto install ([#20820](https://github.com/vitejs/vite/issues/20820)) ([123f239](https://github.com/vitejs/vite/commit/123f2396c8e84308928daf0d61488fa886fc7d50))\n\n### Bug Fixes\n\n* **create-vite:** use shorter command name for `run dev` for each package manager ([#20821](https://github.com/vitejs/vite/issues/20821)) ([0c1bc8a](https://github.com/vitejs/vite/commit/0c1bc8af3422a4c4a3f39ba4a759d9f169e04833))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20810](https://github.com/vitejs/vite/issues/20810)) ([ea68a88](https://github.com/vitejs/vite/commit/ea68a8868c7ee249213057f8a81c3f92a9839dde))\n\n## [8.0.0-beta.0](https://github.com/vitejs/vite/compare/create-vite@7.1.3...create-vite@8.0.0-beta.0) (2025-09-23)\n### Features\n\n* **create-vite:** add `--interactive` / `--no-interactive` ([#20797](https://github.com/vitejs/vite/issues/20797)) ([03a56c5](https://github.com/vitejs/vite/commit/03a56c50a1a6eac76c99b0ce00c17518ed3ccae6))\n* **create-vite:** scaffold with rolldown-vite ([#20739](https://github.com/vitejs/vite/issues/20739)) ([b3227d5](https://github.com/vitejs/vite/commit/b3227d5398a14c1a7aa9a1a997879bca4d80e719))\n* **create-vite:** set default title in index.html to project name ([#20519](https://github.com/vitejs/vite/issues/20519)) ([b178f90](https://github.com/vitejs/vite/commit/b178f90ad0b337fc2a2e5c5091e889a9912ce948))\n* **create-vite:** set types compiler option in tsconfigs ([#20132](https://github.com/vitejs/vite/issues/20132)) ([52469c3](https://github.com/vitejs/vite/commit/52469c3dfe6f46a928a24805ef498993de5d491c))\n* **create-vite:** support auto install dependencies and start dev ([#20468](https://github.com/vitejs/vite/issues/20468)) ([925cefe](https://github.com/vitejs/vite/commit/925cefe8ee5c88c9b5b6fa525f46addc4a8aef83))\n* **create-vite:** support React Compiler ([#20704](https://github.com/vitejs/vite/issues/20704)) ([052aa88](https://github.com/vitejs/vite/commit/052aa88d5618e48a47fe8e868157e768ce38af2e))\n\n## <small>[7.1.3](https://github.com/vitejs/vite/compare/create-vite@7.1.2...create-vite@7.1.3) (2025-09-22)</small>\n### Bug Fixes\n\n* **create-vite:** support deno create command ([#20806](https://github.com/vitejs/vite/issues/20806)) ([a50a162](https://github.com/vitejs/vite/commit/a50a16274ab6a23cb14b2b65b8df4a36dc5f84d2))\n* **deps:** update all non-major dependencies ([#20811](https://github.com/vitejs/vite/issues/20811)) ([9f2247c](https://github.com/vitejs/vite/commit/9f2247c066cac75746356c9391845235445a154b))\n\n## <small>[7.1.2](https://github.com/vitejs/vite/compare/create-vite@7.1.1...create-vite@7.1.2) (2025-09-18)</small>\n### Bug Fixes\n\n* **create-vite:** unique name for tanstack router options ([#20783](https://github.com/vitejs/vite/issues/20783)) ([91e68a3](https://github.com/vitejs/vite/commit/91e68a3015bdf30667ba9365f8fc51d3571f10d0))\n* **deps:** update all non-major dependencies ([#20634](https://github.com/vitejs/vite/issues/20634)) ([4851cab](https://github.com/vitejs/vite/commit/4851cab3ba818b5f0f82eef3796b61d4b12768f1))\n* **deps:** update all non-major dependencies ([#20676](https://github.com/vitejs/vite/issues/20676)) ([5a274b2](https://github.com/vitejs/vite/commit/5a274b29df83744cf0ce4dafd94029d2a9e01135))\n* **deps:** update all non-major dependencies ([#20709](https://github.com/vitejs/vite/issues/20709)) ([0401feb](https://github.com/vitejs/vite/commit/0401feba17e60bd7e976c5643128a0da49670a83))\n* **deps:** update all non-major dependencies ([#20732](https://github.com/vitejs/vite/issues/20732)) ([122bfba](https://github.com/vitejs/vite/commit/122bfbabeb1f095ce7cabd30893e5531e9a007c4))\n* **deps:** update all non-major dependencies ([#20773](https://github.com/vitejs/vite/issues/20773)) ([88af2ae](https://github.com/vitejs/vite/commit/88af2ae7df77160e7d11a9fa147a4967c8499f13))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20633](https://github.com/vitejs/vite/issues/20633)) ([98b92e8](https://github.com/vitejs/vite/commit/98b92e8c4b10ae87c48292a8ac09b01ca81a02cf))\n* **deps:** update rolldown-related dependencies ([#20675](https://github.com/vitejs/vite/issues/20675)) ([a67bb5f](https://github.com/vitejs/vite/commit/a67bb5fbec5f3e42151dc7e3166858d0d33533de))\n* **deps:** update rolldown-related dependencies ([#20772](https://github.com/vitejs/vite/issues/20772)) ([d785e72](https://github.com/vitejs/vite/commit/d785e72f2ead705e8b2416c0a5097878fced3435))\n\n### Code Refactoring\n\n* **create-vite:** migrate `tseslint.config` to ESLint core's `defineConfig` ([#20734](https://github.com/vitejs/vite/issues/20734)) ([feeb8bc](https://github.com/vitejs/vite/commit/feeb8bccfb6981c21f3f8a09b26e36373a51dae0))\n\n## <small>[7.1.1](https://github.com/vitejs/vite/compare/create-vite@7.1.0...create-vite@7.1.1) (2025-08-12)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20587](https://github.com/vitejs/vite/issues/20587)) ([20d4817](https://github.com/vitejs/vite/commit/20d48172a0352d32f766b3c878d52a8944fdbf6e))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency @vitejs/plugin-react to v5 ([#20588](https://github.com/vitejs/vite/issues/20588)) ([a627a0b](https://github.com/vitejs/vite/commit/a627a0ba91fc5a9174ca7356dcab0e86b9703e0f))\n* **deps:** update dependency @vitejs/plugin-react-swc to v4 ([#20589](https://github.com/vitejs/vite/issues/20589)) ([1c372dd](https://github.com/vitejs/vite/commit/1c372dde7ff4d228f0eb620733ef1c5b66ef49f0))\n* **deps:** update rolldown-related dependencies ([#20586](https://github.com/vitejs/vite/issues/20586)) ([77632c5](https://github.com/vitejs/vite/commit/77632c55db51cd6d03bcf24a1cef8d21058100a3))\n\n### Code Refactoring\n\n* **create-vite:** add jsdoc for svelte.config.js in svelte-ts template ([#20543](https://github.com/vitejs/vite/issues/20543)) ([aa93814](https://github.com/vitejs/vite/commit/aa938149337f5232011f203bfe55c741fbaddd6c))\n\n## [7.1.0](https://github.com/vitejs/vite/compare/create-vite@7.0.3...create-vite@7.1.0) (2025-08-07)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20406](https://github.com/vitejs/vite/issues/20406)) ([1a1cc8a](https://github.com/vitejs/vite/commit/1a1cc8a435a21996255b3e5cc75ed4680de2a7f3))\n* **deps:** update all non-major dependencies ([#20442](https://github.com/vitejs/vite/issues/20442)) ([e49f505](https://github.com/vitejs/vite/commit/e49f50599d852eec644e79b074b4648e2dff1e5d))\n* **deps:** update all non-major dependencies ([#20489](https://github.com/vitejs/vite/issues/20489)) ([f6aa04a](https://github.com/vitejs/vite/commit/f6aa04a52d486c8881f666c450caa3dab3c6bba1))\n* **deps:** update all non-major dependencies ([#20537](https://github.com/vitejs/vite/issues/20537)) ([fc9a9d3](https://github.com/vitejs/vite/commit/fc9a9d3f1493caa3d614f64e0a61fd5684f0928b))\n\n### Documentation\n\n* tiny typo ([#20404](https://github.com/vitejs/vite/issues/20404)) ([3123eb7](https://github.com/vitejs/vite/commit/3123eb7071b7f89c7d0043030edc8eb5b3731680))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency vue-tsc to v3 ([#20491](https://github.com/vitejs/vite/issues/20491)) ([51f512f](https://github.com/vitejs/vite/commit/51f512f12aae4b2905863d25b803c1f5d634ba03))\n* **deps:** update rolldown-related dependencies ([#20441](https://github.com/vitejs/vite/issues/20441)) ([f689d61](https://github.com/vitejs/vite/commit/f689d613429ae9452c74f8bc482d8cc2584ea6b8))\n* **deps:** update rolldown-related dependencies ([#20536](https://github.com/vitejs/vite/issues/20536)) ([8be2787](https://github.com/vitejs/vite/commit/8be278748a92b128c49a24619d8d537dd2b08ceb))\n\n## <small>[7.0.3](https://github.com/vitejs/vite/compare/create-vite@7.0.2...create-vite@7.0.3) (2025-07-11)</small>\n### Features\n\n* **create-vite:** bump vite-plugin-svelte to new major for vite7 ([#20394](https://github.com/vitejs/vite/issues/20394)) ([a829a29](https://github.com/vitejs/vite/commit/a829a2963cd201ef0422afdc4cfca3d3e7c92770))\n\n## <small>[7.0.2](https://github.com/vitejs/vite/compare/create-vite@7.0.1...create-vite@7.0.2) (2025-07-10)</small>\n### Bug Fixes\n\n* **create-vite:** fix command for react rsc template ([#20378](https://github.com/vitejs/vite/issues/20378)) ([0362484](https://github.com/vitejs/vite/commit/03624844ebc2950cfb1a48379726d60e6d31bd6e))\n\n## <small>[7.0.1](https://github.com/vitejs/vite/compare/create-vite@7.0.0...create-vite@7.0.1) (2025-07-08)</small>\n### Features\n\n* **create-vite:** update rsc template to use `@vitejs/plugin-rsc` ([#20351](https://github.com/vitejs/vite/issues/20351)) ([b9ebc96](https://github.com/vitejs/vite/commit/b9ebc967bb9e8137dedb7d1304e4f693a52f1c03))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20324](https://github.com/vitejs/vite/issues/20324)) ([3e81af3](https://github.com/vitejs/vite/commit/3e81af38a80c7617aba6bf3300d8b4267570f9cf))\n* **deps:** update all non-major dependencies ([#20366](https://github.com/vitejs/vite/issues/20366)) ([43ac73d](https://github.com/vitejs/vite/commit/43ac73da27b3907c701e95e6a7d28fde659729ec))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20323](https://github.com/vitejs/vite/issues/20323)) ([30d2f1b](https://github.com/vitejs/vite/commit/30d2f1b38c72387ffdca3ee4746730959a020b59))\n* group commits by category in changelog ([#20310](https://github.com/vitejs/vite/issues/20310)) ([41e83f6](https://github.com/vitejs/vite/commit/41e83f62b1adb65f5af4c1ec006de1c845437edc))\n\n## [7.0.0](https://github.com/vitejs/vite/compare/create-vite@6.5.0...create-vite@7.0.0) (2025-06-24)\n### ⚠ BREAKING CHANGES\n\n* bump `build.target` and name it `baseline-widely-available` (#20007)\n* bump required node version to 20.19+, 22.12+ and remove cjs build (#20032)\n* remove node 18 support (#19972)\n\n### Features\n\n* bump `build.target` and name it `baseline-widely-available` ([#20007](https://github.com/vitejs/vite/issues/20007)) ([4a8aa82](https://github.com/vitejs/vite/commit/4a8aa82556eb2b9e54673a6aac77873e0eb27fa9))\n* **create-vite:** add `@hiogawa/vite-rsc` ([#20209](https://github.com/vitejs/vite/issues/20209)) ([7cf0aff](https://github.com/vitejs/vite/commit/7cf0aff0370ca106b0ec88a3741f505f3351a3f4))\n* **create-vite:** update \"react\" and \"react-ts\" templates to use extends in eslint config ([#19732](https://github.com/vitejs/vite/issues/19732)) ([8679a43](https://github.com/vitejs/vite/commit/8679a43de710052c5c84bb6c253829ab999b040a))\n* **create-vite:** update target to es2023 in `tsconfig.node.json` ([#20078](https://github.com/vitejs/vite/issues/20078)) ([8424af3](https://github.com/vitejs/vite/commit/8424af398159e58cf662f7175fca2bed90dbd671))\n* **create-vite:** use more extends in eslint config ([#20008](https://github.com/vitejs/vite/issues/20008)) ([976103e](https://github.com/vitejs/vite/commit/976103ea7ccd831ee4ae334e5ee1e0f5edb5d5b1))\n* **create-vite:** validate project name ([#20257](https://github.com/vitejs/vite/issues/20257)) ([17700b7](https://github.com/vitejs/vite/commit/17700b76a6535b90e27ebfa67e2f2f78bd4ea844))\n* **deps:** update plugin-vue to 6.0.0 in create-vite templates for Vite 7 ([#20281](https://github.com/vitejs/vite/issues/20281)) ([ec06767](https://github.com/vitejs/vite/commit/ec067671d019023109f974310a9cd974a4091251))\n\n### Bug Fixes\n\n* **create-vite:** targetDir is empty fallback defaultTargetDir ([#20199](https://github.com/vitejs/vite/issues/20199)) ([1aae595](https://github.com/vitejs/vite/commit/1aae59594dfc2138144874322e0f26f8fd2188bd))\n* **deps:** update all non-major dependencies ([#19953](https://github.com/vitejs/vite/issues/19953)) ([ac8e1fb](https://github.com/vitejs/vite/commit/ac8e1fb289a06fc0671dab1f4ef68e508e34360e))\n* **deps:** update all non-major dependencies ([#20061](https://github.com/vitejs/vite/issues/20061)) ([7b58856](https://github.com/vitejs/vite/commit/7b588563636a6f735a6e25832f33fc08572b25d9))\n* **deps:** update all non-major dependencies ([#20141](https://github.com/vitejs/vite/issues/20141)) ([89ca65b](https://github.com/vitejs/vite/commit/89ca65ba1d849046dccdea52e9eca980f331be26))\n* **deps:** update all non-major dependencies ([#20181](https://github.com/vitejs/vite/issues/20181)) ([d91d4f7](https://github.com/vitejs/vite/commit/d91d4f7ad55edbcb4a51fc23376cbff89f776d30))\n* **deps:** update all non-major dependencies ([#20212](https://github.com/vitejs/vite/issues/20212)) ([a80339b](https://github.com/vitejs/vite/commit/a80339b1798607dd7389f42964272181cf9eb453))\n* **deps:** update all non-major dependencies ([#20271](https://github.com/vitejs/vite/issues/20271)) ([6b64d63](https://github.com/vitejs/vite/commit/6b64d63d700154de2c00270300b671cef8863708))\n* error starting project with TanStack Router template ([#20184](https://github.com/vitejs/vite/issues/20184)) ([44bd3eb](https://github.com/vitejs/vite/commit/44bd3ebe51a861739ec1656d188246654149eab5))\n* error starting solid project with Tanstack Router template ([#20189](https://github.com/vitejs/vite/issues/20189)) ([dad3962](https://github.com/vitejs/vite/commit/dad3962257fdf916caafefc45743898a56cbac0b))\n\n### Documentation\n\n* tiny typo ([#20110](https://github.com/vitejs/vite/issues/20110)) ([d20fc2c](https://github.com/vitejs/vite/commit/d20fc2cdc9700513425b18b625e01224f61e4eab))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20140](https://github.com/vitejs/vite/issues/20140)) ([0387447](https://github.com/vitejs/vite/commit/03874471e3de14e7d2f474ecb354499e7f5eb418))\n* **deps:** update rolldown-related dependencies ([#20182](https://github.com/vitejs/vite/issues/20182)) ([6172f41](https://github.com/vitejs/vite/commit/6172f410b44cbae8d052997bb1819a6197a4d397))\n* **deps:** update rolldown-related dependencies ([#20270](https://github.com/vitejs/vite/issues/20270)) ([f7377c3](https://github.com/vitejs/vite/commit/f7377c3eae6323bd3237ff5de5ae55c879fe7325))\n* remove node 18 support ([#19972](https://github.com/vitejs/vite/issues/19972)) ([00b8a98](https://github.com/vitejs/vite/commit/00b8a98f36376804437e1342265453915ae613de))\n* speed up typechecking ([#20131](https://github.com/vitejs/vite/issues/20131)) ([a357c19](https://github.com/vitejs/vite/commit/a357c1987f332519d7bacafebc5620c7ab534d8f))\n* update deps in create-vite for 7.0-beta ([#20148](https://github.com/vitejs/vite/issues/20148)) ([c05c159](https://github.com/vitejs/vite/commit/c05c159b84c5e358c1a03991e50179952235910c))\n* use tsdown ([#20065](https://github.com/vitejs/vite/issues/20065)) ([d488efd](https://github.com/vitejs/vite/commit/d488efda95ff40f63684194d51858f84c3d05379))\n\n### Code Refactoring\n\n* bump required node version to 20.19+, 22.12+ and remove cjs build ([#20032](https://github.com/vitejs/vite/issues/20032)) ([2b80243](https://github.com/vitejs/vite/commit/2b80243fada75378e80475028fdcc78f4432bd6f))\n\n## [6.5.0](https://github.com/vitejs/vite/compare/create-vite@6.4.1...create-vite@6.5.0) (2025-05-05)\n### Features\n\n* **create-vite:** add Marko ([#19257](https://github.com/vitejs/vite/issues/19257)) ([171e856](https://github.com/vitejs/vite/commit/171e856e011512098591234d0557804c6175b625))\n* **create-vite:** add RedwoodSDK to create-vite app. ([#19927](https://github.com/vitejs/vite/issues/19927)) ([7f5e0e6](https://github.com/vitejs/vite/commit/7f5e0e61a809412b279338772e205ea458011aa4))\n* **create-vite:** bump TS to 5.8 ([#19892](https://github.com/vitejs/vite/issues/19892)) ([1f90255](https://github.com/vitejs/vite/commit/1f902551207dd4e995eea4263fda28aed59150a6))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19698](https://github.com/vitejs/vite/issues/19698)) ([bab4cb9](https://github.com/vitejs/vite/commit/bab4cb92248adf6b9b18df12b2bf03889b0bd1eb))\n* **deps:** update all non-major dependencies ([#19899](https://github.com/vitejs/vite/issues/19899)) ([a4b500e](https://github.com/vitejs/vite/commit/a4b500ef9ccc9b19a2882156a9ba8397e69bc6b2))\n\n## <small>[6.4.1](https://github.com/vitejs/vite/compare/create-vite@6.4.0...create-vite@6.4.1) (2025-04-17)</small>\n### Bug Fixes\n\n* **create-vite:** adding an interactive flag to force interactivity ([#19875](https://github.com/vitejs/vite/issues/19875)) ([608457c](https://github.com/vitejs/vite/commit/608457cd03ce593492abfe007e20468387c4c895))\n\n### Documentation\n\n* **create-vite:** update react template README files ([#19876](https://github.com/vitejs/vite/issues/19876)) ([2d4c20e](https://github.com/vitejs/vite/commit/2d4c20ebadc35dae7327ffe6cba85cc5c36d579a))\n\n## [6.4.0](https://github.com/vitejs/vite/compare/create-vite@6.3.1...create-vite@6.4.0) (2025-04-16)\n### Features\n\n* **create-vite:** add TanStack Router commands ([#19573](https://github.com/vitejs/vite/issues/19573)) ([e49a3b5](https://github.com/vitejs/vite/commit/e49a3b523c8894e8e0df766642999a944e0148ef))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19555](https://github.com/vitejs/vite/issues/19555)) ([f612e0f](https://github.com/vitejs/vite/commit/f612e0fdf6810317b61fcca1ded125755f261d78))\n* **deps:** update all non-major dependencies ([#19613](https://github.com/vitejs/vite/issues/19613)) ([363d691](https://github.com/vitejs/vite/commit/363d691b4995d72f26a14eb59ed88a9483b1f931))\n* **deps:** update all non-major dependencies ([#19649](https://github.com/vitejs/vite/issues/19649)) ([f4e712f](https://github.com/vitejs/vite/commit/f4e712ff861f8a9504594a4a5e6d35a7547e5a7e))\n\n### Documentation\n\n* remove $ prefix from create-vite terminal commands in README ([#19532](https://github.com/vitejs/vite/issues/19532)) ([cb9165c](https://github.com/vitejs/vite/commit/cb9165c1b2569aabe3e110e9684a909918eae22c))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency globals to v16 ([#19556](https://github.com/vitejs/vite/issues/19556)) ([e4bdd6b](https://github.com/vitejs/vite/commit/e4bdd6b9dd6e2ccf7d11e84a9c2da805e98eed58))\n\n## <small>[6.3.1](https://github.com/vitejs/vite/compare/create-vite@6.3.0...create-vite@6.3.1) (2025-02-27)</small>\n### Bug Fixes\n\n* **create-vite:** make custom command visible ([#19519](https://github.com/vitejs/vite/issues/19519)) ([5ea9a42](https://github.com/vitejs/vite/commit/5ea9a422c5a000c6a3183c617d6c853cdc4a5151))\n* **create-vite:** remove eslint-plugin-react ([#19514](https://github.com/vitejs/vite/issues/19514)) ([c0e3dba](https://github.com/vitejs/vite/commit/c0e3dba3108e479ab839205cfb046db327bdaf43))\n\n### Documentation\n\n* **create-vite:** recommend eslint-react for linting ([#19524](https://github.com/vitejs/vite/issues/19524)) ([e912080](https://github.com/vitejs/vite/commit/e9120805df4dcf202caa65f15edc7d94fb521a63))\n\n### Miscellaneous Chores\n\n* remove prompts alias ([#19507](https://github.com/vitejs/vite/issues/19507)) ([276c1d3](https://github.com/vitejs/vite/commit/276c1d3b4761c436dc668e76decb9cf20cb25ab9))\n\n## [6.3.0](https://github.com/vitejs/vite/compare/create-vite@6.2.1...create-vite@6.3.0) (2025-02-25)\n### Features\n\n* **create-vite:** use `@clack/prompts` ([#19445](https://github.com/vitejs/vite/issues/19445)) ([5dae6c1](https://github.com/vitejs/vite/commit/5dae6c17da2ef135c2864500db2c8f3e2cf2b3db))\n\n## <small>[6.2.1](https://github.com/vitejs/vite/compare/create-vite@6.2.0...create-vite@6.2.1) (2025-02-25)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19392](https://github.com/vitejs/vite/issues/19392)) ([60456a5](https://github.com/vitejs/vite/commit/60456a54fe90872dbd4bed332ecbd85bc88deb92))\n* **deps:** update all non-major dependencies ([#19440](https://github.com/vitejs/vite/issues/19440)) ([ccac73d](https://github.com/vitejs/vite/commit/ccac73d9d0e92c7232f09207d1d6b893e823ed8e))\n* **deps:** update all non-major dependencies ([#19501](https://github.com/vitejs/vite/issues/19501)) ([c94c9e0](https://github.com/vitejs/vite/commit/c94c9e052127cf4796374de1d698ec60b2973dfa))\n\n### Miscellaneous Chores\n\n* **create-vite:** remove font family `Inter` ([#19474](https://github.com/vitejs/vite/issues/19474)) ([4bcd79a](https://github.com/vitejs/vite/commit/4bcd79a0b38c968825494da1a48f3f91fbc0fbf5))\n* **create-vite:** update `@vitejs/plugin-react-swc` version ([#19384](https://github.com/vitejs/vite/issues/19384)) ([39fab6d](https://github.com/vitejs/vite/commit/39fab6db204ea88ffdb346ee98d8abe0ff5d685f))\n\n### Continuous Integration\n\n* update react-swc plugin version in create-vite by renovate ([#19394](https://github.com/vitejs/vite/issues/19394)) ([0f058a9](https://github.com/vitejs/vite/commit/0f058a989f974d6f012539122f0580e37c2e9852))\n\n## [6.2.0](https://github.com/vitejs/vite/compare/create-vite@6.1.1...create-vite@6.2.0) (2025-02-05)\n### Features\n\n* **create-vite:** add hint for external CLIs ([#19157](https://github.com/vitejs/vite/issues/19157)) ([b9a4cc6](https://github.com/vitejs/vite/commit/b9a4cc6b2875555b621f23ae5457fa37f31e2e24))\n* **create-vite:** official starters options naming ([#19163](https://github.com/vitejs/vite/issues/19163)) ([1992f68](https://github.com/vitejs/vite/commit/1992f681fc7662780f2f2fa4fdb0865a8a54deff))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19098](https://github.com/vitejs/vite/issues/19098)) ([8639538](https://github.com/vitejs/vite/commit/8639538e6498d1109da583ad942c1472098b5919))\n* **deps:** update all non-major dependencies ([#19190](https://github.com/vitejs/vite/issues/19190)) ([f2c07db](https://github.com/vitejs/vite/commit/f2c07dbfc874b46f6e09bb04996d0514663e4544))\n* **deps:** update all non-major dependencies ([#19296](https://github.com/vitejs/vite/issues/19296)) ([2bea7ce](https://github.com/vitejs/vite/commit/2bea7cec4b7fddbd5f2fb6090a7eaf5ae7ca0f1b))\n* **deps:** update all non-major dependencies ([#19341](https://github.com/vitejs/vite/issues/19341)) ([a2b2fad](https://github.com/vitejs/vite/commit/a2b2fad6adb781d3fb163a7e2ce4670d56d60748))\n* **deps:** update react monorepo to v19 (major) ([#18917](https://github.com/vitejs/vite/issues/18917)) ([93d5443](https://github.com/vitejs/vite/commit/93d54439784da0c0a995e50dcfcc081ce4da0121))\n\n### Miscellaneous Chores\n\n* bump TypeScript to ~5.7.2 ([#19056](https://github.com/vitejs/vite/issues/19056)) ([1acea1f](https://github.com/vitejs/vite/commit/1acea1f7c42e43209a6ea0aa99441f143ee15018))\n\n## <small>[6.1.1](https://github.com/vitejs/vite/compare/create-vite@6.1.0...create-vite@6.1.1) (2024-12-24)</small>\n### Bug Fixes\n\n* **create-vite:** svelte-ts typecheck command ([#19014](https://github.com/vitejs/vite/issues/19014)) ([ac32968](https://github.com/vitejs/vite/commit/ac329685bba229e1ff43e3d96324f817d48abe48))\n* **deps:** update all non-major dependencies ([#19045](https://github.com/vitejs/vite/issues/19045)) ([b442d12](https://github.com/vitejs/vite/commit/b442d12c97357697be9341b7abebd78382a3d93d))\n\n### Code Refactoring\n\n* **create-vite:** remove tslib from svelte-ts template ([#19015](https://github.com/vitejs/vite/issues/19015)) ([9066049](https://github.com/vitejs/vite/commit/9066049216b41ac8c6b9177539647d50d3498f1f))\n\n## [6.1.0](https://github.com/vitejs/vite/compare/create-vite@6.0.1...create-vite@6.1.0) (2024-12-19)\n### Features\n\n* **create-vite:** align tsconfigs in svelte-ts template with others ([#18995](https://github.com/vitejs/vite/issues/18995)) ([b48b98c](https://github.com/vitejs/vite/commit/b48b98ce0618eb3d142c0ce86a765502fb4ac190))\n* **create-vite:** extend from @vue/tsconfig to simplify tsconfig.app.json ([#18862](https://github.com/vitejs/vite/issues/18862)) ([89eea02](https://github.com/vitejs/vite/commit/89eea020a3723276495b950542e1c71f4ced781a))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#18853](https://github.com/vitejs/vite/issues/18853)) ([5c02236](https://github.com/vitejs/vite/commit/5c0223636fa277d5daeb4d93c3f32d9f3cd69fc5))\n* **deps:** update all non-major dependencies ([#18967](https://github.com/vitejs/vite/issues/18967)) ([d88d000](https://github.com/vitejs/vite/commit/d88d0004a8e891ca6026d356695e0b319caa7fce))\n* **deps:** update all non-major dependencies ([#18996](https://github.com/vitejs/vite/issues/18996)) ([2b4f115](https://github.com/vitejs/vite/commit/2b4f115129fb3fbd730a92078acb724f8527b7f7))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#18916](https://github.com/vitejs/vite/issues/18916)) ([ef7a6a3](https://github.com/vitejs/vite/commit/ef7a6a35e6827b92445e5a0c2c0022616efc80dd))\n\n### Code Refactoring\n\n* fix logic errors found by no-unnecessary-condition rule ([#18891](https://github.com/vitejs/vite/issues/18891)) ([ea802f8](https://github.com/vitejs/vite/commit/ea802f8f8bcf3771a35c1eaf687378613fbabb24))\n\n## <small>[6.0.1](https://github.com/vitejs/vite/compare/create-vite@6.0.0...create-vite@6.0.1) (2024-11-27)</small>\n### Features\n\n* **create-vite:** bump vite-plugin-solid to `2.11.0` ([#18792](https://github.com/vitejs/vite/issues/18792)) ([32ac96f](https://github.com/vitejs/vite/commit/32ac96f54ca459d1a4c7ff7f4dbb4111eaea00f1))\n* **create-vite:** change Remix to React Router v7 ([#18785](https://github.com/vitejs/vite/issues/18785)) ([31cc61b](https://github.com/vitejs/vite/commit/31cc61b7404b2b22d956856f97eeebd0a62f3b4d))\n\n### Reverts\n\n* update moduleResolution value casing ([#18409](https://github.com/vitejs/vite/issues/18409)) ([#18774](https://github.com/vitejs/vite/issues/18774)) ([b0fc6e3](https://github.com/vitejs/vite/commit/b0fc6e3c2591a30360d3714263cf7cc0e2acbfdf))\n\n## [6.0.0](https://github.com/vitejs/vite/compare/create-vite@5.5.5...create-vite@6.0.0) (2024-11-26)\n### ⚠ BREAKING CHANGES\n\n* drop node 21 support in version ranges (#18729)\n\n### Features\n\n* drop node 21 support in version ranges ([#18729](https://github.com/vitejs/vite/issues/18729)) ([a384d8f](https://github.com/vitejs/vite/commit/a384d8fd39162190675abcfea31ba657383a3d03))\n\n### Bug Fixes\n\n* **create-vite:** change create-app prompt to not remove existing files by default ([#18710](https://github.com/vitejs/vite/issues/18710)) ([c2b7529](https://github.com/vitejs/vite/commit/c2b75292f48be0371e337193c3b37a67b8212f97))\n* **create-vite:** improve project name inference from path ([#16490](https://github.com/vitejs/vite/issues/16490)) ([8518113](https://github.com/vitejs/vite/commit/8518113dee2554401d23b2fba62ecab31d2b0541))\n* **deps:** update all non-major dependencies ([#18691](https://github.com/vitejs/vite/issues/18691)) ([f005461](https://github.com/vitejs/vite/commit/f005461ecce89ada21cb0c021f7af460b5479736))\n\n### Miscellaneous Chores\n\n* **create-vite:** change directory structure of `template-vanilla` for consistency ([#18716](https://github.com/vitejs/vite/issues/18716)) ([56a86ae](https://github.com/vitejs/vite/commit/56a86ae479b6aaf1c0a15bfedb0ee435e8ffcf3a))\n* **create-vite:** update to vite 6 ([#18770](https://github.com/vitejs/vite/issues/18770)) ([80bf954](https://github.com/vitejs/vite/commit/80bf9549b48c66a47e5cc76a7540ce3e62e2f2da))\n* **deps:** update all non-major dependencies ([#18562](https://github.com/vitejs/vite/issues/18562)) ([fb227ec](https://github.com/vitejs/vite/commit/fb227ec4402246b5a13e274c881d9de6dd8082dd))\n* **deps:** update all non-major dependencies ([#18634](https://github.com/vitejs/vite/issues/18634)) ([e2231a9](https://github.com/vitejs/vite/commit/e2231a92af46db144b9c94fb57918ac683dc93cb))\n* **deps:** update all non-major dependencies ([#18746](https://github.com/vitejs/vite/issues/18746)) ([0ad16e9](https://github.com/vitejs/vite/commit/0ad16e92d57453d9e5392c90fd06bda947be9de6))\n\n## <small>[5.5.5](https://github.com/vitejs/vite/compare/create-vite@5.5.4...create-vite@5.5.5) (2024-10-30)</small>\n### Bug Fixes\n\n* **create-vite:** add tsBuildInfoFile option ([#18435](https://github.com/vitejs/vite/issues/18435)) ([0a4427f](https://github.com/vitejs/vite/commit/0a4427fc44b9b2075225bf8a9f1d88a8a428a217))\n* **deps:** update all non-major dependencies ([#18484](https://github.com/vitejs/vite/issues/18484)) ([2ec12df](https://github.com/vitejs/vite/commit/2ec12df98d07eb4c986737e86a4a9f8066724658))\n\n### Miscellaneous Chores\n\n* upgrade to unbuild v3 rc ([#18502](https://github.com/vitejs/vite/issues/18502)) ([ddd5c5d](https://github.com/vitejs/vite/commit/ddd5c5d00ff7894462a608841560883f9c771f22))\n\n## <small>[5.5.4](https://github.com/vitejs/vite/compare/create-vite@5.5.3...create-vite@5.5.4) (2024-10-23)</small>\n### Features\n\n* add custom Angular variants ([#18410](https://github.com/vitejs/vite/issues/18410)) ([ac1fd41](https://github.com/vitejs/vite/commit/ac1fd41059f5549922b9f1a93c2bc00fbfcca3e8))\n* **create-vite:** update to svelte 5 ([#18407](https://github.com/vitejs/vite/issues/18407)) ([291830f](https://github.com/vitejs/vite/commit/291830fa632c756b2a0311142d1f25ca7b56a637))\n\n### Bug Fixes\n\n* **create-vite:** update qwik URL ([#18285](https://github.com/vitejs/vite/issues/18285)) ([45c9b5c](https://github.com/vitejs/vite/commit/45c9b5cca160346b41dbddacf6f9000ab1b638bc))\n* **deps:** update all non-major dependencies ([#18292](https://github.com/vitejs/vite/issues/18292)) ([5cac054](https://github.com/vitejs/vite/commit/5cac0544dca2764f0114aac38e9922a0c13d7ef4))\n* **deps:** update all non-major dependencies ([#18345](https://github.com/vitejs/vite/issues/18345)) ([5552583](https://github.com/vitejs/vite/commit/5552583a2272cd4208b30ad60e99d984e34645f0))\n\n### Miscellaneous Chores\n\n* change Angular customCommand ([#18425](https://github.com/vitejs/vite/issues/18425)) ([b53db53](https://github.com/vitejs/vite/commit/b53db53df17c43602d61a24e9bf579267ee8eb6b))\n* combine deps license with same text ([#18356](https://github.com/vitejs/vite/issues/18356)) ([b5d1a05](https://github.com/vitejs/vite/commit/b5d1a058f9dab6a6b1243c2a0b11d2c421dd3291))\n* **create-vite:** mark template files as CC0 ([#18366](https://github.com/vitejs/vite/issues/18366)) ([f6b9074](https://github.com/vitejs/vite/commit/f6b90747eb2b1ad863e5f147a80c75b15e38a51b))\n* **deps:** bump TypeScript to 5.6 ([#18254](https://github.com/vitejs/vite/issues/18254)) ([57a0e85](https://github.com/vitejs/vite/commit/57a0e85186b88118bf5f79dd53391676fb91afec))\n* **deps:** update all non-major dependencies ([#18404](https://github.com/vitejs/vite/issues/18404)) ([802839d](https://github.com/vitejs/vite/commit/802839d48335a69eb15f71f2cd816d0b6e4d3556))\n* **deps:** update eslint-plugin-react-hooks to stable v5 ([#18335](https://github.com/vitejs/vite/issues/18335)) ([0ddfb9f](https://github.com/vitejs/vite/commit/0ddfb9f31a74eea6d61bbedbda2a5c280c9bcc77))\n* specify TypeScript version with `~` ([#18406](https://github.com/vitejs/vite/issues/18406)) ([70bb8de](https://github.com/vitejs/vite/commit/70bb8ded1d5d2f1323d0350a8ad9cb3954c0bd61))\n* update all url references of vitejs.dev to vite.dev ([#18276](https://github.com/vitejs/vite/issues/18276)) ([7052c8f](https://github.com/vitejs/vite/commit/7052c8f6fc253f0a88ff04a4c18c108f3bfdaa78))\n* update license copyright ([#18278](https://github.com/vitejs/vite/issues/18278)) ([56eb869](https://github.com/vitejs/vite/commit/56eb869a67551a257d20cba00016ea59b1e1a2c4))\n* update moduleResolution value casing ([#18409](https://github.com/vitejs/vite/issues/18409)) ([ff018dc](https://github.com/vitejs/vite/commit/ff018dca959c73481ae5f8328cd77d3b02f02134))\n\n## <small>[5.5.3](https://github.com/vitejs/vite/compare/create-vite@5.5.2...create-vite@5.5.3) (2024-10-04)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#18170](https://github.com/vitejs/vite/issues/18170)) ([c8aea5a](https://github.com/vitejs/vite/commit/c8aea5ae0af90dc6796ef3bdd612d1eb819f157b))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#17896](https://github.com/vitejs/vite/issues/17896)) ([3dc23d9](https://github.com/vitejs/vite/commit/3dc23d9aa5deac4d5591ff94eeb978ec1d702072))\n* **deps:** update all non-major dependencies ([#17945](https://github.com/vitejs/vite/issues/17945)) ([cfb621e](https://github.com/vitejs/vite/commit/cfb621e7a5a3e24d710a9af156e6855e73caf891))\n* **deps:** update all non-major dependencies ([#17991](https://github.com/vitejs/vite/issues/17991)) ([0ca53cf](https://github.com/vitejs/vite/commit/0ca53cff9ff49108fcec75ff01d2445f9c2f2a4c))\n* **deps:** update all non-major dependencies ([#18050](https://github.com/vitejs/vite/issues/18050)) ([7cac03f](https://github.com/vitejs/vite/commit/7cac03fa5197a72d2e2422bd0243a85a9a18abfc))\n* **deps:** update all non-major dependencies ([#18108](https://github.com/vitejs/vite/issues/18108)) ([a73bbaa](https://github.com/vitejs/vite/commit/a73bbaadb512a884924cc884060e50ea6d809d74))\n* **deps:** update all non-major dependencies ([#18230](https://github.com/vitejs/vite/issues/18230)) ([c0edd26](https://github.com/vitejs/vite/commit/c0edd26bbfeb9a8d80ebaa420e54fbb7f165bd9b))\n* **deps:** update dependency svelte-check to v4 ([#18051](https://github.com/vitejs/vite/issues/18051)) ([ecabf89](https://github.com/vitejs/vite/commit/ecabf8954ff1db3f9f3e32861de765f028108d2e))\n* enable some eslint rules ([#18084](https://github.com/vitejs/vite/issues/18084)) ([e9a2746](https://github.com/vitejs/vite/commit/e9a2746ca77473b1814fd05db3d299c074135fe5))\n\n### Code Refactoring\n\n* **create-vite:** use picocolors ([#18085](https://github.com/vitejs/vite/issues/18085)) ([ba37df0](https://github.com/vitejs/vite/commit/ba37df0813ad3864fc4b8c6c0b289a1f2bc00c36))\n\n## <small>[5.5.2](https://github.com/vitejs/vite/compare/create-vite@5.5.1...create-vite@5.5.2) (2024-08-15)</small>\n### Bug Fixes\n\n* **create-vite:** move ESLint \"ignores\" config to a separate object in React templates ([#17885](https://github.com/vitejs/vite/issues/17885)) ([1b3b702](https://github.com/vitejs/vite/commit/1b3b702a7ec04fecb81f2642ffdde0b13e38a921))\n* **deps:** update all non-major dependencies ([#17869](https://github.com/vitejs/vite/issues/17869)) ([d11711c](https://github.com/vitejs/vite/commit/d11711c7e4c082fd0400245bfdc766006fd38ac8))\n\n## <small>[5.5.1](https://github.com/vitejs/vite/compare/create-vite@5.5.0...create-vite@5.5.1) (2024-08-07)</small>\n### Bug Fixes\n\n* **create-vite:** remove eslint overrides ([#17833](https://github.com/vitejs/vite/issues/17833)) ([8bc122f](https://github.com/vitejs/vite/commit/8bc122feea8b840575796e1846871a2090525fc9))\n\n## [5.5.0](https://github.com/vitejs/vite/compare/create-vite@5.4.0...create-vite@5.5.0) (2024-08-07)\n### Features\n\n* **create-vite:** add eslint.config.js to React templates ([#12860](https://github.com/vitejs/vite/issues/12860)) ([dcfa75c](https://github.com/vitejs/vite/commit/dcfa75c6f5422d47cbe670798080d3f6d9dcdb6b))\n\n### Bug Fixes\n\n* **create-vite:** avoid usage of composite in TS configs ([#17774](https://github.com/vitejs/vite/issues/17774)) ([efcd830](https://github.com/vitejs/vite/commit/efcd830e479092a0d3b95e0caf4a253d7835892c))\n* **deps:** update all non-major dependencies ([#17629](https://github.com/vitejs/vite/issues/17629)) ([93281b0](https://github.com/vitejs/vite/commit/93281b0e09ff8b00e21c24b80ed796db89cbc1ef))\n* **deps:** update all non-major dependencies ([#17780](https://github.com/vitejs/vite/issues/17780)) ([e408542](https://github.com/vitejs/vite/commit/e408542748edebd93dba07f21e3fd107725cadca))\n\n### Miscellaneous Chores\n\n* bump typescript-eslint to v8 ([#17624](https://github.com/vitejs/vite/issues/17624)) ([d1891fd](https://github.com/vitejs/vite/commit/d1891fda026d27f53409dec97e156a59da609196))\n* **deps:** update all non-major dependencies ([#17734](https://github.com/vitejs/vite/issues/17734)) ([9983731](https://github.com/vitejs/vite/commit/998373120c8306326469d4f342690c17774acdf9))\n* **deps:** update all non-major dependencies ([#17820](https://github.com/vitejs/vite/issues/17820)) ([bb2f8bb](https://github.com/vitejs/vite/commit/bb2f8bb55fdd64e4f16831ff98921c221a5e734a))\n* **deps:** update typescript ([#17699](https://github.com/vitejs/vite/issues/17699)) ([df5ceb3](https://github.com/vitejs/vite/commit/df5ceb35b7f744cfcdfe3a28834f890f35f2b18f))\n* extend commit hash ([#17709](https://github.com/vitejs/vite/issues/17709)) ([4fc9b64](https://github.com/vitejs/vite/commit/4fc9b6424c27aca8004c368b69991a56264e4fdb))\n* remove fs-extra dev dependency ([#17782](https://github.com/vitejs/vite/issues/17782)) ([461d37b](https://github.com/vitejs/vite/commit/461d37b9472ab0f12f9da5bf9aa6f98ece1f1962))\n\n### Code Refactoring\n\n* **create-vite:** use named imports for react ([#17773](https://github.com/vitejs/vite/issues/17773)) ([6eab91e](https://github.com/vitejs/vite/commit/6eab91e5011ec443179af5e58aa7c6123b2d445e))\n\n## [5.4.0](https://github.com/vitejs/vite/compare/create-vite@5.3.0...create-vite@5.4.0) (2024-07-16)\n### Features\n\n* add `create-preact` to list of options in `create-vite` ([#17674](https://github.com/vitejs/vite/issues/17674)) ([d4d98dc](https://github.com/vitejs/vite/commit/d4d98dc95e1f4e4bbbd1ed4529e08e159598a83a))\n\n### Bug Fixes\n\n* **create-vite:** target dir contains special characters ([#17549](https://github.com/vitejs/vite/issues/17549)) ([f946c86](https://github.com/vitejs/vite/commit/f946c8694056fe05262b08a549f3ff7b484d03ea))\n* **deps:** update all non-major dependencies ([#17590](https://github.com/vitejs/vite/issues/17590)) ([012490c](https://github.com/vitejs/vite/commit/012490ca8682e2b560737cb54dbb465ab4f36471))\n\n### Documentation\n\n* **create-vite:** add missing tsconfig.app.json file at the project array for react-ts ([#17645](https://github.com/vitejs/vite/issues/17645)) ([6d31a1d](https://github.com/vitejs/vite/commit/6d31a1de593520ca0f6a323d4f2fde4e59770f4a))\n\n### Miscellaneous Chores\n\n* add `create-preact` recommendation to Preact templates ([#17649](https://github.com/vitejs/vite/issues/17649)) ([564c8f4](https://github.com/vitejs/vite/commit/564c8f45f5429bd149b441d7dca4f44347dedfb1))\n* **deps:** update all non-major dependencies ([#17553](https://github.com/vitejs/vite/issues/17553)) ([a33a97f](https://github.com/vitejs/vite/commit/a33a97f8c32bdeadcad5a9e0de50612ac985d3d0))\n\n## [5.3.0](https://github.com/vitejs/vite/compare/create-vite@5.2.3...create-vite@5.3.0) (2024-06-21)\n### Features\n\n* **create-vite:** add help usage ([#16390](https://github.com/vitejs/vite/issues/16390)) ([1d9bfc0](https://github.com/vitejs/vite/commit/1d9bfc006bcfdc9159154fe453adeab9294afd54))\n* **create-vite:** use \"solution\" tsconfig so that vite.config.ts is type checked ([#15913](https://github.com/vitejs/vite/issues/15913)) ([cf3f40c](https://github.com/vitejs/vite/commit/cf3f40cd383509fdb1294568fb38bacfac419ea1))\n\n### Bug Fixes\n\n* **create-vite:** revert eslint 9 upgrade in templates ([#17511](https://github.com/vitejs/vite/issues/17511)) ([86cf1b4](https://github.com/vitejs/vite/commit/86cf1b4b497557f09a0d9a81dc304e7a081d6198))\n* **create-vite:** update tsconfig with moduleDetection true ([#17468](https://github.com/vitejs/vite/issues/17468)) ([7b240e4](https://github.com/vitejs/vite/commit/7b240e408ed83f172e9f88823eae3b4a9ba92674))\n* **deps:** update all non-major dependencies ([#16258](https://github.com/vitejs/vite/issues/16258)) ([7caef42](https://github.com/vitejs/vite/commit/7caef4216e16d9ac71e38598a9ecedce2281d42f))\n* **deps:** update all non-major dependencies ([#16376](https://github.com/vitejs/vite/issues/16376)) ([58a2938](https://github.com/vitejs/vite/commit/58a2938a9766981fdc2ed89bec8ff1c96cae0716))\n* **deps:** update all non-major dependencies ([#16488](https://github.com/vitejs/vite/issues/16488)) ([2d50be2](https://github.com/vitejs/vite/commit/2d50be2a5424e4f4c22774652ed313d2a232f8af))\n* **deps:** update all non-major dependencies ([#16549](https://github.com/vitejs/vite/issues/16549)) ([2d6a13b](https://github.com/vitejs/vite/commit/2d6a13b0aa1f3860482dac2ce260cfbb0713033f))\n* **deps:** update all non-major dependencies ([#16603](https://github.com/vitejs/vite/issues/16603)) ([6711553](https://github.com/vitejs/vite/commit/671155337af795156fe40a95935a8d2b27af1048))\n* **deps:** update all non-major dependencies ([#16660](https://github.com/vitejs/vite/issues/16660)) ([bf2f014](https://github.com/vitejs/vite/commit/bf2f0145fecb67ca2342c3530716f4c5ddd35a68))\n* **deps:** update all non-major dependencies ([#17321](https://github.com/vitejs/vite/issues/17321)) ([4a89766](https://github.com/vitejs/vite/commit/4a89766d838527c144f14e842211100b16792018))\n* **deps:** update all non-major dependencies ([#17430](https://github.com/vitejs/vite/issues/17430)) ([4453d35](https://github.com/vitejs/vite/commit/4453d3578b343d16a8a5298bf154f280088968d9))\n* **deps:** update all non-major dependencies ([#17494](https://github.com/vitejs/vite/issues/17494)) ([bf123f2](https://github.com/vitejs/vite/commit/bf123f2c6242424a3648cf9234281fd9ff44e3d5))\n\n### Documentation\n\n* **create-vite:** link to Vue docs for IDE support info ([#16225](https://github.com/vitejs/vite/issues/16225)) ([520bb89](https://github.com/vitejs/vite/commit/520bb8917e9bef86c27a1e3486d51a4878bd4297))\n\n### Miscellaneous Chores\n\n* **create-vite:** update IDE support instructions in helloworld components ([#16605](https://github.com/vitejs/vite/issues/16605)) ([a265282](https://github.com/vitejs/vite/commit/a2652825b791336f7fa7e7b78665a50a043f7b3a))\n* **deps:** update all non-major dependencies ([#16325](https://github.com/vitejs/vite/issues/16325)) ([a78e265](https://github.com/vitejs/vite/commit/a78e265822ebf06c5775c2083ee345e974488c6b))\n* **deps:** update all non-major dependencies ([#16722](https://github.com/vitejs/vite/issues/16722)) ([b45922a](https://github.com/vitejs/vite/commit/b45922a91d4a73c27f78f26e369b7b1fd8d800e3))\n* **deps:** update all non-major dependencies ([#17373](https://github.com/vitejs/vite/issues/17373)) ([f2d52f1](https://github.com/vitejs/vite/commit/f2d52f1384e4048ebe7d6bb8c5410e81540c469a))\n* **deps:** update dependency eslint to v9 ([#16661](https://github.com/vitejs/vite/issues/16661)) ([6c10662](https://github.com/vitejs/vite/commit/6c106622812480d2bb134f8ed8efa84e2eb942c4))\n* **deps:** update dependency execa to v9 ([#16662](https://github.com/vitejs/vite/issues/16662)) ([76d1642](https://github.com/vitejs/vite/commit/76d1642c3c9b0f5ec2c52a66dd0d0d565c3a2309))\n\n## <small>[5.2.3](https://github.com/vitejs/vite/compare/create-vite@5.2.2...create-vite@5.2.3) (2024-03-20)</small>\n### Bug Fixes\n\n* **create-vite:** remove vue3 deprecated plugin (TypeScript Vue Plugin) ([#16158](https://github.com/vitejs/vite/issues/16158)) ([1645fc0](https://github.com/vitejs/vite/commit/1645fc0b284d98998348cddbd6945d6e7f897104))\n* **create-vite:** switch to default Remix template ([#16203](https://github.com/vitejs/vite/issues/16203)) ([ea480df](https://github.com/vitejs/vite/commit/ea480df56d355d978e510ea017924bfd876804be))\n\n### Documentation\n\n* update volar name and remove takeover mode related docs ([#16171](https://github.com/vitejs/vite/issues/16171)) ([0a56177](https://github.com/vitejs/vite/commit/0a56177272449489921fef5479b7385dc79a8beb))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#16186](https://github.com/vitejs/vite/issues/16186)) ([842643d](https://github.com/vitejs/vite/commit/842643d82b5fc2b17e994cf47f8fc1a39c09201e))\n* **deps:** update dependency vue-tsc to v2 ([#16187](https://github.com/vitejs/vite/issues/16187)) ([72104f6](https://github.com/vitejs/vite/commit/72104f6de5398a1a0511404e8485b3b7721be537))\n\n## <small>[5.2.2](https://github.com/vitejs/vite/compare/create-vite@5.2.1...create-vite@5.2.2) (2024-03-11)</small>\n### Bug Fixes\n\n* **create-vite:** ts error in the svelte-ts template ([#16031](https://github.com/vitejs/vite/issues/16031)) ([ff4c834](https://github.com/vitejs/vite/commit/ff4c83456f474e0da0fa7848f6431d4fe35306b8))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#16028](https://github.com/vitejs/vite/issues/16028)) ([7cfe80d](https://github.com/vitejs/vite/commit/7cfe80d0df7edfe861b8cc281303f20fc7633841))\n* **deps:** update all non-major dependencies ([#16131](https://github.com/vitejs/vite/issues/16131)) ([a862ecb](https://github.com/vitejs/vite/commit/a862ecb941a432b6e3bab62331012e4b53ddd4e8))\n\n## <small>[5.2.1](https://github.com/vitejs/vite/compare/create-vite@5.2.0...create-vite@5.2.1) (2024-02-21)</small>\n### Features\n\n* **create-vite:** add custom remix option for React ([#15995](https://github.com/vitejs/vite/issues/15995)) ([f3b195c](https://github.com/vitejs/vite/commit/f3b195cf3344d1f0a3b6f8cd8600e4df7c577d62))\n\n### Bug Fixes\n\n* **create-vite:** remove tsc command from qwik template ([#15982](https://github.com/vitejs/vite/issues/15982)) ([5e05f10](https://github.com/vitejs/vite/commit/5e05f10069c84f5749da9d3cdb7d5a5a1a349c53))\n* **deps:** update all non-major dependencies ([#15959](https://github.com/vitejs/vite/issues/15959)) ([571a3fd](https://github.com/vitejs/vite/commit/571a3fde438d60540cfeba132e24646badf5ff2f))\n* **qwik template:** change preview script ([#15975](https://github.com/vitejs/vite/issues/15975)) ([725589a](https://github.com/vitejs/vite/commit/725589adbf7f5ab940600c51f8540c7b15fb3d69))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#15874](https://github.com/vitejs/vite/issues/15874)) ([d16ce5d](https://github.com/vitejs/vite/commit/d16ce5db2f0c4dd327093bae2cbaab0d20c511e9))\n* **deps:** update typescript-eslint monorepo to v7 (major) ([#15960](https://github.com/vitejs/vite/issues/15960)) ([7b9e927](https://github.com/vitejs/vite/commit/7b9e927a65e0f8580a6a8faeaa938f659390259f))\n\n## [5.2.0](https://github.com/vitejs/vite/compare/create-vite@5.1.0...create-vite@5.2.0) (2024-02-08)\n### Features\n\n* **create-vite:** allow overwrite in command line ([#15808](https://github.com/vitejs/vite/issues/15808)) ([1882c73](https://github.com/vitejs/vite/commit/1882c734b1aa3199d12988f06591b71ed5d5af27))\n* **create-vite:** set \"strict: true\" in tsconfig.node.json ([#15820](https://github.com/vitejs/vite/issues/15820)) ([5e5ca7d](https://github.com/vitejs/vite/commit/5e5ca7d1db938cfd8c770746facf52e099c62583))\n\n### Bug Fixes\n\n* **create-vite:** turn off `react/jsx-no-target-blank` ESLint rule in React JS template ([#15672](https://github.com/vitejs/vite/issues/15672)) ([a6f39e8](https://github.com/vitejs/vite/commit/a6f39e861c9981ea36864ebac90ea4c52863b9a5))\n* **deps:** update all non-major dependencies ([#15375](https://github.com/vitejs/vite/issues/15375)) ([ab56227](https://github.com/vitejs/vite/commit/ab56227d89c92bfa781264e1474ed522892e3b8f))\n* **deps:** update all non-major dependencies ([#15603](https://github.com/vitejs/vite/issues/15603)) ([109fb80](https://github.com/vitejs/vite/commit/109fb805fd28c9f738036985b90cf207d1c48e89))\n* **deps:** update all non-major dependencies ([#15675](https://github.com/vitejs/vite/issues/15675)) ([4d9363a](https://github.com/vitejs/vite/commit/4d9363ad6bc460fe2da811cb48b036e53b8cfc75))\n* **deps:** update all non-major dependencies ([#15803](https://github.com/vitejs/vite/issues/15803)) ([e0a6ef2](https://github.com/vitejs/vite/commit/e0a6ef2b9e6f1df8c5e71efab6182b7cf662d18d))\n\n### Documentation\n\n* changed bunx create-vite to bun create vite ([#15646](https://github.com/vitejs/vite/issues/15646)) ([f3c11bb](https://github.com/vitejs/vite/commit/f3c11bb8ab14648379d9816b4e0df980cd4ac214))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency @vitejs/plugin-vue to v5 ([#15474](https://github.com/vitejs/vite/issues/15474)) ([17857e7](https://github.com/vitejs/vite/commit/17857e79d2c9bbe53f7d35ea6046133d68699940))\n\n## [5.1.0](https://github.com/vitejs/vite/compare/create-vite@5.0.0...create-vite@5.1.0) (2023-12-12)\n### Features\n\n* **cli:** allow initializing non-empty directory ([#15272](https://github.com/vitejs/vite/issues/15272)) ([00669e1](https://github.com/vitejs/vite/commit/00669e135ecfe7f8dbaddcee531efd368bdfa2d2))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#15233](https://github.com/vitejs/vite/issues/15233)) ([ad3adda](https://github.com/vitejs/vite/commit/ad3adda7215c33874a07cbd4d430fcffe4c85dce))\n* **deps:** update all non-major dependencies ([#15304](https://github.com/vitejs/vite/issues/15304)) ([bb07f60](https://github.com/vitejs/vite/commit/bb07f605cca698a81f1b4606ddefb34485069dd1))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#15145](https://github.com/vitejs/vite/issues/15145)) ([7ff2c0a](https://github.com/vitejs/vite/commit/7ff2c0afe8c6b6901385af829f2e7e80c1fe344c))\n\n## [5.0.0](https://github.com/vitejs/vite/compare/create-vite@5.0.0-beta.1...create-vite@5.0.0) (2023-11-16)\n### Features\n\n* **create-vite:** update templates for vite 5 ([#15007](https://github.com/vitejs/vite/issues/15007)) ([e208697](https://github.com/vitejs/vite/commit/e208697c8e772e01b62797e29ae808ba40aa3a7c))\n\n### Bug Fixes\n\n* **create-vite:** remove repeated styles in vue-template ([#14766](https://github.com/vitejs/vite/issues/14766)) ([0fed210](https://github.com/vitejs/vite/commit/0fed2104ad07f0de4dbf29ed8d6047b6918c7db3))\n* **deps:** update all non-major dependencies ([#14729](https://github.com/vitejs/vite/issues/14729)) ([d5d96e7](https://github.com/vitejs/vite/commit/d5d96e712788bc762d9c135bc84628dbcfc7fb58))\n* **deps:** update all non-major dependencies ([#14883](https://github.com/vitejs/vite/issues/14883)) ([e5094e5](https://github.com/vitejs/vite/commit/e5094e5bf2aee3516d04ce35ba2fb27e70ea9858))\n* **deps:** update all non-major dependencies ([#14961](https://github.com/vitejs/vite/issues/14961)) ([0bb3995](https://github.com/vitejs/vite/commit/0bb3995a7d2245ef1cc7b2ed8a5242e33af16874))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency eslint-plugin-react-refresh to ^0.4.4 ([#14795](https://github.com/vitejs/vite/issues/14795)) ([7881457](https://github.com/vitejs/vite/commit/788145790e7652d715575d7a0bc33a825b49d566))\n\n## [5.0.0-beta.1](https://github.com/vitejs/vite/compare/create-vite@5.0.0-beta.0...create-vite@5.0.0-beta.1) (2023-10-19)\n### ⚠ BREAKING CHANGES\n\n* rollup v4 (#14508)\n\n### Features\n\n* rollup v4 ([#14508](https://github.com/vitejs/vite/issues/14508)) ([dee6067](https://github.com/vitejs/vite/commit/dee6067ec78c9f9d7923d780b4941d835b34fcf4))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#14559](https://github.com/vitejs/vite/issues/14559)) ([6868480](https://github.com/vitejs/vite/commit/6868480d0036f08388e82611992d58ee52cf97b7))\n* **deps:** update all non-major dependencies ([#14635](https://github.com/vitejs/vite/issues/14635)) ([21017a9](https://github.com/vitejs/vite/commit/21017a9408643cbc7204215ecc5a3fdaf74dc81e))\n* **deps:** update dependency lit to v3 ([#14638](https://github.com/vitejs/vite/issues/14638)) ([c81f3da](https://github.com/vitejs/vite/commit/c81f3da6c3a07beb3cd84fe538090754a3549ce9))\n\n### Documentation\n\n* **create-vite:** add qwik and qwik-ts to the list ([#14624](https://github.com/vitejs/vite/issues/14624)) ([de87fe4](https://github.com/vitejs/vite/commit/de87fe442facd66124fae959baa769ada2e4b6c0))\n\n### Miscellaneous Chores\n\n* **create-vite:** update dependencies ([#14698](https://github.com/vitejs/vite/issues/14698)) ([bd82c30](https://github.com/vitejs/vite/commit/bd82c308c01587d14aeb90af054bcc433b3833fd))\n\n## [5.0.0-beta.0](https://github.com/vitejs/vite/compare/create-vite@4.4.1...create-vite@5.0.0-beta.0) (2023-10-04)\n### ⚠ BREAKING CHANGES\n\n* bump minimum node version to 18 (#14030)\n\n### Features\n\n* bump minimum node version to 18 ([#14030](https://github.com/vitejs/vite/issues/14030)) ([2c1a45c](https://github.com/vitejs/vite/commit/2c1a45c86cab6ecf02abb6e50385f773d5ed568e))\n* **create-vite:** update to vite 5.0 beta ([#14534](https://github.com/vitejs/vite/issues/14534)) ([97c58e0](https://github.com/vitejs/vite/commit/97c58e0d045aea9088ae7d0492c3073847658e95))\n\n### Bug Fixes\n\n* **create-vite:** remove non-standard style ([#14451](https://github.com/vitejs/vite/issues/14451)) ([8349d4e](https://github.com/vitejs/vite/commit/8349d4e7efd2835eafde5d85eec51defa5d8b69f))\n* **create-vite:** remove redundant tsconfig include configuration ([#14256](https://github.com/vitejs/vite/issues/14256)) ([6ea34cc](https://github.com/vitejs/vite/commit/6ea34ccdd5b83f2b76aebbff2cf263621322e0f9))\n* **deps:** update all non-major dependencies ([#14092](https://github.com/vitejs/vite/issues/14092)) ([68638f7](https://github.com/vitejs/vite/commit/68638f7b0b04ddfdf35dc8686c6a022aadbb9453))\n* **deps:** update all non-major dependencies ([#14460](https://github.com/vitejs/vite/issues/14460)) ([b77bff0](https://github.com/vitejs/vite/commit/b77bff0b93ba9449f63c8373ecf82289a39832a0))\n* **deps:** update all non-major dependencies ([#14510](https://github.com/vitejs/vite/issues/14510)) ([eb204fd](https://github.com/vitejs/vite/commit/eb204fd3c5bffb6c6fb40f562f762e426fbaf183))\n* **template:** eliminate the error that occurs when enabling eslint-plugin-markdown ([#13942](https://github.com/vitejs/vite/issues/13942)) ([6251a66](https://github.com/vitejs/vite/commit/6251a666555a42ae518e76af6011e9cb091e3028))\n\n### Documentation\n\n* detect Bun package manager in `create-vite` ([#14017](https://github.com/vitejs/vite/issues/14017)) ([4d3cdd1](https://github.com/vitejs/vite/commit/4d3cdd1b316950885d3edd210d7777cf71b347ce))\n* remove npm@6 commands ([#14240](https://github.com/vitejs/vite/issues/14240)) ([65b6906](https://github.com/vitejs/vite/commit/65b690657f0f97ef7912f3f45002c725d4bcc989))\n\n### Miscellaneous Chores\n\n* **create-vite:** add npm badge ([#14251](https://github.com/vitejs/vite/issues/14251)) ([68bd0a8](https://github.com/vitejs/vite/commit/68bd0a84011eb2bd8a7bb03da6e95acc97e466ea))\n* **deps:** update all non-major dependencies ([#13938](https://github.com/vitejs/vite/issues/13938)) ([a1b519e](https://github.com/vitejs/vite/commit/a1b519e2c71593b6b4286c2f0bd8bfe2e0ad046d))\n* **deps:** update all non-major dependencies ([#14034](https://github.com/vitejs/vite/issues/14034)) ([b0ebf5c](https://github.com/vitejs/vite/commit/b0ebf5c69d5dbd1daad32ae3f96515e6073473ad))\n* ensure create-vite has unbuild dev dep ([#14419](https://github.com/vitejs/vite/issues/14419)) ([881d080](https://github.com/vitejs/vite/commit/881d080c293b642685b2448088422102f24821e7))\n* **templates:** alias react to preact/compat in tsconfig ([#14262](https://github.com/vitejs/vite/issues/14262)) ([c796959](https://github.com/vitejs/vite/commit/c7969597caba80cf5d3348cba9f18ad9d14e9295))\n* update manually bumped deps ([#14430](https://github.com/vitejs/vite/issues/14430)) ([995c4b6](https://github.com/vitejs/vite/commit/995c4b6303e418780d3039db09f591d41dd6b473))\n\n## <small>[4.4.1](https://github.com/vitejs/vite/compare/create-vite@4.4.0...create-vite@4.4.1) (2023-07-20)</small>\n### Bug Fixes\n\n* **create-vite:** fix eslint configuration for React templates ([#13749](https://github.com/vitejs/vite/issues/13749)) ([2ad78aa](https://github.com/vitejs/vite/commit/2ad78aa205563f87b1607d0789608c13695cd9da))\n* **deps:** update all non-major dependencies ([#13758](https://github.com/vitejs/vite/issues/13758)) ([8ead116](https://github.com/vitejs/vite/commit/8ead11648514ae4975bf4328d6e15bd4dd42e45e))\n* **deps:** update all non-major dependencies ([#13872](https://github.com/vitejs/vite/issues/13872)) ([975a631](https://github.com/vitejs/vite/commit/975a631ec7c2373354aeeac6bc2977f24b54d13d))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency prettier to v3 ([#13759](https://github.com/vitejs/vite/issues/13759)) ([5a56941](https://github.com/vitejs/vite/commit/5a56941a895fd0ffdbdbf0094336fb7f0f4099c1))\n\n## [4.4.0](https://github.com/vitejs/vite/compare/create-vite@4.3.2...create-vite@4.4.0) (2023-07-06)\n### Features\n\n* **create-vite:** add qwik templates ([#13620](https://github.com/vitejs/vite/issues/13620)) ([ef4602b](https://github.com/vitejs/vite/commit/ef4602bc56c0b9579342acca7ef82ba655d56a2e))\n* **create-vite:** add solidjs templates ([#12218](https://github.com/vitejs/vite/issues/12218)) ([#12241](https://github.com/vitejs/vite/issues/12241)) ([277e844](https://github.com/vitejs/vite/commit/277e844c1a0cc729c387d9a16ef838835eb06f49))\n* **create-vite:** update create vite for Svelte 4 ([#13602](https://github.com/vitejs/vite/issues/13602)) ([8868fb7](https://github.com/vitejs/vite/commit/8868fb76e18f532e5f72b154f37d518dcc68e45b))\n* update eslint config in React templates ([#13550](https://github.com/vitejs/vite/issues/13550)) ([6fe1491](https://github.com/vitejs/vite/commit/6fe14911deac34f5874687705a46deb9caf1cb10))\n\n### Bug Fixes\n\n* 'module' is not defined eslint error in template-react (fix [#13517](https://github.com/vitejs/vite/issues/13517)) ([#13518](https://github.com/vitejs/vite/issues/13518)) ([41380a5](https://github.com/vitejs/vite/commit/41380a5bbce90f0c9e00d80a55b5dd71a5a706f8))\n* **create-vite:** support bun as a script runner ([#13402](https://github.com/vitejs/vite/issues/13402)) ([471fba2](https://github.com/vitejs/vite/commit/471fba2d1cf647a0bea747739d4d90def60e83ce))\n* **deps:** update all non-major dependencies ([#13059](https://github.com/vitejs/vite/issues/13059)) ([123ef4c](https://github.com/vitejs/vite/commit/123ef4c47c611ebd99d8b41c89c547422aea9c1d))\n* **deps:** update all non-major dependencies ([#13488](https://github.com/vitejs/vite/issues/13488)) ([bd09248](https://github.com/vitejs/vite/commit/bd09248e50ae50ec57b9a72efe0a27aa397ec2e1))\n* **deps:** update all non-major dependencies ([#13701](https://github.com/vitejs/vite/issues/13701)) ([02c6bc3](https://github.com/vitejs/vite/commit/02c6bc38645ce18f9e1c8a71421fb8aad7081688))\n* **template:** bump react-swc plugin version ([#13699](https://github.com/vitejs/vite/issues/13699)) ([8315f9e](https://github.com/vitejs/vite/commit/8315f9ec8555aa6f91531425c817683f054fc45f))\n\n### Miscellaneous Chores\n\n* add funding field ([#13585](https://github.com/vitejs/vite/issues/13585)) ([2501627](https://github.com/vitejs/vite/commit/250162775031a8798f67e8be71fd226a79c9831b))\n* **deps:** update all non-major dependencies ([#13553](https://github.com/vitejs/vite/issues/13553)) ([3ea0534](https://github.com/vitejs/vite/commit/3ea05342d41277baf11a73763f082e6e75c46a8f))\n* **deps:** update all non-major dependencies ([#13633](https://github.com/vitejs/vite/issues/13633)) ([c72fb9b](https://github.com/vitejs/vite/commit/c72fb9b91a277cc79862e65bb1138a44bc339813))\n* **deps:** update dependency @tsconfig/svelte to v5 ([#13702](https://github.com/vitejs/vite/issues/13702)) ([70f0659](https://github.com/vitejs/vite/commit/70f0659a51c18bf764ba8f5b981444e15aa468e3))\n\n## <small>[4.3.2](https://github.com/vitejs/vite/compare/create-vite@4.3.1...create-vite@4.3.2) (2023-05-29)</small>\n### Bug Fixes\n\n* **create-vite:** use `\"target\": \"ES2020\"` in React template ([#13147](https://github.com/vitejs/vite/issues/13147)) ([23096b1](https://github.com/vitejs/vite/commit/23096b19998978803c132021eee175153fa6078d))\n* upgrade svelte-check preventing unmet peer deps errors ([#13103](https://github.com/vitejs/vite/issues/13103)) ([c63ba3f](https://github.com/vitejs/vite/commit/c63ba3fa08a64d75bfffa6885dc4c44875b9c5ba))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#12805](https://github.com/vitejs/vite/issues/12805)) ([5731ac9](https://github.com/vitejs/vite/commit/5731ac9caaef629e892e20394f0cc73c565d9a87))\n\n## <small>[4.3.1](https://github.com/vitejs/vite/compare/create-vite@4.3.0...create-vite@4.3.1) (2023-04-25)</small>\n### Bug Fixes\n\n* **create-vite:** fix h1 css selector in lit templates ([#12951](https://github.com/vitejs/vite/issues/12951)) ([21c61cb](https://github.com/vitejs/vite/commit/21c61cbbbe1add738f3fc4e8e80de2c73b1fc5a8))\n\n### Miscellaneous Chores\n\n* **create-vite:** bump vue-tsc ([#12952](https://github.com/vitejs/vite/issues/12952)) ([30fd101](https://github.com/vitejs/vite/commit/30fd101aa170e06d89a938e657bd4af7da6ee17e))\n* **create-vite:** update to plugin-react 4.0.0 ([14cd939](https://github.com/vitejs/vite/commit/14cd93979265700677bcc8322ff729a33bebe514))\n\n## [4.3.0](https://github.com/vitejs/vite/compare/create-vite@4.3.0-beta.0...create-vite@4.3.0) (2023-04-20)\n### Features\n\n* **create-vite:** add eslint to React templates ([#12801](https://github.com/vitejs/vite/issues/12801)) ([d84460a](https://github.com/vitejs/vite/commit/d84460a5fcc553d71ce1d4962d22ab53419d2b10))\n* **create-vite:** move TypeScript ones up ([#12057](https://github.com/vitejs/vite/issues/12057)) ([313712d](https://github.com/vitejs/vite/commit/313712d28893c1e2405f4c2937033873e4c38d7b))\n\n### Bug Fixes\n\n* **create-vite:** update template-lit-ts tsconfig (fix [#12854](https://github.com/vitejs/vite/issues/12854)) ([#12855](https://github.com/vitejs/vite/issues/12855)) ([c186815](https://github.com/vitejs/vite/commit/c186815e38f1e0f9fb8195456eb41ffec07d3c80))\n\n### Documentation\n\n* update link to svelte-hmr ([#12893](https://github.com/vitejs/vite/issues/12893)) ([2ddeead](https://github.com/vitejs/vite/commit/2ddeead7beabbc1c6dd292dcb1f728a0bdd8ad63))\n\n### Miscellaneous Chores\n\n* **create-vite:** remove unnecessary App class Reference ([#12771](https://github.com/vitejs/vite/issues/12771)) ([1607f4a](https://github.com/vitejs/vite/commit/1607f4ac10715a60a32a1a6029a4fea9eaa33b14))\n* **create-vite:** remove wrapper div for react template ([#12867](https://github.com/vitejs/vite/issues/12867)) ([3679bd7](https://github.com/vitejs/vite/commit/3679bd757f1b24d40f7c66ace14167b97f8093cc))\n* **deps:** update dependency @tsconfig/svelte to v4 ([#12879](https://github.com/vitejs/vite/issues/12879)) ([79619a9](https://github.com/vitejs/vite/commit/79619a95ab5ecd848fb73583fa578851c374d27e))\n\n## [4.3.0-beta.0](https://github.com/vitejs/vite/compare/create-vite@4.2.0...create-vite@4.3.0-beta.0) (2023-04-06)\n### Features\n\n* **create-vite:** lit templates will create application instead of library ([#12459](https://github.com/vitejs/vite/issues/12459)) ([8186b9b](https://github.com/vitejs/vite/commit/8186b9b2b0734544ec37412de7ec2606ba8b1359))\n* **create-vite:** stricter TS configs in templates ([#12604](https://github.com/vitejs/vite/issues/12604)) ([4ffaeee](https://github.com/vitejs/vite/commit/4ffaeee2033531788bc6d4d2541b8b5e44352591))\n* **create-vite:** use typescript 5.0 in templates ([#12481](https://github.com/vitejs/vite/issues/12481)) ([8582e2d](https://github.com/vitejs/vite/commit/8582e2dcfbfa3cd6bf72a305adcba40bbe8d0570))\n\n### Bug Fixes\n\n* **create-vite:** skip lib check in tsconfig templates ([#12591](https://github.com/vitejs/vite/issues/12591)) ([a59914c](https://github.com/vitejs/vite/commit/a59914c71d28a89f5b71b836d8d278d2ed43d2c3))\n* **create-vite:** updated js & ts templates with new react docs link ([#12479](https://github.com/vitejs/vite/issues/12479)) ([c327006](https://github.com/vitejs/vite/commit/c3270069d91e44f498c81674dfb00a9392fce7ee))\n* **deps:** update all non-major dependencies ([#12389](https://github.com/vitejs/vite/issues/12389)) ([3e60b77](https://github.com/vitejs/vite/commit/3e60b778b0ed178a83f674031f5edb123e6c123c))\n\n### Miscellaneous Chores\n\n* **create-vite:** revert to vite 4.2 ([#12456](https://github.com/vitejs/vite/issues/12456)) ([535c8c5](https://github.com/vitejs/vite/commit/535c8c5ca4afdc7b3507c860aedb2a257f97f95a))\n* **create-vite:** rollback to vite 4.1 due to npm publish outage ([d8cb765](https://github.com/vitejs/vite/commit/d8cb765a52598778352dfbc428ace4a306ccbcdb))\n* **create-vite:** update to vite 4.3 beta ([9b0df5d](https://github.com/vitejs/vite/commit/9b0df5d55f677dd0c9b180ebd8e3f29c30d7a592))\n* use @vitejs/release-scripts ([#12682](https://github.com/vitejs/vite/issues/12682)) ([9c37cc1](https://github.com/vitejs/vite/commit/9c37cc1148737458d0580353e37f1e746f766eae))\n\n## [4.2.0](https://github.com/vitejs/vite/compare/create-vite@4.2.0-beta.1...create-vite@4.2.0) (2023-03-16)\n### Features\n\n* **create-vite:** support create-electron-vite ([#12390](https://github.com/vitejs/vite/issues/12390)) ([708133e](https://github.com/vitejs/vite/commit/708133e8453ded99d18886087807139977166c9d))\n\n### Bug Fixes\n\n* **create-vite:** fix broken vite logo when base changed ([#12374](https://github.com/vitejs/vite/issues/12374)) ([2b472d1](https://github.com/vitejs/vite/commit/2b472d1ea0fb1a9fea33e2b5ad71c0a22bcd56d0))\n\n### Styles\n\n* **create-vite:** use quotes for attributes consistently ([#12383](https://github.com/vitejs/vite/issues/12383)) ([46c5f46](https://github.com/vitejs/vite/commit/46c5f469edf0315934222c88fba4ddda87c85adc))\n\n### Miscellaneous Chores\n\n* **create-vite:** update plugin-vue ([e06cda9](https://github.com/vitejs/vite/commit/e06cda970cdb3773c75aecfc12e6fe2151156966))\n* **deps:** update all non-major dependencies ([#12299](https://github.com/vitejs/vite/issues/12299)) ([b41336e](https://github.com/vitejs/vite/commit/b41336e450b093fb3e454806ec4245ebad7ba9c5))\n\n## [4.2.0-beta.1](https://github.com/vitejs/vite/compare/create-vite@4.2.0-beta.0...create-vite@4.2.0-beta.1) (2023-03-07)\n### Miscellaneous Chores\n\n* **create-vite:** update to beta deps ([5ffcaa0](https://github.com/vitejs/vite/commit/5ffcaa00b1dfd2281988e29506ea801d7ac57e8f))\n\n## [4.2.0-beta.0](https://github.com/vitejs/vite/compare/create-vite@4.1.0...create-vite@4.2.0-beta.0) (2023-03-07)\n### Bug Fixes\n\n* **create-vite:** add final newline for package.json ([#11906](https://github.com/vitejs/vite/issues/11906)) ([e033e49](https://github.com/vitejs/vite/commit/e033e492d491d25790baf475023a828eda6d4d9a))\n* **deps:** update all non-major dependencies ([#12036](https://github.com/vitejs/vite/issues/12036)) ([48150f2](https://github.com/vitejs/vite/commit/48150f2ea4d7ff8e3b67f15239ae05f5be317436))\n\n### Miscellaneous Chores\n\n* **create-vite:** update volar link in helloworld components ([#12145](https://github.com/vitejs/vite/issues/12145)) ([7110ddf](https://github.com/vitejs/vite/commit/7110ddf39b3b6f122945bbbc5025773c64f9d948))\n\n## [4.1.0](https://github.com/vitejs/vite/compare/create-vite@4.1.0-beta.0...create-vite@4.1.0) (2023-02-02)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#11846](https://github.com/vitejs/vite/issues/11846)) ([5d55083](https://github.com/vitejs/vite/commit/5d5508311f9856de69babd72dc4de0e7c21c7ae8))\n* two folders are created when the project name contains spaces ([#11630](https://github.com/vitejs/vite/issues/11630)) ([758fc6c](https://github.com/vitejs/vite/commit/758fc6c0b5b7e98e73007172abe3d6b28b24a4be))\n\n### Miscellaneous Chores\n\n* **create-vite:** update plugin-react to 3.1.0 ([8895629](https://github.com/vitejs/vite/commit/8895629f0067acb9f5072d3b7bed1d57da43be66))\n\n## [4.1.0-beta.0](https://github.com/vitejs/vite/compare/create-vite@4.0.0...create-vite@4.1.0-beta.0) (2023-01-26)\n### Features\n\n* **create-vite:** add preprocess to sveltejs template ([#11600](https://github.com/vitejs/vite/issues/11600)) ([529b0a6](https://github.com/vitejs/vite/commit/529b0a6f3cfe20b973a91722eba4adaf71224a48))\n\n### Bug Fixes\n\n* **create-vite:** update templates to use better font ([#11665](https://github.com/vitejs/vite/issues/11665)) ([a65d31b](https://github.com/vitejs/vite/commit/a65d31bbdfca43f76cf0e6212fef7841af8f148d))\n\n### Miscellaneous Chores\n\n* **create-vite:** added transition to grow back drop in ([#11392](https://github.com/vitejs/vite/issues/11392)) ([d0757e2](https://github.com/vitejs/vite/commit/d0757e29380c2086f50ef595d468b7f9f911acd0))\n* **deps:** update all non-major dependencies ([#11321](https://github.com/vitejs/vite/issues/11321)) ([dcc0004](https://github.com/vitejs/vite/commit/dcc0004ceb7a76e6d0cbae8b84a103a15f80049b))\n* **deps:** update all non-major dependencies ([#11419](https://github.com/vitejs/vite/issues/11419)) ([896475d](https://github.com/vitejs/vite/commit/896475dc6c7e5f1168e21d556201a61659552617))\n* **deps:** update all non-major dependencies ([#11701](https://github.com/vitejs/vite/issues/11701)) ([1d2ee63](https://github.com/vitejs/vite/commit/1d2ee6315365b33f84d9d8703fcd46307f6250e3))\n* **deps:** update all non-major dependencies ([#11787](https://github.com/vitejs/vite/issues/11787)) ([271394f](https://github.com/vitejs/vite/commit/271394fc7157a08b19f22d3751c8ec6e69f0bd5f))\n* typecheck create-vite ([#11295](https://github.com/vitejs/vite/issues/11295)) ([af86e5b](https://github.com/vitejs/vite/commit/af86e5bcfe4b78f486f499cba09c3270fb151d54))\n* update create-vite templates for beta testing ([7dbb24f](https://github.com/vitejs/vite/commit/7dbb24fd6b76d732e3b33287eccb50762c8312cd))\n* update plugin-react to 3.1.0-beta.0 ([#11820](https://github.com/vitejs/vite/issues/11820)) ([f0480a5](https://github.com/vitejs/vite/commit/f0480a5691241ee755eda4ed9d4c814ef4524377))\n\n### Tests\n\n* use default import for fs-extra ([#11543](https://github.com/vitejs/vite/issues/11543)) ([d3bed53](https://github.com/vitejs/vite/commit/d3bed53929cf4e3187137a4f4e9e1e4b3a2a5a95))\n\n## [4.0.0](https://github.com/vitejs/vite/compare/create-vite@4.0.0-beta.0...create-vite@4.0.0) (2022-12-09)\n### ⚠ BREAKING CHANGES\n\n* **svelte:** update svelte templates to vite-plugin-svelte 2.0.0 (#11279)\n\n### Features\n\n* **create-vite:** add react-swc templates ([#11280](https://github.com/vitejs/vite/issues/11280)) ([348146f](https://github.com/vitejs/vite/commit/348146f3e39232900eeb347d0922b97b5886bafa))\n* **svelte:** update svelte templates to vite-plugin-svelte 2.0.0 ([#11279](https://github.com/vitejs/vite/issues/11279)) ([2a558ef](https://github.com/vitejs/vite/commit/2a558efd2fa7de6c8c91b2bda2a0dea9de6658ae))\n\n### Bug Fixes\n\n* **create-vite:** update react-swc template name ([#11281](https://github.com/vitejs/vite/issues/11281)) ([b3b9ac5](https://github.com/vitejs/vite/commit/b3b9ac511f550d4635489f0609cd6efdde1f79b3))\n\n### Miscellaneous Chores\n\n* udpate vite and plugins to stable ([#11278](https://github.com/vitejs/vite/issues/11278)) ([026f41e](https://github.com/vitejs/vite/commit/026f41e87e6eb89491c88f62952d7a094f810811))\n\n## [4.0.0-beta.0](https://github.com/vitejs/vite/compare/create-vite@3.2.1...create-vite@4.0.0-beta.0) (2022-12-07)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#10804](https://github.com/vitejs/vite/issues/10804)) ([f686afa](https://github.com/vitejs/vite/commit/f686afa6d3bc0f501b936dcbc2c4552c865fa3f9))\n* **deps:** update all non-major dependencies ([#11091](https://github.com/vitejs/vite/issues/11091)) ([073a4bf](https://github.com/vitejs/vite/commit/073a4bfe2642a4dda2183a9dfecac864524893e1))\n\n### Performance Improvements\n\n* regexp perf issues, refactor regexp stylistic issues ([#10905](https://github.com/vitejs/vite/issues/10905)) ([fc007df](https://github.com/vitejs/vite/commit/fc007dfba2e0392bd29f7e6e2663ca910ed18a6b))\n\n### Miscellaneous Chores\n\n* **create-vite:** align vue template with create-vue ([#11128](https://github.com/vitejs/vite/issues/11128)) ([1a54e58](https://github.com/vitejs/vite/commit/1a54e58fbd55d89d4e8681d1e62eb5a76f4600e9))\n* **deps:** typescript 4.9 ([#11229](https://github.com/vitejs/vite/issues/11229)) ([6b4c4e2](https://github.com/vitejs/vite/commit/6b4c4e28bd1b125adb842e333813e8d57b7ee43d))\n* **deps:** update all non-major dependencies ([#10910](https://github.com/vitejs/vite/issues/10910)) ([f6ad607](https://github.com/vitejs/vite/commit/f6ad607d2430a44ea7dc71ecd3c44c1e8bf8446f))\n* **deps:** update all non-major dependencies ([#11006](https://github.com/vitejs/vite/issues/11006)) ([96f2e98](https://github.com/vitejs/vite/commit/96f2e98f6a196652962ccb5f2fa6195c050c463f))\n* **deps:** update all non-major dependencies ([#11182](https://github.com/vitejs/vite/issues/11182)) ([8b83089](https://github.com/vitejs/vite/commit/8b830899ef0ce4ebe257ed18222543f60b775832))\n* enable prettier trailing commas ([#11167](https://github.com/vitejs/vite/issues/11167)) ([134ce68](https://github.com/vitejs/vite/commit/134ce6817984bad0f5fb043481502531fee9b1db))\n* update create-vite to use beta versions ([#11244](https://github.com/vitejs/vite/issues/11244)) ([f7cfab9](https://github.com/vitejs/vite/commit/f7cfab95ee87a4a2377c5c57f506cc7464347d45))\n\n### Code Refactoring\n\n* move framework plugins out of core ([#11158](https://github.com/vitejs/vite/issues/11158)) ([5935619](https://github.com/vitejs/vite/commit/5935619d855951be50e4e9f1bcccaeda83aae432))\n\n## <small>[3.2.1](https://github.com/vitejs/vite/compare/create-vite@3.2.0...create-vite@3.2.1) (2022-11-07)</small>\n### Bug Fixes\n\n* **create-vite:** add `rel=\"noreferrer\"` to elements with `target=\"_blank\"` ([#10675](https://github.com/vitejs/vite/issues/10675)) ([e8eb67a](https://github.com/vitejs/vite/commit/e8eb67a6aed1408d43cc5c9176b3f697c0153f94))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#10725](https://github.com/vitejs/vite/issues/10725)) ([22cfad8](https://github.com/vitejs/vite/commit/22cfad87c824e717b6c616129f3b579be2e979b2))\n\n## [3.2.0](https://github.com/vitejs/vite/compare/create-vite@3.1.0...create-vite@3.2.0) (2022-10-26)\n### Features\n\n* **create-vite:** support create-vite-extra ([#10214](https://github.com/vitejs/vite/issues/10214)) ([8116cbd](https://github.com/vitejs/vite/commit/8116cbdf67d2e15e5520e8d408b453f825270727))\n* Switch to JSX runtime transform in preact-ts template ([#10061](https://github.com/vitejs/vite/issues/10061)) ([bf69063](https://github.com/vitejs/vite/commit/bf69063282c27d66bc5b9ad04feec288c0142a86))\n\n### Bug Fixes\n\n* **create-vite:** remove baseUrl from Svelte configs ([#10200](https://github.com/vitejs/vite/issues/10200)) ([9c7a331](https://github.com/vitejs/vite/commit/9c7a33156bc9a71ba1fd013732c0a798df5baa13))\n* **deps:** update all non-major dependencies ([#10077](https://github.com/vitejs/vite/issues/10077)) ([caf00c8](https://github.com/vitejs/vite/commit/caf00c8c7a5c81a92182116ffa344b34ce4c3b5e))\n* **deps:** update all non-major dependencies ([#10160](https://github.com/vitejs/vite/issues/10160)) ([6233c83](https://github.com/vitejs/vite/commit/6233c830201085d869fbbd2a7e622a59272e0f43))\n* **deps:** update all non-major dependencies ([#10316](https://github.com/vitejs/vite/issues/10316)) ([a38b450](https://github.com/vitejs/vite/commit/a38b450441eea02a680b80ac0624126ba6abe3f7))\n* **deps:** update all non-major dependencies ([#10610](https://github.com/vitejs/vite/issues/10610)) ([bb95467](https://github.com/vitejs/vite/commit/bb954672e3ee863e5cb37fa78167e5fc6df9ae4e))\n* **deps:** update all non-major dependencies ([#9985](https://github.com/vitejs/vite/issues/9985)) ([855f2f0](https://github.com/vitejs/vite/commit/855f2f077eb8dc41b395bccecb6a5b836eb526a9))\n\n### Miscellaneous Chores\n\n* **create-vite:** remove sourcemap, move --noEmit to tsconfig ([#10150](https://github.com/vitejs/vite/issues/10150)) ([414d2ef](https://github.com/vitejs/vite/commit/414d2ef6e53a8030be68388952f28e1b42d2bb8e))\n* **deps:** update all non-major dependencies ([#10393](https://github.com/vitejs/vite/issues/10393)) ([f519423](https://github.com/vitejs/vite/commit/f519423170fafeee9d58aeb2052cb3bc224f25f8))\n* **deps:** update all non-major dependencies ([#10488](https://github.com/vitejs/vite/issues/10488)) ([15aa827](https://github.com/vitejs/vite/commit/15aa827283d6cbf9f55c02d6d8a3fe43dbd792e4))\n* **deps:** update dependency vue-tsc to v1 ([#10547](https://github.com/vitejs/vite/issues/10547)) ([9d0e0af](https://github.com/vitejs/vite/commit/9d0e0af41ad21ceb6a94396965a90e613e476e7b))\n* remove duplicated logic in vanilla template ([#10145](https://github.com/vitejs/vite/issues/10145)) ([f29fef5](https://github.com/vitejs/vite/commit/f29fef5dc3f87ccc5d430e177bbc0671e9d56679))\n\n## [3.1.0](https://github.com/vitejs/vite/compare/create-vite@3.0.2...create-vite@3.1.0) (2022-09-05)\n### Features\n\n* **create-vite:** add support for custom init commands (`create-vue`, Nuxt, and SvelteKit) ([#9406](https://github.com/vitejs/vite/issues/9406)) ([1673f3d](https://github.com/vitejs/vite/commit/1673f3daa0147b2afa546648ec913837402fec21))\n* skip `.git` when emptying dir ([#9659](https://github.com/vitejs/vite/issues/9659)) ([07fe65e](https://github.com/vitejs/vite/commit/07fe65e33a014e54ce331fb5192aa7c7585eebfa))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#9888](https://github.com/vitejs/vite/issues/9888)) ([e35a58b](https://github.com/vitejs/vite/commit/e35a58ba46f906feea8ab46886c3306257c61560))\n\n### Performance Improvements\n\n* bundle create-vite ([#9034](https://github.com/vitejs/vite/issues/9034)) ([37ac91e](https://github.com/vitejs/vite/commit/37ac91e5f680aea56ce5ca15ce1291adc3cbe05e))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#9675](https://github.com/vitejs/vite/issues/9675)) ([4e56e87](https://github.com/vitejs/vite/commit/4e56e87623501109198e019ebe809872528ab088))\n* **deps:** update all non-major dependencies ([#9778](https://github.com/vitejs/vite/issues/9778)) ([aceaefc](https://github.com/vitejs/vite/commit/aceaefc19eaa05c76b8a7adec035a0e4b33694c6))\n\n### Code Refactoring\n\n* **create-vite:** migrate to TypeScript ([#9941](https://github.com/vitejs/vite/issues/9941)) ([85fa2c8](https://github.com/vitejs/vite/commit/85fa2c89f35ecdda4ec5ed52ea50110337d98822))\n\n### Tests\n\n* **cli:** remove unnecessary generics usage ([#9859](https://github.com/vitejs/vite/issues/9859)) ([45d6797](https://github.com/vitejs/vite/commit/45d6797d9e573fe572dfd6d1c337c8c21f4c29a4))\n\n## <small>[3.0.2](https://github.com/vitejs/vite/compare/create-vite@3.0.1...create-vite@3.0.2) (2022-08-12)</small>\n## <small>[3.0.1](https://github.com/vitejs/vite/compare/create-vite@3.0.0...create-vite@3.0.1) (2022-08-11)</small>\n### Bug Fixes\n\n* **create-vite:** update vanilla-ts brand color ([#9254](https://github.com/vitejs/vite/issues/9254)) ([bff3abb](https://github.com/vitejs/vite/commit/bff3abbc9a6ebe8dabd2398666de42ae8e13f2dc))\n* **deps:** update all non-major dependencies ([#9176](https://github.com/vitejs/vite/issues/9176)) ([31d3b70](https://github.com/vitejs/vite/commit/31d3b70672ea8759a8d7ff1993d64bb4f0e30fab))\n* **deps:** update all non-major dependencies ([#9575](https://github.com/vitejs/vite/issues/9575)) ([8071325](https://github.com/vitejs/vite/commit/80713256d0dd5716e42086fb617e96e9e92c3675))\n* mention that Node.js 13/15 support is dropped (fixes [#9113](https://github.com/vitejs/vite/issues/9113)) ([#9116](https://github.com/vitejs/vite/issues/9116)) ([2826303](https://github.com/vitejs/vite/commit/2826303bd253e20df2746f84f6a7c06cb5cf3d6b))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#9347](https://github.com/vitejs/vite/issues/9347)) ([2fcb027](https://github.com/vitejs/vite/commit/2fcb0272442664c395322acfc7899ab6a32bd86c))\n* **deps:** update all non-major dependencies ([#9478](https://github.com/vitejs/vite/issues/9478)) ([c530d16](https://github.com/vitejs/vite/commit/c530d168309557c7a254128364f07f7b4f017e14))\n* remove unused `favicon.svg` ([#9181](https://github.com/vitejs/vite/issues/9181)) ([33b5b0d](https://github.com/vitejs/vite/commit/33b5b0d0231f4ce0f40c799965f9352ae062eff3))\n* tidy up eslint config ([#9468](https://github.com/vitejs/vite/issues/9468)) ([f4addcf](https://github.com/vitejs/vite/commit/f4addcfc24b1668b906411ff8f8fc394ce5c3643))\n\n## [3.0.0](https://github.com/vitejs/vite/compare/create-vite@2.9.3...create-vite@3.0.0) (2022-07-13)\n### ⚠ BREAKING CHANGES\n\n* bump targets (#8045)\n* remove node v12 support (#7833)\n\n### Features\n\n* bump minimum node version to 14.18.0 ([#8662](https://github.com/vitejs/vite/issues/8662)) ([8a05432](https://github.com/vitejs/vite/commit/8a05432e6dcc0e11d78c7b029e7340fa47fceb92))\n* **create-vite:** add `type: module` to all templates ([#8251](https://github.com/vitejs/vite/issues/8251)) ([c3ec60c](https://github.com/vitejs/vite/commit/c3ec60c4eca39d5641141ed0d1812f37e047a2e6))\n* **create-vite:** align template styles with docs ([#8478](https://github.com/vitejs/vite/issues/8478)) ([d72b3dd](https://github.com/vitejs/vite/commit/d72b3ddacd7fee209234dc1dd4081ce90f10d091))\n* **create-vite:** migrate to ESM ([#8253](https://github.com/vitejs/vite/issues/8253)) ([49478ae](https://github.com/vitejs/vite/commit/49478ae7c2ea9f9fe197021bed4a2f9f0f9c7b1e))\n* **create-vite:** supports nested directory (closes [#6638](https://github.com/vitejs/vite/issues/6638)) ([#6739](https://github.com/vitejs/vite/issues/6739)) ([6ccf9aa](https://github.com/vitejs/vite/commit/6ccf9aab1d2c89d05dce97051a2eca71b5d1145b))\n* **create-vite:** use framework brand glow color ([#8539](https://github.com/vitejs/vite/issues/8539)) ([3a21a5e](https://github.com/vitejs/vite/commit/3a21a5e39b47120e5139269138eae0e2ca2efcd4))\n\n### Bug Fixes\n\n* **create-vite:** allow slash at the end of project path ([#6897](https://github.com/vitejs/vite/issues/6897)) ([8167db3](https://github.com/vitejs/vite/commit/8167db32ec44047b006a93a7969028101f5d9276))\n* **create-vite:** remove import from public ([#9074](https://github.com/vitejs/vite/issues/9074)) ([880f560](https://github.com/vitejs/vite/commit/880f5608b435a32a5c5b4554c8ef929c24149007))\n* **deps:** update all non-major dependencies ([#8281](https://github.com/vitejs/vite/issues/8281)) ([c68db4d](https://github.com/vitejs/vite/commit/c68db4d7ad2c1baee41f280b34ae89a85ba0373d))\n* **deps:** update all non-major dependencies ([#8391](https://github.com/vitejs/vite/issues/8391)) ([842f995](https://github.com/vitejs/vite/commit/842f995ca69600c4c06c46d202fe713b80373418))\n* **deps:** update all non-major dependencies ([#8558](https://github.com/vitejs/vite/issues/8558)) ([9a1fd4c](https://github.com/vitejs/vite/commit/9a1fd4ccf8986dd92b85563e7304b2591f782365))\n* **deps:** update all non-major dependencies ([#8802](https://github.com/vitejs/vite/issues/8802)) ([a4a634d](https://github.com/vitejs/vite/commit/a4a634d6a08f8b54f052cfc2cc1b60c1bca6d48a))\n* **lib:** use proper extension ([#6827](https://github.com/vitejs/vite/issues/6827)) ([34df307](https://github.com/vitejs/vite/commit/34df3075fce5bf71f4f69335bb6811731b1cadb0))\n* template-react-ts warning when importing path in vite.config.ts ([#8924](https://github.com/vitejs/vite/issues/8924)) ([0e6b82e](https://github.com/vitejs/vite/commit/0e6b82ea130963ff60f419e3f352ec7702bea22e))\n* use Vitest for unit testing, clean regex bug ([#8040](https://github.com/vitejs/vite/issues/8040)) ([63cd53d](https://github.com/vitejs/vite/commit/63cd53d2480e40db717aff78966240eb6482aba4))\n\n### Documentation\n\n* correct pnpm command ([#8763](https://github.com/vitejs/vite/issues/8763)) ([8108b1b](https://github.com/vitejs/vite/commit/8108b1ba1f954241d3bdd18bbc70905aa2dc95f3))\n\n### Miscellaneous Chores\n\n* bump minors and rebuild lock ([#8074](https://github.com/vitejs/vite/issues/8074)) ([aeb5b74](https://github.com/vitejs/vite/commit/aeb5b7436df5a4d7cf0ee1a9f6f110d00ef7aac1))\n* cleanup now that we've dropped Node 12 ([#8239](https://github.com/vitejs/vite/issues/8239)) ([29659a0](https://github.com/vitejs/vite/commit/29659a0cbb58e3d7a7fcb951ee50dd64ce24be49))\n* **create-vite:** add current directory description ([#8501](https://github.com/vitejs/vite/issues/8501)) ([8d08220](https://github.com/vitejs/vite/commit/8d082204cb9b7f7412f328ea7670e76738cce44a))\n* **create-vite:** react-ts non-null-assertion ([#7881](https://github.com/vitejs/vite/issues/7881)) ([771312b](https://github.com/vitejs/vite/commit/771312b9b3ae5d68eecbcf1c22f7ba08e8f9347c))\n* **create-vite:** update logo and header styles ([#8502](https://github.com/vitejs/vite/issues/8502)) ([1f1ca5e](https://github.com/vitejs/vite/commit/1f1ca5eb2a2493804f79562334bc8708dd246f0d))\n* **create-vite:** upgrade vite-plugin-svelte ([#9076](https://github.com/vitejs/vite/issues/9076)) ([acaf9e0](https://github.com/vitejs/vite/commit/acaf9e04cee054ec82b5236696e6c749a44745d6))\n* **create-vite:** use Type assertion in preact-ts ([#8579](https://github.com/vitejs/vite/issues/8579)) ([d1ba059](https://github.com/vitejs/vite/commit/d1ba0590a43f3c25a25522b1b2c9bf51a17fbde4))\n* **deps:** update all non-major dependencies ([#8474](https://github.com/vitejs/vite/issues/8474)) ([6d0ede7](https://github.com/vitejs/vite/commit/6d0ede7c60aaa4c010207a047bf30a2b87b5049f))\n* **deps:** update all non-major dependencies ([#8669](https://github.com/vitejs/vite/issues/8669)) ([628863d](https://github.com/vitejs/vite/commit/628863dc6120804cc1af8bda2ea98e802ded0e84))\n* **deps:** update all non-major dependencies ([#8905](https://github.com/vitejs/vite/issues/8905)) ([4a24c17](https://github.com/vitejs/vite/commit/4a24c17772bdbbc6077fae08b536bdb089eeefe1))\n* **deps:** update all non-major dependencies ([#9022](https://github.com/vitejs/vite/issues/9022)) ([6342140](https://github.com/vitejs/vite/commit/6342140e6ac7e033ca83d3494f94ea20ca2eaf07))\n* **deps:** update dependency @tsconfig/svelte to v3 ([#8282](https://github.com/vitejs/vite/issues/8282)) ([015ebed](https://github.com/vitejs/vite/commit/015ebed220011b9e12d63906cea315a77a31c8d7))\n* enable ESLint for `__tests__` dir ([#8370](https://github.com/vitejs/vite/issues/8370)) ([cd21abf](https://github.com/vitejs/vite/commit/cd21abfb636ce4c6dd1507f134f1ee9bb67f6717))\n* update major deps ([#8572](https://github.com/vitejs/vite/issues/8572)) ([0e20949](https://github.com/vitejs/vite/commit/0e20949dbf0ba38bdaefbf32a36764fe29858e20))\n* use node prefix ([#8309](https://github.com/vitejs/vite/issues/8309)) ([60721ac](https://github.com/vitejs/vite/commit/60721ac53a1bf326d1cac097f23642faede234ff))\n* use vite-env.d.ts convention ([#8988](https://github.com/vitejs/vite/issues/8988)) ([cf23963](https://github.com/vitejs/vite/commit/cf23963b50eafe5504cb16e97b161fa6cc4ebabe))\n\n### Build System\n\n* bump targets ([#8045](https://github.com/vitejs/vite/issues/8045)) ([66efd69](https://github.com/vitejs/vite/commit/66efd69a399fd73284cc7a3bffc904e154291a14))\n* remove node v12 support ([#7833](https://github.com/vitejs/vite/issues/7833)) ([eeac2d2](https://github.com/vitejs/vite/commit/eeac2d2e217ddbca79d5b1dfde9bb5097e821b6a))\n\n## <small>[2.9.3](https://github.com/vitejs/vite/compare/create-vite@2.9.2...create-vite@2.9.3) (2022-05-02)</small>\n### Features\n\n* **create-vite:** scaffold directory with only .git ([#7971](https://github.com/vitejs/vite/issues/7971)) ([a5bdb9f](https://github.com/vitejs/vite/commit/a5bdb9fa706850c45134c25b77aea2dee1ea03d4))\n\n### Miscellaneous Chores\n\n* **create-vite:** update reference to volar vscode extension ([#7994](https://github.com/vitejs/vite/issues/7994)) ([2b6d8fe](https://github.com/vitejs/vite/commit/2b6d8fec25961b34e2bfcf776be0fb4e499b4cf9))\n\n## <small>[2.9.2](https://github.com/vitejs/vite/compare/create-vite@2.9.1...create-vite@2.9.2) (2022-04-19)</small>\n### Bug Fixes\n\n* **create-vite:** bump `vue-tsc` to `0.34.7` ([#7760](https://github.com/vitejs/vite/issues/7760)) ([9a93233](https://github.com/vitejs/vite/commit/9a932339aae8bfbb9f3b522706c551a21a1eea3a))\n* **create-vite:** set skipLibCheck true ([#7726](https://github.com/vitejs/vite/issues/7726)) ([54e9cdd](https://github.com/vitejs/vite/commit/54e9cdd9f913ba7b650bce6657b5ff666dd0b5a8))\n\n### Miscellaneous Chores\n\n* remove useless code in preact template ([#7789](https://github.com/vitejs/vite/issues/7789)) ([e5729be](https://github.com/vitejs/vite/commit/e5729bee1e3f0753dc3514757fa15e5533c387fe))\n\n## <small>[2.9.1](https://github.com/vitejs/vite/compare/create-vite@2.9.0...create-vite@2.9.1) (2022-04-13)</small>\n### Miscellaneous Chores\n\n* **create-vite-app:** upgrade react to 18 ([#7597](https://github.com/vitejs/vite/issues/7597)) ([8b21029](https://github.com/vitejs/vite/commit/8b21029f9dcd1a63e8b58f3d54cef12c53ebef53))\n* **create-vite:** add isolatedModules ([#7697](https://github.com/vitejs/vite/issues/7697)) ([8f28350](https://github.com/vitejs/vite/commit/8f28350291dde55e9d20b05f124b53867bcaf8e9))\n* fix term cases ([#7553](https://github.com/vitejs/vite/issues/7553)) ([c296130](https://github.com/vitejs/vite/commit/c29613013ca1c6d9c77b97e2253ed1f07e40a544))\n* update @types/react version ([#7655](https://github.com/vitejs/vite/issues/7655)) ([eb57627](https://github.com/vitejs/vite/commit/eb57627a368a5ae0532b5836c176647525d5394f))\n* update vue template setup api doc url ([#7628](https://github.com/vitejs/vite/issues/7628)) ([4433df4](https://github.com/vitejs/vite/commit/4433df4c6b278d5a2f4d2ca14f0a7930ed647e80))\n\n## [2.9.0](https://github.com/vitejs/vite/compare/create-vite@2.8.0...create-vite@2.9.0) (2022-03-30)\n### Documentation\n\n* **vue-ts:** update note on vue type support in ts ([#6165](https://github.com/vitejs/vite/issues/6165)) ([cfc7648](https://github.com/vitejs/vite/commit/cfc76482269b2f2c9f44404e901b208b9c8b7331))\n\n### Miscellaneous Chores\n\n* add isolatedModules to create-vite > template-vue-ts > tsconfig ([#7304](https://github.com/vitejs/vite/issues/7304)) ([21990ea](https://github.com/vitejs/vite/commit/21990ea394e3c82ca716cb6b55d2f5ca3bec646c))\n* **deps:** update all non-major dependencies ([#7490](https://github.com/vitejs/vite/issues/7490)) ([42c15f6](https://github.com/vitejs/vite/commit/42c15f6bad06f98962bc058c69a9f1e1a0f23440))\n\n## [2.8.0](https://github.com/vitejs/vite/compare/create-vite@2.7.2...create-vite@2.8.0) (2022-02-09)\n### Features\n\n* **create-vite:** tsconfig support vite.config.ts ([#6324](https://github.com/vitejs/vite/issues/6324)) ([bfbdb22](https://github.com/vitejs/vite/commit/bfbdb2242e57cfba0309a88475a1f9cf2a50413f))\n\n### Bug Fixes\n\n* **create-vite:** use `reset` for prompts for white bg color shell ([#6131](https://github.com/vitejs/vite/issues/6131)) ([dd3bbb8](https://github.com/vitejs/vite/commit/dd3bbb8e21aff812ec482f760e1abceb6bd67aef))\n\n### Documentation\n\n* align npm commands to other pms (create and add) ([#6550](https://github.com/vitejs/vite/issues/6550)) ([e6b06e5](https://github.com/vitejs/vite/commit/e6b06e535fb26e064f5c341703df4bcb30aa6432))\n* update node version note ([#6177](https://github.com/vitejs/vite/issues/6177)) ([10e8f85](https://github.com/vitejs/vite/commit/10e8f857d320cfbb2f0375dac03911484cbc0b33))\n\n### Miscellaneous Chores\n\n* convert scripts to TS ([#6160](https://github.com/vitejs/vite/issues/6160)) ([15b6f1b](https://github.com/vitejs/vite/commit/15b6f1ba82731c16b19e00ca3b28b1a898caa4d4))\n* **create-vite:** add more gitignore ([#6247](https://github.com/vitejs/vite/issues/6247)) ([64b1595](https://github.com/vitejs/vite/commit/64b1595030be0500b1fbc31ec8e51d34951c6c11))\n* **deps:** update all non-major dependencies ([#6185](https://github.com/vitejs/vite/issues/6185)) ([b45f4ad](https://github.com/vitejs/vite/commit/b45f4ad9f1336d1e88d271d7aca9498dde2e5013))\n* ensure local package private ([#6785](https://github.com/vitejs/vite/issues/6785)) ([487c1d1](https://github.com/vitejs/vite/commit/487c1d1236a7459f5b2e1d1af049d9e085b1e5ee))\n* prefer type imports ([#5835](https://github.com/vitejs/vite/issues/5835)) ([7186857](https://github.com/vitejs/vite/commit/71868579058512b51991718655e089a78b99d39c))\n\n## <small>[2.7.2](https://github.com/vitejs/vite/compare/create-vite@2.7.1...create-vite@2.7.2) (2021-12-13)</small>\n## <small>[2.7.1](https://github.com/vitejs/vite/compare/create-vite@2.7.0...create-vite@2.7.1) (2021-12-12)</small>\n### Miscellaneous Chores\n\n* bump vue version ([5e60562](https://github.com/vitejs/vite/commit/5e60562254e47d2ad0aaa246d3c5016e498d98bf))\n* update create-vite templates ([cdebb49](https://github.com/vitejs/vite/commit/cdebb49c558864cb09019dd3e62a2f5335a05ee8))\n\n## [2.7.0](https://github.com/vitejs/vite/compare/create-vite@2.6.6...create-vite@2.7.0) (2021-12-07)\n### Bug Fixes\n\n* **create-vite:** update vue-tsc for dts flags ([#5453](https://github.com/vitejs/vite/issues/5453)) ([c93bc3d](https://github.com/vitejs/vite/commit/c93bc3df90b5c4e8e25ffd864ae53a3ae7559315))\n\n### Documentation\n\n* switch from pnpm dlx to pnpm create ([#5322](https://github.com/vitejs/vite/issues/5322)) ([9afc2e7](https://github.com/vitejs/vite/commit/9afc2e7c5d6e7289bf035e9ad3cbf5a7758a0732))\n\n### Miscellaneous Chores\n\n* bump vue version ([ecafa80](https://github.com/vitejs/vite/commit/ecafa8090b50131c34a9973f4f66db0c15aafa51))\n* **deps:** update create-vite ([#5461](https://github.com/vitejs/vite/issues/5461)) ([6e8a70f](https://github.com/vitejs/vite/commit/6e8a70fd3979334f6f8abe3fcd795437e887c9d5))\n* use cjs extension with scripts ([#5877](https://github.com/vitejs/vite/issues/5877)) ([775baba](https://github.com/vitejs/vite/commit/775babac40da546b01b8b8cbd7dff32b5cfcee6d))\n\n### Code Refactoring\n\n* normalize scripts and commands naming ([#5207](https://github.com/vitejs/vite/issues/5207)) ([22873a7](https://github.com/vitejs/vite/commit/22873a7d040a244935aca24823a484cb0cdc0876))\n\n## <small>[2.6.6](https://github.com/vitejs/vite/compare/create-vite@2.6.5...create-vite@2.6.6) (2021-10-07)</small>\n## <small>[2.6.5](https://github.com/vitejs/vite/compare/create-vite@2.6.4...create-vite@2.6.5) (2021-09-29)</small>\n### Features\n\n* **create-vite:** migrate lit-element to lit ([#5012](https://github.com/vitejs/vite/issues/5012)) ([d66ea0f](https://github.com/vitejs/vite/commit/d66ea0f420eb7926d927b64e40ecaf83d9388e63))\n\n## <small>[2.6.4](https://github.com/vitejs/vite/compare/create-vite@2.6.3...create-vite@2.6.4) (2021-09-22)</small>\n### Miscellaneous Chores\n\n* **create-vite:** use @vitejs/plugin-react ([#5030](https://github.com/vitejs/vite/issues/5030)) ([42a9ef2](https://github.com/vitejs/vite/commit/42a9ef269617318b68cd379f3a71eeee6f8d5e29))\n\n## <small>[2.6.3](https://github.com/vitejs/vite/compare/create-vite@2.6.2...create-vite@2.6.3) (2021-09-21)</small>\n### Features\n\n* **create-vite:** update vue templates ([a2be9c1](https://github.com/vitejs/vite/commit/a2be9c11fccb53ed60a33d72025c2d30635be1a7))\n\n### Bug Fixes\n\n* pnpm create-vite command documentation ([#4902](https://github.com/vitejs/vite/issues/4902)) ([3392a8a](https://github.com/vitejs/vite/commit/3392a8ad5618cc68b6898a327b6c8959de6f4992))\n\n### Miscellaneous Chores\n\n* **create-vite:** skip pre-releases when updating version ([9bc56ef](https://github.com/vitejs/vite/commit/9bc56efb21511a62f94a5c6a4937b09ad9c5c7fe))\n* format ([#4931](https://github.com/vitejs/vite/issues/4931)) ([e59997f](https://github.com/vitejs/vite/commit/e59997f79c8b450bdc9ab357d90f444dc0a99f50))\n\n## <small>[2.6.2](https://github.com/vitejs/vite/compare/create-vite@2.6.1...create-vite@2.6.2) (2021-09-07)</small>\n### Miscellaneous Chores\n\n* recommend volar vscode extension ([#4842](https://github.com/vitejs/vite/issues/4842)) ([5bc0ffc](https://github.com/vitejs/vite/commit/5bc0ffc125ffe105de73f4cf306e2b24f7ec644c))\n\n## <small>[2.6.1](https://github.com/vitejs/vite/compare/create-vite@2.5.4...create-vite@2.6.1) (2021-08-31)</small>\n### Features\n\n* **create-vite:** update vue templates ([87a9a70](https://github.com/vitejs/vite/commit/87a9a70f75991a8afb06a0b84f4eab43ca76fa89))\n* explicit set `useDefineForClassFields` in ts templates ([#4280](https://github.com/vitejs/vite/issues/4280)) ([fe74173](https://github.com/vitejs/vite/commit/fe74173f19b6e341114723a99043440abce27bd6))\n\n### Bug Fixes\n\n* **create-vite:** project name with only numbers as an argument ([#4606](https://github.com/vitejs/vite/issues/4606)) ([085a621](https://github.com/vitejs/vite/commit/085a6219ceb89052ac0a269e7ccda081e534a800))\n\n### Miscellaneous Chores\n\n* bump vue version (fix broken alias test case) ([a6c8fa3](https://github.com/vitejs/vite/commit/a6c8fa3b465d03475a4c372b17cf9f3153b73a84))\n* **create-vite:** bump versions ([12bca19](https://github.com/vitejs/vite/commit/12bca19530104240ca55cedb71cce6183ecd9c07))\n\n## <small>[2.5.4](https://github.com/vitejs/vite/compare/create-vite@2.5.3...create-vite@2.5.4) (2021-08-03)</small>\n### Bug Fixes\n\n* **create-vite:** distinguish pnpm pkgManager ([#4220](https://github.com/vitejs/vite/issues/4220)) ([c0a3dbf](https://github.com/vitejs/vite/commit/c0a3dbfa66266378f6f329f1981d5827b781fdbb))\n\n## <small>[2.5.3](https://github.com/vitejs/vite/compare/create-vite@2.5.2...create-vite@2.5.3) (2021-07-27)</small>\n### Miscellaneous Chores\n\n* **create-vite:** update version of vue-tsc ([#4390](https://github.com/vitejs/vite/issues/4390)) ([08471ef](https://github.com/vitejs/vite/commit/08471ef626b325572c823ea82c4e23e8c312798e))\n\n## <small>[2.5.2](https://github.com/vitejs/vite/compare/create-vite@2.5.1...create-vite@2.5.2) (2021-07-20)</small>\n### Bug Fixes\n\n* create-vite when targetDir is a valid packageName ([#4247](https://github.com/vitejs/vite/issues/4247)) ([02e244d](https://github.com/vitejs/vite/commit/02e244dce128e7ea054034f68a0e28edabec28a0))\n\n### Miscellaneous Chores\n\n* format ([#4233](https://github.com/vitejs/vite/issues/4233)) ([e519548](https://github.com/vitejs/vite/commit/e519548be0eb5ddb9cb43486174d9b0fb6eb4d05))\n* use eslint rule eqeqeq ([#4234](https://github.com/vitejs/vite/issues/4234)) ([732d60c](https://github.com/vitejs/vite/commit/732d60cc99c6ea4dfcf5fd625d36632a8dc6c078))\n\n## <small>[2.5.1](https://github.com/vitejs/vite/compare/create-vite@2.5.0...create-vite@2.5.1) (2021-07-12)</small>\n### Miscellaneous Chores\n\n* update create-vite commands ([#4216](https://github.com/vitejs/vite/issues/4216)) ([eb39853](https://github.com/vitejs/vite/commit/eb39853479d6dfd6bd0e63ad07a44e8614986866))\n\n# 2.5.0 (2021-07-12)\n\n* @vitejs/create-app has been moved to create-vite, so the command to scaffold a Vite app is now shorter and easier to remember.\n\nWith NPM:\n\n```bash\n$ npm init vite@latest\n```\n\nWith Yarn:\n\n```bash\n$ yarn create vite\n```\n\nWith PNPM:\n\n```bash\n$ pnpm dlx create-vite\n```\n\n\n## [2.4.5](https://github.com/vitejs/vite/compare/create-app@2.4.4...create-app@2.4.5) (2021-07-05)\n\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#3878](https://github.com/vitejs/vite/issues/3878)) ([a66a805](https://github.com/vitejs/vite/commit/a66a8053e9520d20bcf95fce870570c5195bcc91))\n\n\n\n## [2.4.4](https://github.com/vitejs/vite/compare/create-app@2.4.3...create-app@2.4.4) (2021-06-22)\n\n\n### Bug Fixes\n\n* **create-app:** svelte templates use type module (fixes [#3834](https://github.com/vitejs/vite/issues/3834)) ([#3835](https://github.com/vitejs/vite/issues/3835)) ([ddefe84](https://github.com/vitejs/vite/commit/ddefe8410efdb2104763b9d03fec0e42b9f7bf17))\n* **deps:** update all non-major dependencies ([#3791](https://github.com/vitejs/vite/issues/3791)) ([74d409e](https://github.com/vitejs/vite/commit/74d409eafca8d74ec4a6ece621ea2895bc1f2a32))\n\n\n\n## [2.4.3](https://github.com/vitejs/vite/compare/create-app@2.4.2...create-app@2.4.3) (2021-06-16)\n\n\n### Bug Fixes\n\n* **create-app:** improve prompt message ([#3769](https://github.com/vitejs/vite/issues/3769)) ([9703bcd](https://github.com/vitejs/vite/commit/9703bcd7e594769792779306f8f978dcc010d92f))\n* **create-app:** update svelte templates to use named export of vite-… ([#3760](https://github.com/vitejs/vite/issues/3760)) ([c69f836](https://github.com/vitejs/vite/commit/c69f83615292953d40f07b1178d1ed1d72abe695))\n\n\n\n## [2.4.2](https://github.com/vitejs/vite/compare/create-app@2.4.1...create-app@2.4.2) (2021-06-08)\n\n\n### Features\n\n* **create-app:** update svelte-ts template to use @tsconfig/svelte a… ([#3668](https://github.com/vitejs/vite/issues/3668)) ([5c3b668](https://github.com/vitejs/vite/commit/5c3b668250903ba9ed75db5c4bb7f548d5cb6105))\n\n\n\n## [2.4.1](https://github.com/vitejs/vite/compare/create-app@2.4.0...create-app@2.4.1) (2021-06-01)\n\n\n### Bug Fixes\n\n* **create-app:** handle invalid template ([#3615](https://github.com/vitejs/vite/issues/3615)) ([4578a8c](https://github.com/vitejs/vite/commit/4578a8cc2f0ab972d6dc6bdb9ac92d6fbbd6fb05))\n\n\n\n# [2.4.0](https://github.com/vitejs/vite/compare/create-app@2.3.2...create-app@2.4.0) (2021-06-01)\n\n\n\n## [2.3.2](https://github.com/vitejs/vite/compare/create-app@2.3.1...create-app@2.3.2) (2021-05-25)\n\n\n### Features\n\n* **create-app:** improve client types ([#3214](https://github.com/vitejs/vite/issues/3214)) ([ba8b7af](https://github.com/vitejs/vite/commit/ba8b7afa650277b7218e0bd53564b5fb45bf4549))\n\n\n\n## [2.3.1](https://github.com/vitejs/vite/compare/create-app@2.3.0...create-app@2.3.1) (2021-05-17)\n\n\n### Bug Fixes\n\n* **create-app:** lit-element templates package.json ([#3435](https://github.com/vitejs/vite/issues/3435)) ([74986d3](https://github.com/vitejs/vite/commit/74986d3d053aabe7ec3de20c987e9df309c684b2))\n\n\n\n# [2.3.0](https://github.com/vitejs/vite/compare/create-app@2.2.5...create-app@2.3.0) (2021-05-11)\n\n\n### Features\n\n* **create-app:** bump vite version to 2.3 ([f8315c9](https://github.com/vitejs/vite/commit/f8315c936dd07aa62c51b02f059a42aab103c9c1))\n\n\n\n## [2.2.5](https://github.com/vitejs/vite/compare/create-app@2.2.4...create-app@2.2.5) (2021-04-25)\n\n\n### Features\n\n* **create-app:** improve non-empty message for current dir ([#3117](https://github.com/vitejs/vite/issues/3117)) ([c0a0a84](https://github.com/vitejs/vite/commit/c0a0a8427e61dc0f5774056aebd038c69492294a))\n\n\n\n## [2.2.4](https://github.com/vitejs/vite/compare/create-app@2.2.3...create-app@2.2.4) (2021-04-15)\n\n\n### Bug Fixes\n\n* **create-app:** change index.html templates' favicon.svg href to absolute URL ([#2620](https://github.com/vitejs/vite/issues/2620)) ([3816f6e](https://github.com/vitejs/vite/commit/3816f6edb67e6bdf94db98e82e8acff4029bfe48))\n* **create-app:** the node in the svelte template is incorrectly mounted ([#2947](https://github.com/vitejs/vite/issues/2947)) ([0825f7e](https://github.com/vitejs/vite/commit/0825f7ee3574ae3f28f566da27835fbf3b210fac))\n\n\n### Features\n\n* **create-app:** add template vanilla-ts ([#2023](https://github.com/vitejs/vite/issues/2023)) ([89898d3](https://github.com/vitejs/vite/commit/89898d36cbe03bce9b6a7ab80a1c45de9989e56e))\n* **create-app:** two-level prompt for framework and variants ([#2941](https://github.com/vitejs/vite/issues/2941)) ([176e55d](https://github.com/vitejs/vite/commit/176e55dd1bf0232f483697d35b95f6e29a47fd74))\n\n\n\n## [2.2.3](https://github.com/vitejs/vite/compare/create-app@2.2.2...create-app@2.2.3) (2021-03-31)\n\n\n### Features\n\n* **create-app:** improved package name validation ([#2772](https://github.com/vitejs/vite/issues/2772)) ([9fa282e](https://github.com/vitejs/vite/commit/9fa282e9209185c70ac80e2fe1fbe4b7e92dae07))\n\n\n\n## [2.2.2](https://github.com/vitejs/vite/compare/create-app@2.2.1...create-app@2.2.2) (2021-03-25)\n\n\n\n## [2.2.1](https://github.com/vitejs/vite/compare/create-app@2.2.0...create-app@2.2.1) (2021-03-25)\n\n\n\n# [2.2.0](https://github.com/vitejs/vite/compare/create-app@2.1.0...create-app@2.2.0) (2021-03-16)\n\n\n### Features\n\n* **create-app:** add 'svelte' and 'svelte-ts' options ([#2537](https://github.com/vitejs/vite/issues/2537)) ([e441f23](https://github.com/vitejs/vite/commit/e441f23e187eec0834704949da492515cd25f8cd))\n\n\n\n# [2.1.0](https://github.com/vitejs/vite/compare/create-app@2.0.2...create-app@2.1.0) (2021-03-15)\n\n\n### Bug Fixes\n\n* **create-app:** ensure valid package name when creating project ([1dbf246](https://github.com/vitejs/vite/commit/1dbf24627d0fed4d6936f53fb84bc94b79372652)), closes [#2360](https://github.com/vitejs/vite/issues/2360)\n\n\n### Features\n\n* **create-app:** add `vue-tsc` for vue-ts template ([#2498](https://github.com/vitejs/vite/issues/2498)) ([b3b3c01](https://github.com/vitejs/vite/commit/b3b3c017d90ac86ba8d02deb93dec443a4fa4bad))\n\n\n\n## [2.0.2](https://github.com/vitejs/vite/compare/create-app@2.0.1...create-app@2.0.2) (2021-03-02)\n\n\n### Bug Fixes\n\n* **create-app:** add missing import meta types in preact ts template ([#2298](https://github.com/vitejs/vite/issues/2298)) ([ee86d2c](https://github.com/vitejs/vite/commit/ee86d2c3a7e967626da5e1d8ed104102df563980))\n* typo ([#2127](https://github.com/vitejs/vite/issues/2127)) ([ea95a1d](https://github.com/vitejs/vite/commit/ea95a1d44ab6f1a66701ae43c48f10b2047cb141))\n\n\n\n## [2.0.1](https://github.com/vitejs/vite/compare/create-app@2.0.0...create-app@2.0.1) (2021-02-20)\n\n\n### Bug Fixes\n\n* **create-app:** prompt the user on supplying an invalid template ([#2072](https://github.com/vitejs/vite/issues/2072)) ([ea31690](https://github.com/vitejs/vite/commit/ea31690580d4966b60e2aa8e14ae78dee955935f))\n* **create-app:** update prompt message based on user input ([#2103](https://github.com/vitejs/vite/issues/2103)) ([038f786](https://github.com/vitejs/vite/commit/038f78660042454935ef343bce240a5220328760))\n\n\n\n# [2.0.0](https://github.com/vitejs/vite/compare/create-app@1.8.0...create-app@2.0.0) (2021-02-16)\n\n\n### Features\n\n* **create-app:** bump to vite 2.0 ([81c72bb](https://github.com/vitejs/vite/commit/81c72bbdb112e3a6a48c026d4bc18410ec42a53a))\n\n\n\n# [1.8.0](https://github.com/vitejs/vite/compare/create-app@1.7.1...create-app@1.8.0) (2021-02-15)\n\n\n### Bug Fixes\n\n* **create-app:** add declaration tsconfig option ([7b3da03](https://github.com/vitejs/vite/commit/7b3da0320e9d43816e467d7ac8daef3fcdd1dc1e)), closes [#2010](https://github.com/vitejs/vite/issues/2010)\n\n\n### Features\n\n* **create-app:** closer parity on preact typescript template to preact template ([#1996](https://github.com/vitejs/vite/issues/1996)) ([c2622de](https://github.com/vitejs/vite/commit/c2622defe13a888f398df44d993cd40e0ee07f11))\n\n\n\n## [1.7.1](https://github.com/vitejs/vite/compare/create-app@1.7.0...create-app@1.7.1) (2021-02-12)\n\n\n### Bug Fixes\n\n* ensure intellisense for all create-app templates ([589b295](https://github.com/vitejs/vite/commit/589b29596e8046122b1ad8b69c4c70aa40cd4165))\n* **create-app:** Adds a newline before \"Scaffolding project in...\" ([#1945](https://github.com/vitejs/vite/issues/1945)) ([8a1c602](https://github.com/vitejs/vite/commit/8a1c602b29413b297c811577a9f6690bef88e01c))\n\n\n\n# [1.7.0](https://github.com/vitejs/vite/compare/create-app@1.6.0...create-app@1.7.0) (2021-02-08)\n\n\n### Features\n\n* **create-app:** add favicons for all templates that are missing one ([#1935](https://github.com/vitejs/vite/issues/1935)) ([3fa1d39](https://github.com/vitejs/vite/commit/3fa1d398080372bddc5dab0b4021ac1670a644b9))\n\n\n\n# [1.6.0](https://github.com/vitejs/vite/compare/create-app@1.5.2...create-app@1.6.0) (2021-02-05)\n\n\n### Bug Fixes\n\n* **create-app:** add resolveJsonModule to tsconfig.json for vue-ts template ([#1879](https://github.com/vitejs/vite/issues/1879)) ([2c914a5](https://github.com/vitejs/vite/commit/2c914a5b728d0c130f1e5b73c7b0ab0eedc1cda5))\n\n\n### Features\n\n* **create-app:** clearer vue-ts setup recommend ([#1896](https://github.com/vitejs/vite/issues/1896)) [skip ci] ([d6bf066](https://github.com/vitejs/vite/commit/d6bf066e3a18b749bed1a7fc622dd2551404e29f))\n\n\n\n## [1.5.2](https://github.com/vitejs/vite/compare/create-app@1.5.1...create-app@1.5.2) (2021-02-03)\n\n\n### Features\n\n* **create-app:** more detailed instructions for vue-ts template ([79dd32c](https://github.com/vitejs/vite/commit/79dd32cbb61b2aeedfd6b1081867a98cc7c73a68))\n\n\n\n## [1.5.1](https://github.com/vitejs/vite/compare/create-app@1.5.0...create-app@1.5.1) (2021-01-27)\n\n\n### Features\n\n* add link to config docs ([ce71d71](https://github.com/vitejs/vite/commit/ce71d71e83785a1072204bf8117a61ab7e4e772c))\n\n\n\n# [1.5.0](https://github.com/vitejs/vite/compare/create-app@1.4.0...create-app@1.5.0) (2021-01-25)\n\n\n### Features\n\n* bump vuedx versions ([fa1229a](https://github.com/vitejs/vite/commit/fa1229abc5602f14cf88470b7337e085164a989e))\n* lit-element templates ([830f3d3](https://github.com/vitejs/vite/commit/830f3d34f58cfa7680e1b2d753a023bcb1018ba2)), closes [#1684](https://github.com/vitejs/vite/issues/1684)\n\n\n\n# [1.4.0](https://github.com/vitejs/vite/compare/create-app@1.3.0...create-app@1.4.0) (2021-01-24)\n\n\n\n# [1.3.0](https://github.com/vitejs/vite/compare/create-app@1.1.0...create-app@1.3.0) (2021-01-23)\n\n\n### Features\n\n* add colors to create-app options ([cf7e43f](https://github.com/vitejs/vite/commit/cf7e43f8484e21ebd3efb3c86899eadb4f949848))\n\n\n\n# [1.2.0](https://github.com/vitejs/vite/compare/create-app@1.1.0...create-app@1.2.0) (2021-01-08)\n\n\n### Features\n\n* add colors to create-app options ([870f57a](https://github.com/vitejs/vite/commit/870f57a0a67b0ee854b67b40e2c7b9dad58b4004))\n\n\n\n# [1.1.0](https://github.com/vitejs/vite/compare/create-app@1.0.6...create-app@1.1.0) (2021-01-08)\n\n\n### Features\n\n* preact templates ([905cb65](https://github.com/vitejs/vite/commit/905cb65d3b766d584137e5fbb400764bd3156558))\n\n\n\n## [1.0.6](https://github.com/vitejs/vite/compare/create-app@1.0.5...create-app@1.0.6) (2021-01-05)\n\n\n### Code Refactoring\n\n* update client type usage ([245303c](https://github.com/vitejs/vite/commit/245303ca35ff2a40eca49e102b4f82cb1210f597))\n\n\n### BREAKING CHANGES\n\n* client types are now exposed under `vite/client.d.ts`.\nIt can now be included via the following `tsconfig.json`:\n\n    ```ts\n    {\n      \"compilerOptions\": {\n        \"types\": [\"vite/client\"]\n      }\n    }\n    ```\n\n\n\n## [1.0.5](https://github.com/vitejs/vite/compare/create-app@1.0.4...create-app@1.0.5) (2021-01-05)\n\n\n### Features\n\n* **create-app:** include env shim ([4802c1a](https://github.com/vitejs/vite/commit/4802c1a56ca79718881fae9466cbb836db8e9453))\n\n\n\n## [1.0.4](https://github.com/vitejs/vite/compare/create-app@1.0.3...create-app@1.0.4) (2021-01-04)\n\n\n### Bug Fixes\n\n* **create-app:** remove favicon link in vanilla template ([d9df7eb](https://github.com/vitejs/vite/commit/d9df7ebc48cd5c04c43830b14504ba391caf37c6)), closes [#1340](https://github.com/vitejs/vite/issues/1340)\n\n\n\n## [1.0.3](https://github.com/vitejs/vite/compare/create-app@1.0.2...create-app@1.0.3) (2021-01-02)\n\n\n### Bug Fixes\n\n* fix yarn create compat ([d135949](https://github.com/vitejs/vite/commit/d135949013ea0e572fe0a7b22bb9306644036c08))\n\n\n\n## [1.0.2](https://github.com/vitejs/vite/compare/create-app@1.0.1...create-app@1.0.2) (2021-01-02)\n\n\n\n## [1.0.1](https://github.com/vitejs/vite/compare/create-app@1.0.0...create-app@1.0.1) (2021-01-02)\n\n\n### Bug Fixes\n\n* include template in dist files ([8d0ddf9](https://github.com/vitejs/vite/commit/8d0ddf9f8bdf76b94e31358a3f03955fb4d4e247))\n\n\n\n# 1.0.0 (2021-01-02)\n\n\n### Features\n\n* create-app ([7785958](https://github.com/vitejs/vite/commit/7785958d28316464d2309981d9d0b0ac716da95e))\n* initial batch of templates ([2168ed0](https://github.com/vitejs/vite/commit/2168ed0f5019363d71956eabcce60bc31a36d30b))\n"
  },
  {
    "path": "packages/create-vite/LICENSE",
    "content": "# create-vite license\ncreate-vite is released under the MIT license:\n\nMIT License\n\nCopyright (c) 2019-present, VoidZero Inc. and Vite contributors\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\n# License of the files in the directories starting with \"template-\" in create-vite\nThe files in the directories starting with \"template-\" in create-vite and files\ngenerated from those files are licensed under the CC0 1.0 Universal license:\n\nCC0 1.0 Universal\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator and\nsubsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for the\npurpose of contributing to a commons of creative, cultural and scientific\nworks (\"Commons\") that the public can reliably and without fear of later\nclaims of infringement build upon, modify, incorporate in other works, reuse\nand redistribute as freely as possible in any form whatsoever and for any\npurposes, including without limitation commercial purposes. These owners may\ncontribute to the Commons to promote the ideal of a free culture and the\nfurther production of creative, cultural and scientific works, or to gain\nreputation or greater distribution for their Work in part through the use and\nefforts of others.\n\nFor these and/or other purposes and motivations, and without any expectation\nof additional consideration or compensation, the person associating CC0 with a\nWork (the \"Affirmer\"), to the extent that he or she is an owner of Copyright\nand Related Rights in the Work, voluntarily elects to apply CC0 to the Work\nand publicly distribute the Work under its terms, with knowledge of his or her\nCopyright and Related Rights in the Work and the meaning and intended legal\neffect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not limited\nto, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display, communicate,\n  and translate a Work;\n\n  ii. moral rights retained by the original author(s) and/or performer(s);\n\n  iii. publicity and privacy rights pertaining to a person's image or likeness\n  depicted in a Work;\n\n  iv. rights protecting against unfair competition in regards to a Work,\n  subject to the limitations in paragraph 4(a), below;\n\n  v. rights protecting the extraction, dissemination, use and reuse of data in\n  a Work;\n\n  vi. database rights (such as those arising under Directive 96/9/EC of the\n  European Parliament and of the Council of 11 March 1996 on the legal\n  protection of databases, and under any national implementation thereof,\n  including any amended or successor version of such directive); and\n\n  vii. other similar, equivalent or corresponding rights throughout the world\n  based on applicable law or treaty, and any national implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention of,\napplicable law, Affirmer hereby overtly, fully, permanently, irrevocably and\nunconditionally waives, abandons, and surrenders all of Affirmer's Copyright\nand Related Rights and associated claims and causes of action, whether now\nknown or unknown (including existing as well as future claims and causes of\naction), in the Work (i) in all territories worldwide, (ii) for the maximum\nduration provided by applicable law or treaty (including future time\nextensions), (iii) in any current or future medium and for any number of\ncopies, and (iv) for any purpose whatsoever, including without limitation\ncommercial, advertising or promotional purposes (the \"Waiver\"). Affirmer makes\nthe Waiver for the benefit of each member of the public at large and to the\ndetriment of Affirmer's heirs and successors, fully intending that such Waiver\nshall not be subject to revocation, rescission, cancellation, termination, or\nany other legal or equitable action to disrupt the quiet enjoyment of the Work\nby the public as contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason be\njudged legally invalid or ineffective under applicable law, then the Waiver\nshall be preserved to the maximum extent permitted taking into account\nAffirmer's express Statement of Purpose. In addition, to the extent the Waiver\nis so judged Affirmer hereby grants to each affected person a royalty-free,\nnon transferable, non sublicensable, non exclusive, irrevocable and\nunconditional license to exercise Affirmer's Copyright and Related Rights in\nthe Work (i) in all territories worldwide, (ii) for the maximum duration\nprovided by applicable law or treaty (including future time extensions), (iii)\nin any current or future medium and for any number of copies, and (iv) for any\npurpose whatsoever, including without limitation commercial, advertising or\npromotional purposes (the \"License\"). The License shall be deemed effective as\nof the date CC0 was applied by Affirmer to the Work. Should any part of the\nLicense for any reason be judged legally invalid or ineffective under\napplicable law, such partial invalidity or ineffectiveness shall not\ninvalidate the remainder of the License, and in such case Affirmer hereby\naffirms that he or she will not (i) exercise any of his or her remaining\nCopyright and Related Rights in the Work or (ii) assert any associated claims\nand causes of action with respect to the Work, in either case contrary to\nAffirmer's express Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n  a. No trademark or patent rights held by Affirmer are waived, abandoned,\n  surrendered, licensed or otherwise affected by this document.\n\n  b. Affirmer offers the Work as-is and makes no representations or warranties\n  of any kind concerning the Work, express, implied, statutory or otherwise,\n  including without limitation warranties of title, merchantability, fitness\n  for a particular purpose, non infringement, or the absence of latent or\n  other defects, accuracy, or the present or absence of errors, whether or not\n  discoverable, all to the greatest extent permissible under applicable law.\n\n  c. Affirmer disclaims responsibility for clearing rights of other persons\n  that may apply to the Work or any use thereof, including without limitation\n  any person's Copyright and Related Rights in the Work. Further, Affirmer\n  disclaims responsibility for obtaining any necessary consents, permissions\n  or other rights required for any use of the Work.\n\n  d. Affirmer understands and acknowledges that Creative Commons is not a\n  party to this document and has no duty or obligation with respect to this\n  CC0 or use of the Work.\n\nFor more information, please see\n<http://creativecommons.org/publicdomain/zero/1.0/>\n\n# Licenses of bundled dependencies\nThe published create-vite artifact additionally contains code with the following licenses:\nApache-2.0, ISC, MIT\n\n# Bundled dependencies:\n## @clack/core, @clack/prompts\nLicense: MIT\nBy: Nate Moore\nRepositories: https://github.com/bombshell-dev/clack, https://github.com/bombshell-dev/clack\n\n> MIT License\n> \n> Copyright (c) Nate Moore\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## @vercel/detect-agent\nLicense: Apache-2.0\nBy: Vercel\nRepository: https://github.com/vercel/vercel\n\n> Apache License\n>                            Version 2.0, January 2004\n>                         http://www.apache.org/licenses/\n> \n>    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n> \n>    1. Definitions.\n> \n>       \"License\" shall mean the terms and conditions for use, reproduction,\n>       and distribution as defined by Sections 1 through 9 of this document.\n> \n>       \"Licensor\" shall mean the copyright owner or entity authorized by\n>       the copyright owner that is granting the License.\n> \n>       \"Legal Entity\" shall mean the union of the acting entity and all\n>       other entities that control, are controlled by, or are under common\n>       control with that entity. For the purposes of this definition,\n>       \"control\" means (i) the power, direct or indirect, to cause the\n>       direction or management of such entity, whether by contract or\n>       otherwise, or (ii) ownership of fifty percent (50%) or more of the\n>       outstanding shares, or (iii) beneficial ownership of such entity.\n> \n>       \"You\" (or \"Your\") shall mean an individual or Legal Entity\n>       exercising permissions granted by this License.\n> \n>       \"Source\" form shall mean the preferred form for making modifications,\n>       including but not limited to software source code, documentation\n>       source, and configuration files.\n> \n>       \"Object\" form shall mean any form resulting from mechanical\n>       transformation or translation of a Source form, including but\n>       not limited to compiled object code, generated documentation,\n>       and conversions to other media types.\n> \n>       \"Work\" shall mean the work of authorship, whether in Source or\n>       Object form, made available under the License, as indicated by a\n>       copyright notice that is included in or attached to the work\n>       (an example is provided in the Appendix below).\n> \n>       \"Derivative Works\" shall mean any work, whether in Source or Object\n>       form, that is based on (or derived from) the Work and for which the\n>       editorial revisions, annotations, elaborations, or other modifications\n>       represent, as a whole, an original work of authorship. For the purposes\n>       of this License, Derivative Works shall not include works that remain\n>       separable from, or merely link (or bind by name) to the interfaces of,\n>       the Work and Derivative Works thereof.\n> \n>       \"Contribution\" shall mean any work of authorship, including\n>       the original version of the Work and any modifications or additions\n>       to that Work or Derivative Works thereof, that is intentionally\n>       submitted to Licensor for inclusion in the Work by the copyright owner\n>       or by an individual or Legal Entity authorized to submit on behalf of\n>       the copyright owner. For the purposes of this definition, \"submitted\"\n>       means any form of electronic, verbal, or written communication sent\n>       to the Licensor or its representatives, including but not limited to\n>       communication on electronic mailing lists, source code control systems,\n>       and issue tracking systems that are managed by, or on behalf of, the\n>       Licensor for the purpose of discussing and improving the Work, but\n>       excluding communication that is conspicuously marked or otherwise\n>       designated in writing by the copyright owner as \"Not a Contribution.\"\n> \n>       \"Contributor\" shall mean Licensor and any individual or Legal Entity\n>       on behalf of whom a Contribution has been received by Licensor and\n>       subsequently incorporated within the Work.\n> \n>    2. Grant of Copyright License. Subject to the terms and conditions of\n>       this License, each Contributor hereby grants to You a perpetual,\n>       worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n>       copyright license to reproduce, prepare Derivative Works of,\n>       publicly display, publicly perform, sublicense, and distribute the\n>       Work and such Derivative Works in Source or Object form.\n> \n>    3. Grant of Patent License. Subject to the terms and conditions of\n>       this License, each Contributor hereby grants to You a perpetual,\n>       worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n>       (except as stated in this section) patent license to make, have made,\n>       use, offer to sell, sell, import, and otherwise transfer the Work,\n>       where such license applies only to those patent claims licensable\n>       by such Contributor that are necessarily infringed by their\n>       Contribution(s) alone or by combination of their Contribution(s)\n>       with the Work to which such Contribution(s) was submitted. If You\n>       institute patent litigation against any entity (including a\n>       cross-claim or counterclaim in a lawsuit) alleging that the Work\n>       or a Contribution incorporated within the Work constitutes direct\n>       or contributory patent infringement, then any patent licenses\n>       granted to You under this License for that Work shall terminate\n>       as of the date such litigation is filed.\n> \n>    4. Redistribution. You may reproduce and distribute copies of the\n>       Work or Derivative Works thereof in any medium, with or without\n>       modifications, and in Source or Object form, provided that You\n>       meet the following conditions:\n> \n>       (a) You must give any other recipients of the Work or\n>           Derivative Works a copy of this License; and\n> \n>       (b) You must cause any modified files to carry prominent notices\n>           stating that You changed the files; and\n> \n>       (c) You must retain, in the Source form of any Derivative Works\n>           that You distribute, all copyright, patent, trademark, and\n>           attribution notices from the Source form of the Work,\n>           excluding those notices that do not pertain to any part of\n>           the Derivative Works; and\n> \n>       (d) If the Work includes a \"NOTICE\" text file as part of its\n>           distribution, then any Derivative Works that You distribute must\n>           include a readable copy of the attribution notices contained\n>           within such NOTICE file, excluding those notices that do not\n>           pertain to any part of the Derivative Works, in at least one\n>           of the following places: within a NOTICE text file distributed\n>           as part of the Derivative Works; within the Source form or\n>           documentation, if provided along with the Derivative Works; or,\n>           within a display generated by the Derivative Works, if and\n>           wherever such third-party notices normally appear. The contents\n>           of the NOTICE file are for informational purposes only and\n>           do not modify the License. You may add Your own attribution\n>           notices within Derivative Works that You distribute, alongside\n>           or as an addendum to the NOTICE text from the Work, provided\n>           that such additional attribution notices cannot be construed\n>           as modifying the License.\n> \n>       You may add Your own copyright statement to Your modifications and\n>       may provide additional or different license terms and conditions\n>       for use, reproduction, or distribution of Your modifications, or\n>       for any such Derivative Works as a whole, provided Your use,\n>       reproduction, and distribution of the Work otherwise complies with\n>       the conditions stated in this License.\n> \n>    5. Submission of Contributions. Unless You explicitly state otherwise,\n>       any Contribution intentionally submitted for inclusion in the Work\n>       by You to the Licensor shall be under the terms and conditions of\n>       this License, without any additional terms or conditions.\n>       Notwithstanding the above, nothing herein shall supersede or modify\n>       the terms of any separate license agreement you may have executed\n>       with Licensor regarding such Contributions.\n> \n>    6. Trademarks. This License does not grant permission to use the trade\n>       names, trademarks, service marks, or product names of the Licensor,\n>       except as required for reasonable and customary use in describing the\n>       origin of the Work and reproducing the content of the NOTICE file.\n> \n>    7. Disclaimer of Warranty. Unless required by applicable law or\n>       agreed to in writing, Licensor provides the Work (and each\n>       Contributor provides its Contributions) on an \"AS IS\" BASIS,\n>       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n>       implied, including, without limitation, any warranties or conditions\n>       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n>       PARTICULAR PURPOSE. You are solely responsible for determining the\n>       appropriateness of using or redistributing the Work and assume any\n>       risks associated with Your exercise of permissions under this License.\n> \n>    8. Limitation of Liability. In no event and under no legal theory,\n>       whether in tort (including negligence), contract, or otherwise,\n>       unless required by applicable law (such as deliberate and grossly\n>       negligent acts) or agreed to in writing, shall any Contributor be\n>       liable to You for damages, including any direct, indirect, special,\n>       incidental, or consequential damages of any character arising as a\n>       result of this License or out of the use or inability to use the\n>       Work (including but not limited to damages for loss of goodwill,\n>       work stoppage, computer failure or malfunction, or any and all\n>       other commercial damages or losses), even if such Contributor\n>       has been advised of the possibility of such damages.\n> \n>    9. Accepting Warranty or Additional Liability. While redistributing\n>       the Work or Derivative Works thereof, You may choose to offer,\n>       and charge a fee for, acceptance of support, warranty, indemnity,\n>       or other liability obligations and/or rights consistent with this\n>       License. However, in accepting such obligations, You may act only\n>       on Your own behalf and on Your sole responsibility, not on behalf\n>       of any other Contributor, and only if You agree to indemnify,\n>       defend, and hold each Contributor harmless for any liability\n>       incurred by, or claims asserted against, such Contributor by reason\n>       of your accepting any such warranty or additional liability.\n> \n>    END OF TERMS AND CONDITIONS\n> \n>    APPENDIX: How to apply the Apache License to your work.\n> \n>       To apply the Apache License to your work, attach the following\n>       boilerplate notice, with the fields enclosed by brackets \"[]\"\n>       replaced with your own identifying information. (Don't include\n>       the brackets!)  The text should be enclosed in the appropriate\n>       comment syntax for the file format. We also recommend that a\n>       file or class name and description of purpose be included on the\n>       same \"printed page\" as the copyright notice for easier\n>       identification within third-party archives.\n> \n>    Copyright 2017 Vercel, Inc.\n> \n>    Licensed under the Apache License, Version 2.0 (the \"License\");\n>    you may not use this file except in compliance with the License.\n>    You may obtain a copy of the License at\n> \n>        http://www.apache.org/licenses/LICENSE-2.0\n> \n>    Unless required by applicable law or agreed to in writing, software\n>    distributed under the License is distributed on an \"AS IS\" BASIS,\n>    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n>    See the License for the specific language governing permissions and\n>    limitations under the License.\n\n---------------------------------------\n\n## cross-spawn\nLicense: MIT\nBy: André Cruz\nRepository: https://github.com/moxystudio/node-cross-spawn\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## isexe, which\nLicense: ISC\nBy: Isaac Z. Schlueter\nRepositories: https://github.com/isaacs/isexe, https://github.com/isaacs/node-which\n\n> The ISC License\n> \n> Copyright (c) Isaac Z. Schlueter and Contributors\n> \n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\n> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## mri\nLicense: MIT\nBy: Luke Edwards\nRepository: https://github.com/lukeed/mri\n\n> The MIT License (MIT)\n> \n> Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## path-key, shebang-regex\nLicense: MIT\nBy: Sindre Sorhus\nRepositories: https://github.com/sindresorhus/path-key, https://github.com/sindresorhus/shebang-regex\n\n> MIT License\n> \n> Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## picocolors\nLicense: ISC\nBy: Alexey Raspopov\nRepository: https://github.com/alexeyraspopov/picocolors\n\n> ISC License\n> \n> Copyright (c) 2021-2024 Oleksii Raspopov, Kostiantyn Denysov, Anton Verinov\n> \n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n> OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## shebang-command\nLicense: MIT\nBy: Kevin Mårtensson\nRepository: https://github.com/kevva/shebang-command\n\n> MIT License\n> \n> Copyright (c) Kevin Mårtensson <kevinmartensson@gmail.com> (github.com/kevva)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## sisteransi\nLicense: MIT\nBy: Terkel Gjervig\nRepository: https://github.com/terkelg/sisteransi\n\n> MIT License\n> \n> Copyright (c) 2018 Terkel Gjervig Nielsen\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n"
  },
  {
    "path": "packages/create-vite/README.md",
    "content": "# create-vite <a href=\"https://npmjs.com/package/create-vite\"><img src=\"https://img.shields.io/npm/v/create-vite\" alt=\"npm package\"></a>\n\n## Scaffolding Your First Vite Project\n\n> **Compatibility Note:**\n> Vite requires [Node.js](https://nodejs.org/en/) version 20.19+, 22.12+. However, some templates require a higher Node.js version to work, please upgrade if your package manager warns about it.\n\nWith NPM:\n\n```bash\nnpm create vite@latest\n```\n\nWith Yarn:\n\n```bash\nyarn create vite\n```\n\nWith PNPM:\n\n```bash\npnpm create vite\n```\n\nWith Bun:\n\n```bash\nbun create vite\n```\n\nWith Deno:\n\n```bash\ndeno init --npm vite\n```\n\nThen follow the prompts!\n\nYou can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + Vue project, run:\n\n```bash\n# npm 7+, extra double-dash is needed:\nnpm create vite@latest my-vue-app -- --template vue\n\n# yarn\nyarn create vite my-vue-app --template vue\n\n# pnpm\npnpm create vite my-vue-app --template vue\n\n# Bun\nbun create vite my-vue-app --template vue\n\n# Deno\ndeno init --npm vite my-vue-app --template vue\n```\n\nCurrently supported template presets include:\n\n- `vanilla`\n- `vanilla-ts`\n- `vue`\n- `vue-ts`\n- `react`\n- `react-ts`\n- `react-swc`\n- `react-swc-ts`\n- `preact`\n- `preact-ts`\n- `lit`\n- `lit-ts`\n- `svelte`\n- `svelte-ts`\n- `solid`\n- `solid-ts`\n- `qwik`\n- `qwik-ts`\n\nYou can use `.` for the project name to scaffold in the current directory.\n\n## Community Templates\n\ncreate-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for [community maintained templates](https://github.com/vitejs/awesome-vite#templates) that include other tools or target different frameworks. You can use a tool like [tiged](https://github.com/tiged/tiged) to scaffold your project with one of the templates.\n\n```bash\nnpx tiged user/project my-project\ncd my-project\n\nnpm install\nnpm run dev\n```\n"
  },
  {
    "path": "packages/create-vite/__tests__/cli.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport type { SyncOptions } from 'execa'\nimport { execaCommandSync } from 'execa'\nimport { afterEach, beforeAll, expect, test } from 'vitest'\n\nconst CLI_PATH = path.join(import.meta.dirname, '..')\n\nconst projectName = 'test-app'\nconst genPath = path.join(import.meta.dirname, projectName)\nconst genPathWithSubfolder = path.join(\n  import.meta.dirname,\n  'subfolder',\n  projectName,\n)\n\nconst run = (args: string[], options?: SyncOptions) => {\n  return execaCommandSync(`node ${CLI_PATH} ${args.join(' ')}`, {\n    env: { ...process.env, _VITE_TEST_CLI: 'true' },\n    ...options,\n  })\n}\n\n// Helper to create a non-empty directory\nconst createNonEmptyDir = (overrideFolder?: string) => {\n  // Create the temporary directory\n  const newNonEmptyFolder = overrideFolder || genPath\n  fs.mkdirSync(newNonEmptyFolder, { recursive: true })\n\n  // Create a package.json file\n  const pkgJson = path.join(newNonEmptyFolder, 'package.json')\n  fs.writeFileSync(pkgJson, '{ \"foo\": \"bar\" }')\n}\n\n// Vue 3 starter template\nconst templateFiles = fs\n  .readdirSync(path.join(CLI_PATH, 'template-vue'))\n  // _gitignore is renamed to .gitignore\n  .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath))\n  .sort()\n\n// React starter template\nconst templateFilesReact = fs\n  .readdirSync(path.join(CLI_PATH, 'template-react'))\n  // _gitignore is renamed to .gitignore\n  .map((filePath) => (filePath === '_gitignore' ? '.gitignore' : filePath))\n  .sort()\n\nconst clearAnyPreviousFolders = () => {\n  if (fs.existsSync(genPath)) {\n    fs.rmSync(genPath, { recursive: true, force: true })\n  }\n  if (fs.existsSync(genPathWithSubfolder)) {\n    fs.rmSync(genPathWithSubfolder, { recursive: true, force: true })\n  }\n}\n\nbeforeAll(() => clearAnyPreviousFolders())\nafterEach(() => clearAnyPreviousFolders())\n\ntest('prompts for the project name if none supplied', () => {\n  const { stdout } = run(['--interactive'])\n  expect(stdout).toContain('Project name:')\n})\n\ntest('prompts for the framework if none supplied when target dir is current directory', () => {\n  fs.mkdirSync(genPath, { recursive: true })\n  const { stdout } = run(['.', '--interactive'], { cwd: genPath })\n  expect(stdout).toContain('Select a framework:')\n})\n\ntest('prompts for the framework if none supplied', () => {\n  const { stdout } = run([projectName, '--interactive'])\n  expect(stdout).toContain('Select a framework:')\n})\n\ntest('prompts for the framework on not supplying a value for --template', () => {\n  const { stdout } = run([projectName, '--interactive', '--template'])\n  expect(stdout).toContain('Select a framework:')\n})\n\ntest('prompts for the framework on supplying an invalid template', () => {\n  const { stdout } = run([\n    projectName,\n    '--interactive',\n    '--template',\n    'unknown',\n  ])\n  expect(stdout).toContain(\n    `\"unknown\" isn't a valid template. Please choose from below:`,\n  )\n})\n\ntest('asks to overwrite non-empty target directory', () => {\n  createNonEmptyDir()\n  const { stdout } = run([projectName, '--interactive'], {\n    cwd: import.meta.dirname,\n  })\n  expect(stdout).toContain(`Target directory \"${projectName}\" is not empty.`)\n})\n\ntest('asks to overwrite non-empty target directory with subfolder', () => {\n  createNonEmptyDir(genPathWithSubfolder)\n  const { stdout } = run([`subfolder/${projectName}`, '--interactive'], {\n    cwd: import.meta.dirname,\n  })\n  expect(stdout).toContain(\n    `Target directory \"subfolder/${projectName}\" is not empty.`,\n  )\n})\n\ntest('asks to overwrite non-empty current directory', () => {\n  createNonEmptyDir()\n  const { stdout } = run(['.', '--interactive'], { cwd: genPath })\n  expect(stdout).toContain(`Current directory is not empty.`)\n})\n\ntest('successfully scaffolds a project based on vue starter template', () => {\n  const { stdout } = run(\n    [\n      projectName,\n      '--interactive',\n      '--no-immediate',\n      '--template',\n      'vue',\n      '--no-rolldown',\n    ],\n    {\n      cwd: import.meta.dirname,\n    },\n  )\n  const generatedFiles = fs.readdirSync(genPath).sort()\n\n  // Assertions\n  expect(stdout).toContain(`Scaffolding project in ${genPath}`)\n  expect(templateFiles).toEqual(generatedFiles)\n})\n\ntest('successfully scaffolds a project with subfolder based on react starter template', () => {\n  const { stdout } = run(\n    [\n      `subfolder/${projectName}`,\n      '--interactive',\n      '--no-immediate',\n      '--template',\n      'react',\n      '--no-rolldown',\n    ],\n    {\n      cwd: import.meta.dirname,\n    },\n  )\n  const generatedFiles = fs.readdirSync(genPathWithSubfolder).sort()\n\n  // Assertions\n  expect(stdout).toContain(`Scaffolding project in ${genPathWithSubfolder}`)\n  expect(templateFilesReact).toEqual(generatedFiles)\n})\n\ntest('successfully scaffolds a project based on react-compiler-ts starter template', () => {\n  const { stdout } = run([projectName, '--template', 'react-compiler-ts'], {\n    cwd: import.meta.dirname,\n  })\n  const configFile = fs.readFileSync(\n    path.join(genPath, 'vite.config.ts'),\n    'utf-8',\n  )\n  const packageJsonFile = fs.readFileSync(\n    path.join(genPath, 'package.json'),\n    'utf-8',\n  )\n  const readmeFile = fs.readFileSync(path.join(genPath, 'README.md'), 'utf-8')\n\n  // Assertions\n  expect(stdout).toContain(`Scaffolding project in ${genPath}`)\n  expect(configFile).toContain('reactCompilerPreset')\n  expect(packageJsonFile).toContain('babel-plugin-react-compiler')\n  expect(readmeFile).toContain('The React Compiler is enabled on this template')\n})\n\ntest('works with the -t alias', () => {\n  const { stdout } = run(\n    [\n      projectName,\n      '--interactive',\n      '--no-immediate',\n      '-t',\n      'vue',\n      '--no-rolldown',\n    ],\n    {\n      cwd: import.meta.dirname,\n    },\n  )\n  const generatedFiles = fs.readdirSync(genPath).sort()\n\n  // Assertions\n  expect(stdout).toContain(`Scaffolding project in ${genPath}`)\n  expect(templateFiles).toEqual(generatedFiles)\n})\n\ntest('accepts command line override for --overwrite', () => {\n  createNonEmptyDir()\n  const { stdout } = run(['.', '--interactive', '--overwrite', 'ignore'], {\n    cwd: genPath,\n  })\n  expect(stdout).not.toContain(`Current directory is not empty.`)\n})\n\ntest('skip prompts when --no-interactive is passed', () => {\n  createNonEmptyDir()\n  const { stdout } = run([projectName, '--no-interactive'], { cwd: genPath })\n  expect(stdout).not.toContain('Project name:')\n  expect(stdout).toContain('Done. Now run:')\n})\n\ntest('return help usage how to use create-vite', () => {\n  const { stdout } = run(['--help'], { cwd: import.meta.dirname })\n  const message = 'Usage: create-vite [OPTION]... [DIRECTORY]'\n  expect(stdout).toContain(message)\n})\n\ntest('return help usage how to use create-vite with -h alias', () => {\n  const { stdout } = run(['--h'], { cwd: import.meta.dirname })\n  const message = 'Usage: create-vite [OPTION]... [DIRECTORY]'\n  expect(stdout).toContain(message)\n})\n\ntest('sets index.html title to project name', () => {\n  const { stdout } = run([projectName, '--template', 'react'], {\n    cwd: import.meta.dirname,\n  })\n\n  const indexHtmlPath = path.join(genPath, 'index.html')\n  const indexHtmlContent = fs.readFileSync(indexHtmlPath, 'utf-8')\n\n  expect(stdout).toContain(`Scaffolding project in ${genPath}`)\n  expect(indexHtmlContent).toContain(`<title>${projectName}</title>`)\n})\n\ntest('accepts immediate flag', () => {\n  const { stdout } = run([projectName, '--template', 'vue', '--immediate'], {\n    cwd: import.meta.dirname,\n  })\n  expect(stdout).not.toContain('Install and start now?')\n  expect(stdout).toContain(`Scaffolding project in ${genPath}`)\n  expect(stdout).toContain('Installing dependencies')\n})\n\ntest('accepts immediate flag and skips install prompt', () => {\n  const { stdout } = run([projectName, '--template', 'vue', '--no-immediate'], {\n    cwd: import.meta.dirname,\n  })\n  expect(stdout).not.toContain('Install and start now?')\n  expect(stdout).not.toContain('Installing dependencies')\n  expect(stdout).toContain(`Scaffolding project in ${genPath}`)\n})\n"
  },
  {
    "path": "packages/create-vite/index.js",
    "content": "#!/usr/bin/env node\n\nimport './dist/index.js'\n"
  },
  {
    "path": "packages/create-vite/package.json",
    "content": "{\n  \"name\": \"create-vite\",\n  \"version\": \"9.0.3\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"author\": \"Evan You\",\n  \"bin\": {\n    \"create-vite\": \"index.js\",\n    \"cva\": \"index.js\"\n  },\n  \"files\": [\n    \"index.js\",\n    \"template-*\",\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"dev\": \"tsdown --watch\",\n    \"build\": \"tsdown\",\n    \"typecheck\": \"tsc\",\n    \"prepublishOnly\": \"npm run build\",\n    \"execute\": \"node index.js\"\n  },\n  \"engines\": {\n    \"node\": \"^20.19.0 || >=22.12.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitejs/vite.git\",\n    \"directory\": \"packages/create-vite\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitejs/vite/issues\"\n  },\n  \"homepage\": \"https://github.com/vitejs/vite/tree/main/packages/create-vite#readme\",\n  \"funding\": \"https://github.com/vitejs/vite?sponsor=1\",\n  \"devDependencies\": {\n    \"@clack/prompts\": \"^1.1.0\",\n    \"@vercel/detect-agent\": \"^1.2.1\",\n    \"cross-spawn\": \"^7.0.6\",\n    \"mri\": \"^1.2.0\",\n    \"picocolors\": \"^1.1.1\",\n    \"tsdown\": \"^0.21.4\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/src/index.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { SpawnOptions } from 'node:child_process'\nimport spawn from 'cross-spawn'\nimport mri from 'mri'\nimport * as prompts from '@clack/prompts'\nimport colors from 'picocolors'\nimport { determineAgent } from '@vercel/detect-agent'\n\nconst {\n  blue,\n  blueBright,\n  cyan,\n  green,\n  greenBright,\n  magenta,\n  red,\n  redBright,\n  reset,\n  underline,\n  yellow,\n} = colors\n\nconst argv = mri<{\n  template?: string\n  help?: boolean\n  overwrite?: boolean\n  immediate?: boolean\n  interactive?: boolean\n}>(process.argv.slice(2), {\n  boolean: ['help', 'overwrite', 'immediate', 'interactive'],\n  alias: { h: 'help', t: 'template', i: 'immediate' },\n  string: ['template'],\n})\nconst cwd = process.cwd()\n\n// prettier-ignore\nconst helpMessage = `\\\nUsage: create-vite [OPTION]... [DIRECTORY]\n\nCreate a new Vite project in JavaScript or TypeScript.\nWhen running in TTY, the CLI will start in interactive mode.\n\nOptions:\n  -t, --template NAME                   use a specific template\n  -i, --immediate                       install dependencies and start dev\n  --interactive / --no-interactive      force interactive / non-interactive mode\n\nAvailable templates:\n${yellow    ('vanilla-ts          vanilla'       )}\n${green     ('vue-ts              vue'           )}\n${cyan      ('react-ts            react'         )}\n${cyan      ('react-compiler-ts   react-compiler')}\n${magenta   ('preact-ts           preact'        )}\n${redBright ('lit-ts              lit'           )}\n${red       ('svelte-ts           svelte'        )}\n${blue      ('solid-ts            solid'         )}\n${blueBright('qwik-ts             qwik'          )}`\n\ntype ColorFunc = (str: string | number) => string\ntype Framework = {\n  name: string\n  display: string\n  color: ColorFunc\n  variants: FrameworkVariant[]\n}\ntype FrameworkVariant = {\n  name: string\n  display: string\n  link?: `https://${string}`\n  color: ColorFunc\n  customCommand?: string\n}\n\nconst FRAMEWORKS: Framework[] = [\n  {\n    name: 'vanilla',\n    display: 'Vanilla',\n    color: yellow,\n    variants: [\n      {\n        name: 'vanilla-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'vanilla',\n        display: 'JavaScript',\n        color: yellow,\n      },\n    ],\n  },\n  {\n    name: 'vue',\n    display: 'Vue',\n    color: green,\n    variants: [\n      {\n        name: 'vue-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'vue',\n        display: 'JavaScript',\n        color: yellow,\n      },\n      {\n        name: 'custom-create-vue',\n        display: 'Official Vue Starter ↗',\n        color: green,\n        customCommand: 'npm create vue@latest TARGET_DIR',\n      },\n      {\n        name: 'custom-nuxt',\n        display: 'Nuxt ↗',\n        link: 'https://nuxt.com',\n        color: greenBright,\n        customCommand: 'npm exec nuxi init TARGET_DIR',\n      },\n      {\n        name: 'custom-vike-vue',\n        display: 'Vike ↗',\n        link: 'https://vike.dev',\n        color: greenBright,\n        customCommand: 'npm create -- vike@latest --vue TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'react',\n    display: 'React',\n    color: cyan,\n    variants: [\n      {\n        name: 'react-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'react-compiler-ts',\n        display: 'TypeScript + React Compiler',\n        color: blue,\n      },\n      {\n        name: 'react',\n        display: 'JavaScript',\n        color: yellow,\n      },\n      {\n        name: 'react-compiler',\n        display: 'JavaScript + React Compiler',\n        color: yellow,\n      },\n      {\n        name: 'rsc',\n        display: 'RSC',\n        color: magenta,\n        customCommand:\n          'npm exec tiged vitejs/vite-plugin-react/packages/plugin-rsc/examples/starter TARGET_DIR',\n      },\n      {\n        name: 'custom-react-router',\n        display: 'React Router v7 ↗',\n        link: 'https://reactrouter.com',\n        color: cyan,\n        customCommand: 'npm create react-router@latest TARGET_DIR',\n      },\n      {\n        name: 'custom-tanstack-router-react',\n        display: 'TanStack Router ↗',\n        link: 'https://tanstack.com/router',\n        color: cyan,\n        customCommand:\n          'npm exec -- @tanstack/cli@latest create TARGET_DIR --interactive',\n      },\n      {\n        name: 'redwoodsdk-standard',\n        display: 'RedwoodSDK ↗',\n        link: 'https://rwsdk.com',\n        color: cyan,\n        customCommand: 'npm create rwsdk@latest TARGET_DIR',\n      },\n      {\n        name: 'custom-vike-react',\n        display: 'Vike ↗',\n        link: 'https://vike.dev',\n        color: cyan,\n        customCommand: 'npm create -- vike@latest --react TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'preact',\n    display: 'Preact',\n    color: magenta,\n    variants: [\n      {\n        name: 'preact-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'preact',\n        display: 'JavaScript',\n        color: yellow,\n      },\n      {\n        name: 'custom-create-preact',\n        display: 'Official Preact Starter ↗',\n        color: magenta,\n        customCommand: 'npm create preact@latest TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'lit',\n    display: 'Lit',\n    color: redBright,\n    variants: [\n      {\n        name: 'lit-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'lit',\n        display: 'JavaScript',\n        color: yellow,\n      },\n    ],\n  },\n  {\n    name: 'svelte',\n    display: 'Svelte',\n    color: red,\n    variants: [\n      {\n        name: 'svelte-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'svelte',\n        display: 'JavaScript',\n        color: yellow,\n      },\n      {\n        name: 'custom-svelte-kit',\n        display: 'SvelteKit ↗',\n        color: red,\n        customCommand: 'npm exec sv create TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'solid',\n    display: 'Solid',\n    color: blue,\n    variants: [\n      {\n        name: 'solid-ts',\n        display: 'TypeScript',\n        color: blue,\n      },\n      {\n        name: 'solid',\n        display: 'JavaScript',\n        color: yellow,\n      },\n      {\n        name: 'custom-tanstack-router-solid',\n        display: 'TanStack Router ↗',\n        link: 'https://tanstack.com/router',\n        color: cyan,\n        customCommand:\n          'npm exec -- @tanstack/cli@latest create TARGET_DIR --framework solid --interactive',\n      },\n      {\n        name: 'custom-vike-solid',\n        display: 'Vike ↗',\n        link: 'https://vike.dev',\n        color: cyan,\n        customCommand: 'npm create -- vike@latest --solid TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'ember',\n    display: 'Ember',\n    color: redBright,\n    variants: [\n      {\n        name: 'ember-app-ts',\n        display: 'TypeScript ↗',\n        color: blueBright,\n        customCommand:\n          'npm exec -- ember-cli@latest new TARGET_DIR --typescript',\n      },\n      {\n        name: 'ember-app',\n        display: 'JavaScript ↗',\n        color: redBright,\n        customCommand: 'npm exec -- ember-cli@latest new TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'qwik',\n    display: 'Qwik',\n    color: blueBright,\n    variants: [\n      {\n        name: 'qwik-ts',\n        display: 'TypeScript',\n        color: blueBright,\n      },\n      {\n        name: 'qwik',\n        display: 'JavaScript',\n        color: yellow,\n      },\n      {\n        name: 'custom-qwik-city',\n        display: 'QwikCity ↗',\n        color: blueBright,\n        customCommand: 'npm create qwik@latest empty TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'angular',\n    display: 'Angular',\n    color: red,\n    variants: [\n      {\n        name: 'custom-angular',\n        display: 'Angular ↗',\n        color: red,\n        customCommand: 'npm exec @angular/cli@latest new TARGET_DIR',\n      },\n      {\n        name: 'custom-analog',\n        display: 'Analog ↗',\n        color: yellow,\n        customCommand: 'npm create analog@latest TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'marko',\n    display: 'Marko',\n    color: magenta,\n    variants: [\n      {\n        name: 'marko-run',\n        display: 'Marko Run ↗',\n        color: magenta,\n        customCommand: 'npm create -- marko@latest --name TARGET_DIR',\n      },\n    ],\n  },\n  {\n    name: 'others',\n    display: 'Others',\n    color: reset,\n    variants: [\n      {\n        name: 'create-vite-extra',\n        display: 'Extra Vite Starters ↗',\n        color: reset,\n        customCommand: 'npm create vite-extra@latest TARGET_DIR',\n      },\n      {\n        name: 'create-electron-vite',\n        display: 'Electron ↗',\n        color: reset,\n        customCommand: 'npm create electron-vite@latest TARGET_DIR',\n      },\n    ],\n  },\n]\n\nconst TEMPLATES = FRAMEWORKS.map((f) => f.variants.map((v) => v.name)).reduce(\n  (a, b) => a.concat(b),\n  [],\n)\n\nconst renameFiles: Record<string, string | undefined> = {\n  _gitignore: '.gitignore',\n}\n\nconst defaultTargetDir = 'vite-project'\n\nfunction run([command, ...args]: string[], options?: SpawnOptions) {\n  const { status, error } = spawn.sync(command, args, options)\n  if (status != null && status > 0) {\n    process.exit(status)\n  }\n\n  if (error) {\n    console.error(`\\n${command} ${args.join(' ')} error!`)\n    console.error(error)\n    process.exit(1)\n  }\n}\n\nfunction install(root: string, agent: string) {\n  if (process.env._VITE_TEST_CLI) {\n    prompts.log.step(\n      `Installing dependencies with ${agent}... (skipped in test)`,\n    )\n    return\n  }\n  prompts.log.step(`Installing dependencies with ${agent}...`)\n  run(getInstallCommand(agent), {\n    stdio: 'inherit',\n    cwd: root,\n  })\n}\n\nfunction start(root: string, agent: string) {\n  if (process.env._VITE_TEST_CLI) {\n    prompts.log.step('Starting dev server... (skipped in test)')\n    return\n  }\n  prompts.log.step('Starting dev server...')\n  run(getRunCommand(agent, 'dev'), {\n    stdio: 'inherit',\n    cwd: root,\n  })\n}\n\nasync function init() {\n  const argTargetDir = argv._[0]\n    ? formatTargetDir(String(argv._[0]))\n    : undefined\n  const argTemplate = argv.template\n  const argOverwrite = argv.overwrite\n  const argImmediate = argv.immediate\n  const argInteractive = argv.interactive\n\n  const help = argv.help\n  if (help) {\n    console.log(helpMessage)\n    return\n  }\n\n  const interactive = argInteractive ?? process.stdin.isTTY\n\n  // Detect AI agent environment for better agent experience (AX)\n  const { isAgent } = await determineAgent()\n  if (isAgent && interactive) {\n    console.log(\n      '\\nTo create in one go, run: create-vite <DIRECTORY> --no-interactive --template <TEMPLATE>\\n',\n    )\n  }\n\n  const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent)\n  const cancel = () => prompts.cancel('Operation cancelled')\n\n  // 1. Get project name and target dir\n  let targetDir = argTargetDir\n  if (!targetDir) {\n    if (interactive) {\n      const projectName = await prompts.text({\n        message: 'Project name:',\n        defaultValue: defaultTargetDir,\n        placeholder: defaultTargetDir,\n        validate: (value) => {\n          return !value || formatTargetDir(value).length > 0\n            ? undefined\n            : 'Invalid project name'\n        },\n      })\n      if (prompts.isCancel(projectName)) return cancel()\n      targetDir = formatTargetDir(projectName)\n    } else {\n      targetDir = defaultTargetDir\n    }\n  }\n\n  // 2. Handle directory if exist and not empty\n  if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {\n    let overwrite: 'yes' | 'no' | 'ignore' | undefined = argOverwrite\n      ? 'yes'\n      : undefined\n    if (!overwrite) {\n      if (interactive) {\n        const res = await prompts.select({\n          message:\n            (targetDir === '.'\n              ? 'Current directory'\n              : `Target directory \"${targetDir}\"`) +\n            ` is not empty. Please choose how to proceed:`,\n          options: [\n            {\n              label: 'Cancel operation',\n              value: 'no',\n            },\n            {\n              label: 'Remove existing files and continue',\n              value: 'yes',\n            },\n            {\n              label: 'Ignore files and continue',\n              value: 'ignore',\n            },\n          ],\n        })\n        if (prompts.isCancel(res)) return cancel()\n        overwrite = res\n      } else {\n        overwrite = 'no'\n      }\n    }\n\n    switch (overwrite) {\n      case 'yes':\n        emptyDir(targetDir)\n        break\n      case 'no':\n        cancel()\n        return\n    }\n  }\n\n  // 3. Get package name\n  let packageName = path.basename(path.resolve(targetDir))\n  if (!isValidPackageName(packageName)) {\n    if (interactive) {\n      const packageNameResult = await prompts.text({\n        message: 'Package name:',\n        defaultValue: toValidPackageName(packageName),\n        placeholder: toValidPackageName(packageName),\n        validate(dir) {\n          if (dir && !isValidPackageName(dir)) {\n            return 'Invalid package.json name'\n          }\n        },\n      })\n      if (prompts.isCancel(packageNameResult)) return cancel()\n      packageName = packageNameResult\n    } else {\n      packageName = toValidPackageName(packageName)\n    }\n  }\n\n  // 4. Choose a framework and variant\n  let template = argTemplate\n  let hasInvalidArgTemplate = false\n  if (argTemplate && !TEMPLATES.includes(argTemplate)) {\n    template = undefined\n    hasInvalidArgTemplate = true\n  }\n  if (!template) {\n    if (interactive) {\n      const framework = await prompts.select({\n        message: hasInvalidArgTemplate\n          ? `\"${argTemplate}\" isn't a valid template. Please choose from below: `\n          : 'Select a framework:',\n        options: FRAMEWORKS.map((framework) => {\n          const frameworkColor = framework.color\n          return {\n            label: frameworkColor(framework.display || framework.name),\n            value: framework,\n          }\n        }),\n      })\n      if (prompts.isCancel(framework)) return cancel()\n\n      const variant = await prompts.select({\n        message: 'Select a variant:',\n        options: framework.variants.map((variant) => {\n          const command = variant.customCommand\n            ? getFullCustomCommand(variant.customCommand, pkgInfo).replace(\n                / TARGET_DIR$/,\n                '',\n              )\n            : undefined\n          return {\n            label: getLabel(variant),\n            value: variant.name,\n            hint: command,\n          }\n        }),\n      })\n      if (prompts.isCancel(variant)) return cancel()\n\n      template = variant\n    } else {\n      template = 'vanilla-ts'\n    }\n  }\n\n  const pkgManager = pkgInfo ? pkgInfo.name : 'npm'\n\n  const root = path.join(cwd, targetDir)\n  // determine template\n  let isReactCompiler = false\n  if (template.includes('react-compiler')) {\n    isReactCompiler = true\n    template = template.replace('-compiler', '')\n  }\n\n  const { customCommand } =\n    FRAMEWORKS.flatMap((f) => f.variants).find((v) => v.name === template) ?? {}\n\n  if (customCommand) {\n    const fullCustomCommand = getFullCustomCommand(customCommand, pkgInfo)\n\n    const [command, ...args] = fullCustomCommand.split(' ')\n    // we replace TARGET_DIR here because targetDir may include a space\n    const replacedArgs = args.map((arg) =>\n      arg.replace('TARGET_DIR', () => targetDir),\n    )\n    const { status } = spawn.sync(command, replacedArgs, {\n      stdio: 'inherit',\n    })\n    process.exit(status ?? 0)\n  }\n\n  // 5. Ask about immediate install and package manager\n  let immediate = argImmediate\n  if (immediate === undefined) {\n    if (interactive) {\n      const immediateResult = await prompts.confirm({\n        message: `Install with ${pkgManager} and start now?`,\n      })\n      if (prompts.isCancel(immediateResult)) return cancel()\n      immediate = immediateResult\n    } else {\n      immediate = false\n    }\n  }\n\n  // Only create directory for built-in templates, not for customCommand\n  fs.mkdirSync(root, { recursive: true })\n  prompts.log.step(`Scaffolding project in ${root}...`)\n\n  const templateDir = path.resolve(\n    fileURLToPath(import.meta.url),\n    '../..',\n    `template-${template}`,\n  )\n\n  const write = (file: string, content?: string) => {\n    const targetPath = path.join(root, renameFiles[file] ?? file)\n    if (content) {\n      fs.writeFileSync(targetPath, content)\n    } else if (file === 'index.html') {\n      const templatePath = path.join(templateDir, file)\n      const templateContent = fs.readFileSync(templatePath, 'utf-8')\n      const updatedContent = templateContent.replace(\n        /<title>.*?<\\/title>/,\n        `<title>${packageName}</title>`,\n      )\n      fs.writeFileSync(targetPath, updatedContent)\n    } else {\n      copy(path.join(templateDir, file), targetPath)\n    }\n  }\n\n  const files = fs.readdirSync(templateDir)\n  for (const file of files.filter((f) => f !== 'package.json')) {\n    write(file)\n  }\n\n  const pkg = JSON.parse(\n    fs.readFileSync(path.join(templateDir, `package.json`), 'utf-8'),\n  )\n\n  pkg.name = packageName\n\n  write('package.json', JSON.stringify(pkg, null, 2) + '\\n')\n\n  if (isReactCompiler) {\n    setupReactCompiler(root, template.endsWith('-ts'))\n  }\n\n  if (immediate) {\n    install(root, pkgManager)\n    start(root, pkgManager)\n  } else {\n    let doneMessage = ''\n    const cdProjectName = path.relative(cwd, root)\n    doneMessage += `Done. Now run:\\n`\n    if (root !== cwd) {\n      doneMessage += `\\n  cd ${\n        cdProjectName.includes(' ') ? `\"${cdProjectName}\"` : cdProjectName\n      }`\n    }\n    doneMessage += `\\n  ${getInstallCommand(pkgManager).join(' ')}`\n    doneMessage += `\\n  ${getRunCommand(pkgManager, 'dev').join(' ')}`\n    prompts.outro(doneMessage)\n  }\n}\n\nfunction formatTargetDir(targetDir: string) {\n  return targetDir\n    .trim()\n    .replace(/[<>:\"\\\\|?*]/g, '')\n    .replace(/\\/+$/g, '')\n}\n\nfunction copy(src: string, dest: string) {\n  const stat = fs.statSync(src)\n  if (stat.isDirectory()) {\n    copyDir(src, dest)\n  } else {\n    fs.copyFileSync(src, dest)\n  }\n}\n\nfunction isValidPackageName(projectName: string) {\n  return /^(?:@[a-z\\d\\-*~][a-z\\d\\-*._~]*\\/)?[a-z\\d\\-~][a-z\\d\\-._~]*$/.test(\n    projectName,\n  )\n}\n\nfunction toValidPackageName(projectName: string) {\n  return projectName\n    .trim()\n    .toLowerCase()\n    .replace(/\\s+/g, '-')\n    .replace(/^[._]/, '')\n    .replace(/[^a-z\\d\\-~]+/g, '-')\n}\n\nfunction copyDir(srcDir: string, destDir: string) {\n  fs.mkdirSync(destDir, { recursive: true })\n  for (const file of fs.readdirSync(srcDir)) {\n    const srcFile = path.resolve(srcDir, file)\n    const destFile = path.resolve(destDir, file)\n    copy(srcFile, destFile)\n  }\n}\n\nfunction isEmpty(path: string) {\n  const files = fs.readdirSync(path)\n  return files.length === 0 || (files.length === 1 && files[0] === '.git')\n}\n\nfunction emptyDir(dir: string) {\n  if (!fs.existsSync(dir)) {\n    return\n  }\n  for (const file of fs.readdirSync(dir)) {\n    if (file === '.git') {\n      continue\n    }\n    fs.rmSync(path.resolve(dir, file), { recursive: true, force: true })\n  }\n}\n\ninterface PkgInfo {\n  name: string\n  version: string\n}\n\nfunction pkgFromUserAgent(userAgent: string | undefined): PkgInfo | undefined {\n  if (!userAgent) return undefined\n  const pkgSpec = userAgent.split(' ')[0]\n  const pkgSpecArr = pkgSpec.split('/')\n  return {\n    name: pkgSpecArr[0],\n    version: pkgSpecArr[1],\n  }\n}\n\nfunction setupReactCompiler(root: string, isTs: boolean) {\n  // renovate: datasource=npm depName=@rolldown/plugin-babel\n  const babelPluginVersion = '0.2.1'\n  // renovate: datasource=npm depName=babel-plugin-react-compiler\n  const reactCompilerPluginVersion = '1.0.0'\n  // renovate: datasource=npm depName=@babel/core\n  const babelCoreVersion = '7.29.0'\n  // renovate: datasource=npm depName=@types/babel__core\n  const typesBabelCoreVersion = '7.20.5'\n\n  editFile(path.resolve(root, 'package.json'), (content) => {\n    const asObject = JSON.parse(content)\n    const devDepsEntries = Object.entries(asObject.devDependencies)\n    devDepsEntries.push(['@rolldown/plugin-babel', `^${babelPluginVersion}`])\n    devDepsEntries.push([\n      'babel-plugin-react-compiler',\n      `^${reactCompilerPluginVersion}`,\n    ])\n    devDepsEntries.push(['@babel/core', `^${babelCoreVersion}`])\n    if (isTs) {\n      devDepsEntries.push(['@types/babel__core', `^${typesBabelCoreVersion}`])\n    }\n    devDepsEntries.sort()\n    asObject.devDependencies = Object.fromEntries(devDepsEntries)\n    return JSON.stringify(asObject, null, 2) + '\\n'\n  })\n  editFile(\n    path.resolve(root, `vite.config.${isTs ? 'ts' : 'js'}`),\n    (content) => {\n      return content\n        .replace(\n          `import react from '@vitejs/plugin-react'`,\n          `import react, { reactCompilerPreset } from '@vitejs/plugin-react'\nimport babel from '@rolldown/plugin-babel'`,\n        )\n        .replace(\n          '  plugins: [react()],',\n          `  plugins: [\n    react(),\n    babel({ presets: [reactCompilerPreset()] })\n  ],`,\n        )\n    },\n  )\n  updateReactCompilerReadme(\n    root,\n    'The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.\\n\\nNote: This will impact Vite dev & build performances.',\n  )\n}\n\nfunction updateReactCompilerReadme(root: string, newBody: string) {\n  editFile(path.resolve(root, `README.md`), (content) => {\n    const h2Start = content.indexOf('## React Compiler')\n    const bodyStart = content.indexOf('\\n\\n', h2Start)\n    const compilerSectionEnd = content.indexOf('\\n## ', bodyStart)\n    if (h2Start === -1 || bodyStart === -1 || compilerSectionEnd === -1) {\n      console.warn('Could not update compiler section in README.md')\n      return content\n    }\n    return content.replace(\n      content.slice(bodyStart + 2, compilerSectionEnd - 1),\n      newBody,\n    )\n  })\n}\n\nfunction editFile(file: string, callback: (content: string) => string) {\n  const content = fs.readFileSync(file, 'utf-8')\n  fs.writeFileSync(file, callback(content), 'utf-8')\n}\n\nfunction getFullCustomCommand(customCommand: string, pkgInfo?: PkgInfo) {\n  const pkgManager = pkgInfo ? pkgInfo.name : 'npm'\n  const isYarn1 = pkgManager === 'yarn' && pkgInfo?.version.startsWith('1.')\n\n  return (\n    customCommand\n      .replace(/^npm create (?:-- )?/, () => {\n        // `bun create` uses its own set of templates,\n        // the closest alternative is using `bun x` directly on the package\n        if (pkgManager === 'bun') {\n          return 'bun x create-'\n        }\n        // Deno uses `run -A npm:create-` instead of `create` or `init` to also provide needed perms\n        if (pkgManager === 'deno') {\n          return 'deno run -A npm:create-'\n        }\n        // pnpm doesn't support the -- syntax\n        if (pkgManager === 'pnpm') {\n          return 'pnpm create '\n        }\n        // For other package managers, preserve the original format\n        return customCommand.startsWith('npm create -- ')\n          ? `${pkgManager} create -- `\n          : `${pkgManager} create `\n      })\n      // Only Yarn 1.x doesn't support `@version` in the `create` command\n      .replace('@latest', () => (isYarn1 ? '' : '@latest'))\n      .replace(/^npm exec (?:-- )?/, () => {\n        // Prefer `pnpm dlx`, `yarn dlx`, or `bun x`\n        if (pkgManager === 'pnpm') {\n          // pnpm doesn't support the -- syntax\n          return 'pnpm dlx '\n        }\n        if (pkgManager === 'yarn' && !isYarn1) {\n          return 'yarn dlx '\n        }\n        if (pkgManager === 'bun') {\n          return 'bun x '\n        }\n        if (pkgManager === 'deno') {\n          return 'deno run -A npm:'\n        }\n        // Use `npm exec` in all other cases,\n        // including Yarn 1.x and other custom npm clients.\n        return customCommand.startsWith('npm exec -- ')\n          ? 'npm exec -- '\n          : 'npm exec '\n      })\n  )\n}\n\nfunction getLabel(variant: FrameworkVariant) {\n  const labelText = variant.display || variant.name\n  let label = variant.color(labelText)\n  const { link } = variant\n  if (link) {\n    label += ` ${underline(link)}`\n  }\n  return label\n}\n\nfunction getInstallCommand(agent: string) {\n  if (agent === 'yarn') {\n    return [agent]\n  }\n  return [agent, 'install']\n}\n\nfunction getRunCommand(agent: string, script: string) {\n  switch (agent) {\n    case 'yarn':\n    case 'pnpm':\n    case 'bun':\n      return [agent, script]\n    case 'deno':\n      return [agent, 'task', script]\n    default:\n      return [agent, 'run', script]\n  }\n}\n\ninit().catch((e) => {\n  console.error(e)\n})\n"
  },
  {
    "path": "packages/create-vite/template-lit/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-lit/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Lit</title>\n    <link rel=\"stylesheet\" href=\"./src/index.css\" />\n    <script type=\"module\" src=\"/src/my-element.js\"></script>\n  </head>\n  <body>\n    <my-element>\n      <h1>Get started</h1>\n    </my-element>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-lit/package.json",
    "content": "{\n  \"name\": \"vite-lit-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"lit\": \"^3.3.2\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-lit/src/index.css",
    "content": ":root {\n  color-scheme: light dark;\n  background-color: #ffffff;\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    background-color: #16171d;\n  }\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  min-width: 320px;\n  min-height: 100svh;\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  overflow-x: hidden;\n}\n"
  },
  {
    "path": "packages/create-vite/template-lit/src/my-element.js",
    "content": "import { LitElement, css, html } from 'lit'\nimport litLogo from './assets/lit.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\n\n/**\n * An example element.\n *\n * @slot - This element has a slot\n * @csspart button - The button\n */\nexport class MyElement extends LitElement {\n  static get properties() {\n    return {\n      /**\n       * The number of times the button has been clicked.\n       */\n      count: { type: Number },\n    }\n  }\n\n  constructor() {\n    super()\n    this.count = 0\n  }\n\n  render() {\n    return html`\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src=${heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src=${litLogo} class=\"framework\" alt=\"Lit logo\" />\n          <img src=${viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <slot></slot>\n          <p>\n            Edit <code>src/my-element.js</code> and save to test\n            <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" @click=${this._onClick} part=\"button\">\n          Count is ${this.count}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src=${viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://lit.dev/\" target=\"_blank\">\n                <img class=\"button-icon\" src=${litLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    `\n  }\n\n  _onClick() {\n    this.count++\n  }\n\n  static get styles() {\n    return css`\n      :host {\n        --text: #6b6375;\n        --text-h: #08060d;\n        --bg: #fff;\n        --border: #e5e4e7;\n        --code-bg: #f4f3ec;\n        --accent: #aa3bff;\n        --accent-bg: rgba(170, 59, 255, 0.1);\n        --accent-border: rgba(170, 59, 255, 0.5);\n        --social-bg: rgba(244, 243, 236, 0.5);\n        --shadow:\n          rgba(0, 0, 0, 0.1) 0 10px 15px -3px,\n          rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n        --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n        --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n        --mono: ui-monospace, Consolas, monospace;\n\n        font: 18px/145% var(--sans);\n        letter-spacing: 0.18px;\n\n        width: 1126px;\n        max-width: 100%;\n        margin: 0 auto;\n        text-align: center;\n        border-inline: 1px solid var(--border);\n        min-height: 100svh;\n        display: flex;\n        flex-direction: column;\n        box-sizing: border-box;\n        color: var(--text);\n      }\n\n      @media (prefers-color-scheme: dark) {\n        :host {\n          --text: #9ca3af;\n          --text-h: #f3f4f6;\n          --bg: #16171d;\n          --border: #2e303a;\n          --code-bg: #1f2028;\n          --accent: #c084fc;\n          --accent-bg: rgba(192, 132, 252, 0.15);\n          --accent-border: rgba(192, 132, 252, 0.5);\n          --social-bg: rgba(47, 48, 58, 0.5);\n          --shadow:\n            rgba(0, 0, 0, 0.4) 0 10px 15px -3px,\n            rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n        }\n\n        #social .button-icon {\n          filter: invert(1) brightness(2);\n        }\n      }\n\n      h1,\n      h2,\n      ::slotted(h1),\n      ::slotted(h2) {\n        font-family: var(--heading);\n        font-weight: 500;\n        color: var(--text-h);\n      }\n\n      h1,\n      ::slotted(h1) {\n        font-size: 56px;\n        letter-spacing: -1.68px;\n        margin: 32px 0;\n      }\n\n      h2 {\n        font-size: 24px;\n        line-height: 118%;\n        letter-spacing: -0.24px;\n        margin: 0 0 8px;\n      }\n\n      p {\n        margin: 0;\n      }\n\n      code {\n        font-family: var(--mono);\n        font-size: 15px;\n        line-height: 135%;\n        display: inline-flex;\n        padding: 4px 8px;\n        border-radius: 4px;\n        color: var(--text-h);\n        background: var(--code-bg);\n      }\n\n      .counter {\n        font-family: var(--mono);\n        font-size: 16px;\n        display: inline-flex;\n        padding: 5px 10px;\n        border-radius: 5px;\n        color: var(--accent);\n        background: var(--accent-bg);\n        border: 2px solid transparent;\n        transition: border-color 0.3s;\n        margin-bottom: 24px;\n        cursor: pointer;\n      }\n\n      .counter:hover {\n        border-color: var(--accent-border);\n      }\n\n      .counter:focus-visible {\n        outline: 2px solid var(--accent);\n        outline-offset: 2px;\n      }\n\n      .hero {\n        position: relative;\n      }\n\n      .hero .base,\n      .hero .framework,\n      .hero .vite {\n        inset-inline: 0;\n        margin: 0 auto;\n      }\n\n      .hero .base {\n        width: 170px;\n        position: relative;\n        z-index: 0;\n      }\n\n      .hero .framework,\n      .hero .vite {\n        position: absolute;\n      }\n\n      .hero .framework {\n        z-index: 1;\n        top: 34px;\n        height: 28px;\n        transform: perspective(2000px) rotateZ(300deg) rotateX(44deg)\n          rotateY(39deg) scale(1.4);\n      }\n\n      .hero .vite {\n        z-index: 0;\n        top: 107px;\n        height: 26px;\n        width: auto;\n        transform: perspective(2000px) rotateZ(300deg) rotateX(40deg)\n          rotateY(39deg) scale(0.8);\n      }\n\n      #center {\n        display: flex;\n        flex-direction: column;\n        gap: 25px;\n        place-content: center;\n        place-items: center;\n        flex-grow: 1;\n      }\n\n      #next-steps {\n        display: flex;\n        border-top: 1px solid var(--border);\n        text-align: left;\n      }\n\n      #next-steps > div {\n        flex: 1 1 0;\n        padding: 32px;\n      }\n\n      #next-steps .icon {\n        margin-bottom: 16px;\n        width: 22px;\n        height: 22px;\n      }\n\n      #docs {\n        border-right: 1px solid var(--border);\n      }\n\n      #next-steps ul {\n        list-style: none;\n        padding: 0;\n        display: flex;\n        gap: 8px;\n        margin: 32px 0 0;\n      }\n\n      #next-steps ul .logo {\n        height: 18px;\n      }\n\n      #next-steps ul .logo svg {\n        height: 100%;\n        width: auto;\n      }\n\n      #next-steps ul a {\n        color: var(--text-h);\n        font-size: 16px;\n        border-radius: 6px;\n        background: var(--social-bg);\n        display: flex;\n        padding: 6px 12px;\n        align-items: center;\n        gap: 8px;\n        text-decoration: none;\n        transition: box-shadow 0.3s;\n      }\n\n      #next-steps ul a:hover {\n        box-shadow: var(--shadow);\n      }\n\n      #next-steps ul .button-icon {\n        height: 18px;\n        width: 18px;\n      }\n\n      #spacer {\n        height: 88px;\n        border-top: 1px solid var(--border);\n      }\n\n      .ticks {\n        position: relative;\n        width: 100%;\n      }\n\n      .ticks::before,\n      .ticks::after {\n        content: '';\n        position: absolute;\n        top: -4.5px;\n        border: 5px solid transparent;\n      }\n\n      .ticks::before {\n        left: 0;\n        border-left-color: var(--border);\n      }\n\n      .ticks::after {\n        right: 0;\n        border-right-color: var(--border);\n      }\n\n      @media (max-width: 1024px) {\n        :host {\n          font-size: 16px;\n          width: 100%;\n          max-width: 100%;\n        }\n\n        h1,\n        ::slotted(h1) {\n          font-size: 36px;\n          margin: 20px 0;\n        }\n\n        h2,\n        ::slotted(h2) {\n          font-size: 20px;\n        }\n\n        #center {\n          padding: 32px 20px 24px;\n          gap: 18px;\n        }\n\n        #next-steps {\n          flex-direction: column;\n          text-align: center;\n        }\n\n        #next-steps > div {\n          padding: 24px 20px;\n        }\n\n        #docs {\n          border-right: none;\n          border-bottom: 1px solid var(--border);\n        }\n\n        #next-steps ul {\n          margin-top: 20px;\n          flex-wrap: wrap;\n          justify-content: center;\n        }\n\n        #next-steps ul li {\n          flex: 1 1 calc(50% - 8px);\n        }\n\n        #next-steps ul a {\n          width: 100%;\n          justify-content: center;\n          box-sizing: border-box;\n        }\n\n        #spacer {\n          height: 48px;\n        }\n      }\n    `\n  }\n}\n\nwindow.customElements.define('my-element', MyElement)\n"
  },
  {
    "path": "packages/create-vite/template-lit-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-lit-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Lit + TS</title>\n    <link rel=\"stylesheet\" href=\"./src/index.css\" />\n    <script type=\"module\" src=\"/src/my-element.ts\"></script>\n  </head>\n  <body>\n    <my-element>\n      <h1>Get started</h1>\n    </my-element>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-lit-ts/package.json",
    "content": "{\n  \"name\": \"vite-lit-ts-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"lit\": \"^3.3.2\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-lit-ts/src/index.css",
    "content": ":root {\n  color-scheme: light dark;\n  background-color: #ffffff;\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    background-color: #16171d;\n  }\n}\n\nbody {\n  margin: 0;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  min-width: 320px;\n  min-height: 100svh;\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  overflow-x: hidden;\n}\n"
  },
  {
    "path": "packages/create-vite/template-lit-ts/src/my-element.ts",
    "content": "import { LitElement, css, html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport litLogo from './assets/lit.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\n\n/**\n * An example element.\n *\n * @slot - This element has a slot\n * @csspart button - The button\n */\n@customElement('my-element')\nexport class MyElement extends LitElement {\n  /**\n   * The number of times the button has been clicked.\n   */\n  @property({ type: Number })\n  count = 0\n\n  render() {\n    return html`\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src=${heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src=${litLogo} class=\"framework\" alt=\"Lit logo\" />\n          <img src=${viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <slot></slot>\n          <p>\n            Edit <code>src/my-element.ts</code> and save to test\n            <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" @click=${this._onClick} part=\"button\">\n          Count is ${this.count}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src=${viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://lit.dev/\" target=\"_blank\">\n                <img class=\"button-icon\" src=${litLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    `\n  }\n\n  private _onClick() {\n    this.count++\n  }\n\n  static styles = css`\n    :host {\n      --text: #6b6375;\n      --text-h: #08060d;\n      --bg: #fff;\n      --border: #e5e4e7;\n      --code-bg: #f4f3ec;\n      --accent: #aa3bff;\n      --accent-bg: rgba(170, 59, 255, 0.1);\n      --accent-border: rgba(170, 59, 255, 0.5);\n      --social-bg: rgba(244, 243, 236, 0.5);\n      --shadow:\n        rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n      --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n      --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n      --mono: ui-monospace, Consolas, monospace;\n\n      font: 18px/145% var(--sans);\n      letter-spacing: 0.18px;\n\n      width: 1126px;\n      max-width: 100%;\n      margin: 0 auto;\n      text-align: center;\n      border-inline: 1px solid var(--border);\n      min-height: 100svh;\n      display: flex;\n      flex-direction: column;\n      box-sizing: border-box;\n      color: var(--text);\n    }\n\n    @media (prefers-color-scheme: dark) {\n      :host {\n        --text: #9ca3af;\n        --text-h: #f3f4f6;\n        --bg: #16171d;\n        --border: #2e303a;\n        --code-bg: #1f2028;\n        --accent: #c084fc;\n        --accent-bg: rgba(192, 132, 252, 0.15);\n        --accent-border: rgba(192, 132, 252, 0.5);\n        --social-bg: rgba(47, 48, 58, 0.5);\n        --shadow:\n          rgba(0, 0, 0, 0.4) 0 10px 15px -3px,\n          rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n      }\n\n      #social .button-icon {\n        filter: invert(1) brightness(2);\n      }\n    }\n\n    h1,\n    h2,\n    ::slotted(h1),\n    ::slotted(h2) {\n      font-family: var(--heading);\n      font-weight: 500;\n      color: var(--text-h);\n    }\n\n    h1,\n    ::slotted(h1) {\n      font-size: 56px;\n      letter-spacing: -1.68px;\n      margin: 32px 0;\n    }\n\n    h2 {\n      font-size: 24px;\n      line-height: 118%;\n      letter-spacing: -0.24px;\n      margin: 0 0 8px;\n    }\n\n    p {\n      margin: 0;\n    }\n\n    code {\n      font-family: var(--mono);\n      font-size: 15px;\n      line-height: 135%;\n      display: inline-flex;\n      padding: 4px 8px;\n      border-radius: 4px;\n      color: var(--text-h);\n      background: var(--code-bg);\n    }\n\n    .counter {\n      font-family: var(--mono);\n      font-size: 16px;\n      display: inline-flex;\n      padding: 5px 10px;\n      border-radius: 5px;\n      color: var(--accent);\n      background: var(--accent-bg);\n      border: 2px solid transparent;\n      transition: border-color 0.3s;\n      margin-bottom: 24px;\n      cursor: pointer;\n    }\n\n    .counter:hover {\n      border-color: var(--accent-border);\n    }\n\n    .counter:focus-visible {\n      outline: 2px solid var(--accent);\n      outline-offset: 2px;\n    }\n\n    .hero {\n      position: relative;\n    }\n\n    .hero .base,\n    .hero .framework,\n    .hero .vite {\n      inset-inline: 0;\n      margin: 0 auto;\n    }\n\n    .hero .base {\n      width: 170px;\n      position: relative;\n      z-index: 0;\n    }\n\n    .hero .framework,\n    .hero .vite {\n      position: absolute;\n    }\n\n    .hero .framework {\n      z-index: 1;\n      top: 34px;\n      height: 28px;\n      transform: perspective(2000px) rotateZ(300deg) rotateX(44deg)\n        rotateY(39deg) scale(1.4);\n    }\n\n    .hero .vite {\n      z-index: 0;\n      top: 107px;\n      height: 26px;\n      width: auto;\n      color: var(--vite-logo);\n      transform: perspective(2000px) rotateZ(300deg) rotateX(40deg)\n        rotateY(39deg) scale(0.8);\n    }\n\n    #center {\n      display: flex;\n      flex-direction: column;\n      gap: 25px;\n      place-content: center;\n      place-items: center;\n      flex-grow: 1;\n    }\n\n    #next-steps {\n      display: flex;\n      border-top: 1px solid var(--border);\n      text-align: left;\n    }\n\n    #next-steps > div {\n      flex: 1 1 0;\n      padding: 32px;\n    }\n\n    #next-steps .icon {\n      margin-bottom: 16px;\n      width: 22px;\n      height: 22px;\n    }\n\n    #docs {\n      border-right: 1px solid var(--border);\n    }\n\n    #next-steps ul {\n      list-style: none;\n      padding: 0;\n      display: flex;\n      gap: 8px;\n      margin: 32px 0 0;\n    }\n\n    #next-steps ul .logo {\n      height: 18px;\n    }\n\n    #next-steps ul .logo svg {\n      height: 100%;\n      width: auto;\n    }\n\n    #next-steps ul a {\n      color: var(--text-h);\n      font-size: 16px;\n      border-radius: 6px;\n      background: var(--social-bg);\n      display: flex;\n      padding: 6px 12px;\n      align-items: center;\n      gap: 8px;\n      text-decoration: none;\n      transition: box-shadow 0.3s;\n    }\n\n    #next-steps ul a:hover {\n      box-shadow: var(--shadow);\n    }\n\n    #next-steps ul .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n\n    #spacer {\n      height: 88px;\n      border-top: 1px solid var(--border);\n    }\n\n    .ticks {\n      position: relative;\n      width: 100%;\n    }\n\n    .ticks::before,\n    .ticks::after {\n      content: '';\n      position: absolute;\n      top: -4.5px;\n      border: 5px solid transparent;\n    }\n\n    .ticks::before {\n      left: 0;\n      border-left-color: var(--border);\n    }\n\n    .ticks::after {\n      right: 0;\n      border-right-color: var(--border);\n    }\n\n    @media (max-width: 1024px) {\n      :host {\n        font-size: 16px;\n        width: 100%;\n        max-width: 100%;\n      }\n\n      h1,\n      ::slotted(h1) {\n        font-size: 36px;\n        margin: 20px 0;\n      }\n\n      h2,\n      ::slotted(h2) {\n        font-size: 20px;\n      }\n\n      #center {\n        padding: 32px 20px 24px;\n        gap: 18px;\n      }\n\n      #next-steps {\n        flex-direction: column;\n        text-align: center;\n      }\n\n      #next-steps > div {\n        padding: 24px 20px;\n      }\n\n      #docs {\n        border-right: none;\n        border-bottom: 1px solid var(--border);\n      }\n\n      #next-steps ul {\n        margin-top: 20px;\n        flex-wrap: wrap;\n        justify-content: center;\n      }\n\n      #next-steps ul li {\n        flex: 1 1 calc(50% - 8px);\n      }\n\n      #next-steps ul a {\n        width: 100%;\n        justify-content: center;\n        box-sizing: border-box;\n      }\n\n      #spacer {\n        height: 48px;\n      }\n    }\n  `\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'my-element': MyElement\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-lit-ts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2023\",\n    \"experimentalDecorators\": true,\n    \"useDefineForClassFields\": false,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-preact/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Preact</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-preact/package.json",
    "content": "{\n  \"name\": \"vite-preact-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"preact\": \"^10.29.0\"\n  },\n  \"devDependencies\": {\n    \"@preact/preset-vite\": \"^2.10.4\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact/src/app.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact/src/app.jsx",
    "content": "import { useState } from 'preact/hooks'\nimport preactLogo from './assets/preact.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './app.css'\n\nexport function App() {\n  const [count, setCount] = useState(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={preactLogo} class=\"framework\" alt=\"Preact logo\" />\n          <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/app.jsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" onClick={() => setCount((count) => count + 1)}>\n          Count is {count}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://preactjs.com/\" target=\"_blank\">\n                <img class=\"button-icon\" src={preactLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact/src/main.jsx",
    "content": "import { render } from 'preact'\nimport './index.css'\nimport { App } from './app.jsx'\n\nrender(<App />, document.getElementById('app'))\n"
  },
  {
    "path": "packages/create-vite/template-preact/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport preact from '@preact/preset-vite'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [preact()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Preact + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/package.json",
    "content": "{\n  \"name\": \"vite-preact-ts-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc -b && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"preact\": \"^10.29.0\"\n  },\n  \"devDependencies\": {\n    \"@preact/preset-vite\": \"^2.10.4\",\n    \"@types/node\": \"^24.12.0\",\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/src/app.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/src/app.tsx",
    "content": "import { useState } from 'preact/hooks'\nimport preactLogo from './assets/preact.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './app.css'\n\nexport function App() {\n  const [count, setCount] = useState(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={preactLogo} class=\"framework\" alt=\"Preact logo\" />\n          <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/app.tsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" onClick={() => setCount((count) => count + 1)}>\n          Count is {count}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://preactjs.com/\" target=\"_blank\">\n                <img class=\"button-icon\" src={preactLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/src/main.tsx",
    "content": "import { render } from 'preact'\nimport './index.css'\nimport { App } from './app.tsx'\n\nrender(<App />, document.getElementById('app')!)\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n    \"paths\": {\n      \"react\": [\"./node_modules/preact/compat/\"],\n      \"react-dom\": [\"./node_modules/preact/compat/\"]\n    },\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"preact\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ]\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"node\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-preact-ts/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport preact from '@preact/preset-vite'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [preact()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-qwik/README.md",
    "content": "# Qwik + Vite\n\n## Qwik in CSR mode\n\nThis starter is using a pure CSR (Client-Side Rendering) mode. This means, that the application is fully bootstrapped in the browser. Most of Qwik innovations however take advantage of SSR (Server-Side Rendering) mode.\n\n```ts\nexport default defineConfig({\n  plugins: [\n    qwikVite({\n      csr: true,\n    }),\n  ],\n})\n```\n\nUse `npm create qwik@latest` to create a full production ready Qwik application, using SSR and [QwikCity](https://qwik.dev/docs/qwikcity/), our server-side metaframwork.\n\n## Usage\n\n```bash\n$ npm install # or pnpm install or yarn install\n```\n\nLearn more on the [Qwik Website](https://qwik.dev) and join our community on our [Discord](https://qwik.dev/chat)\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `npm run dev`\n\nRuns the app in the development mode.<br>\nOpen [http://localhost:5173](http://localhost:5173) to view it in the browser.\n\n### `npm run build`\n\nBuilds the app for production to the `dist` folder.<br>\n"
  },
  {
    "path": "packages/create-vite/template-qwik/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-qwik/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Qwik</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-qwik/package.json",
    "content": "{\n  \"name\": \"vite-qwik\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"serve dist\"\n  },\n  \"devDependencies\": {\n    \"serve\": \"^14.2.6\",\n    \"vite\": \"^8.0.1\"\n  },\n  \"dependencies\": {\n    \"@builder.io/qwik\": \"^1.19.2\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik/src/app.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik/src/app.jsx",
    "content": "import { component$, useSignal } from '@builder.io/qwik'\n\nimport qwikLogo from './assets/qwik.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './app.css'\n\nexport const App = component$(() => {\n  const count = useSignal(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={qwikLogo} class=\"framework\" alt=\"Qwik logo\" />\n          <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/app.jsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" onClick$={() => count.value++}>\n          Count is {count.value}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://qwik.dev/\" target=\"_blank\">\n                <img class=\"button-icon\" src={qwikLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n})\n"
  },
  {
    "path": "packages/create-vite/template-qwik/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik/src/main.jsx",
    "content": "import '@builder.io/qwik/qwikloader.js'\n\nimport { render } from '@builder.io/qwik'\nimport './index.css'\nimport { App } from './app.jsx'\n\nrender(document.getElementById('app'), <App />)\n"
  },
  {
    "path": "packages/create-vite/template-qwik/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport { qwikVite } from '@builder.io/qwik/optimizer'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [\n    qwikVite({\n      csr: true,\n    }),\n  ],\n})\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/README.md",
    "content": "# Qwik + Vite\n\n## Qwik in CSR mode\n\nThis starter is using a pure CSR (Client-Side Rendering) mode. This means, that the application is fully bootstrapped in the browser. Most of Qwik innovations however take advantage of SSR (Server-Side Rendering) mode.\n\n```ts\nexport default defineConfig({\n  plugins: [\n    qwikVite({\n      csr: true,\n    }),\n  ],\n})\n```\n\nUse `npm create qwik@latest` to create a full production ready Qwik application, using SSR and [QwikCity](https://qwik.dev/docs/qwikcity/), our server-side metaframwork.\n\n## Usage\n\n```bash\n$ npm install # or pnpm install or yarn install\n```\n\nLearn more on the [Qwik Website](https://qwik.dev) and join our community on our [Discord](https://qwik.dev/chat)\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `npm run dev`\n\nRuns the app in the development mode.<br>\nOpen [http://localhost:5173](http://localhost:5173) to view it in the browser.\n\n### `npm run build`\n\nBuilds the app for production to the `dist` folder.<br>\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Qwik + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/package.json",
    "content": "{\n  \"name\": \"vite-qwik\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc -b && vite build\",\n    \"preview\": \"serve dist\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.12.0\",\n    \"serve\": \"^14.2.6\",\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\"\n  },\n  \"dependencies\": {\n    \"@builder.io/qwik\": \"^1.19.2\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/src/app.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/src/app.tsx",
    "content": "import { component$, useSignal } from '@builder.io/qwik'\n\nimport qwikLogo from './assets/qwik.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './app.css'\n\nexport const App = component$(() => {\n  const count = useSignal(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={qwikLogo} class=\"framework\" alt=\"Qwik logo\" />\n          <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/app.tsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" onClick$={() => count.value++}>\n          Count is {count.value}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://qwik.dev/\" target=\"_blank\">\n                <img class=\"button-icon\" src={qwikLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n})\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/src/main.tsx",
    "content": "import '@builder.io/qwik/qwikloader.js'\n\nimport { render } from '@builder.io/qwik'\nimport './index.css'\nimport { App } from './app.tsx'\n\nrender(document.getElementById('app') as HTMLElement, <App />)\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"@builder.io/qwik\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ]\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"node\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-qwik-ts/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { qwikVite } from '@builder.io/qwik/optimizer'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [\n    qwikVite({\n      csr: true,\n    }),\n  ],\n})\n"
  },
  {
    "path": "packages/create-vite/template-react/README.md",
    "content": "# React + Vite\n\nThis template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.\n\nCurrently, two official plugins are available:\n\n- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)\n- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)\n\n## React Compiler\n\nThe React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).\n\n## Expanding the ESLint configuration\n\nIf you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.\n"
  },
  {
    "path": "packages/create-vite/template-react/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-react/eslint.config.js",
    "content": "import js from '@eslint/js'\nimport globals from 'globals'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport reactRefresh from 'eslint-plugin-react-refresh'\nimport { defineConfig, globalIgnores } from 'eslint/config'\n\nexport default defineConfig([\n  globalIgnores(['dist']),\n  {\n    files: ['**/*.{js,jsx}'],\n    extends: [\n      js.configs.recommended,\n      reactHooks.configs.flat.recommended,\n      reactRefresh.configs.vite,\n    ],\n    languageOptions: {\n      ecmaVersion: 2020,\n      globals: globals.browser,\n      parserOptions: {\n        ecmaVersion: 'latest',\n        ecmaFeatures: { jsx: true },\n        sourceType: 'module',\n      },\n    },\n    rules: {\n      'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],\n    },\n  },\n])\n"
  },
  {
    "path": "packages/create-vite/template-react/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + React</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-react/package.json",
    "content": "{\n  \"name\": \"vite-react-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"lint\": \"eslint .\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"react\": \"^19.2.4\",\n    \"react-dom\": \"^19.2.4\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.39.4\",\n    \"@types/react\": \"^19.2.14\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"@vitejs/plugin-react\": \"^6.0.1\",\n    \"eslint\": \"^9.39.4\",\n    \"eslint-plugin-react-hooks\": \"^7.0.1\",\n    \"eslint-plugin-react-refresh\": \"^0.5.2\",\n    \"globals\": \"^17.4.0\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-react/src/App.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-react/src/App.jsx",
    "content": "import { useState } from 'react'\nimport reactLogo from './assets/react.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './App.css'\n\nfunction App() {\n  const [count, setCount] = useState(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div className=\"hero\">\n          <img src={heroImg} className=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={reactLogo} className=\"framework\" alt=\"React logo\" />\n          <img src={viteLogo} className=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/App.jsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button\n          className=\"counter\"\n          onClick={() => setCount((count) => count + 1)}\n        >\n          Count is {count}\n        </button>\n      </section>\n\n      <div className=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg className=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img className=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://react.dev/\" target=\"_blank\">\n                <img className=\"button-icon\" src={reactLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg className=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div className=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "packages/create-vite/template-react/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-react/src/main.jsx",
    "content": "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport './index.css'\nimport App from './App.jsx'\n\ncreateRoot(document.getElementById('root')).render(\n  <StrictMode>\n    <App />\n  </StrictMode>,\n)\n"
  },
  {
    "path": "packages/create-vite/template-react/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/README.md",
    "content": "# React + TypeScript + Vite\n\nThis template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.\n\nCurrently, two official plugins are available:\n\n- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)\n- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)\n\n## React Compiler\n\nThe React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).\n\n## Expanding the ESLint configuration\n\nIf you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:\n\n```js\nexport default defineConfig([\n  globalIgnores(['dist']),\n  {\n    files: ['**/*.{ts,tsx}'],\n    extends: [\n      // Other configs...\n\n      // Remove tseslint.configs.recommended and replace with this\n      tseslint.configs.recommendedTypeChecked,\n      // Alternatively, use this for stricter rules\n      tseslint.configs.strictTypeChecked,\n      // Optionally, add this for stylistic rules\n      tseslint.configs.stylisticTypeChecked,\n\n      // Other configs...\n    ],\n    languageOptions: {\n      parserOptions: {\n        project: ['./tsconfig.node.json', './tsconfig.app.json'],\n        tsconfigRootDir: import.meta.dirname,\n      },\n      // other options...\n    },\n  },\n])\n```\n\nYou can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:\n\n```js\n// eslint.config.js\nimport reactX from 'eslint-plugin-react-x'\nimport reactDom from 'eslint-plugin-react-dom'\n\nexport default defineConfig([\n  globalIgnores(['dist']),\n  {\n    files: ['**/*.{ts,tsx}'],\n    extends: [\n      // Other configs...\n      // Enable lint rules for React\n      reactX.configs['recommended-typescript'],\n      // Enable lint rules for React DOM\n      reactDom.configs.recommended,\n    ],\n    languageOptions: {\n      parserOptions: {\n        project: ['./tsconfig.node.json', './tsconfig.app.json'],\n        tsconfigRootDir: import.meta.dirname,\n      },\n      // other options...\n    },\n  },\n])\n```\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/eslint.config.js",
    "content": "import js from '@eslint/js'\nimport globals from 'globals'\nimport reactHooks from 'eslint-plugin-react-hooks'\nimport reactRefresh from 'eslint-plugin-react-refresh'\nimport tseslint from 'typescript-eslint'\nimport { defineConfig, globalIgnores } from 'eslint/config'\n\nexport default defineConfig([\n  globalIgnores(['dist']),\n  {\n    files: ['**/*.{ts,tsx}'],\n    extends: [\n      js.configs.recommended,\n      tseslint.configs.recommended,\n      reactHooks.configs.flat.recommended,\n      reactRefresh.configs.vite,\n    ],\n    languageOptions: {\n      ecmaVersion: 2020,\n      globals: globals.browser,\n    },\n  },\n])\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + React + TS</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/package.json",
    "content": "{\n  \"name\": \"vite-react-typescript-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc -b && vite build\",\n    \"lint\": \"eslint .\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"react\": \"^19.2.4\",\n    \"react-dom\": \"^19.2.4\"\n  },\n  \"devDependencies\": {\n    \"@eslint/js\": \"^9.39.4\",\n    \"@types/node\": \"^24.12.0\",\n    \"@types/react\": \"^19.2.14\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"@vitejs/plugin-react\": \"^6.0.1\",\n    \"eslint\": \"^9.39.4\",\n    \"eslint-plugin-react-hooks\": \"^7.0.1\",\n    \"eslint-plugin-react-refresh\": \"^0.5.2\",\n    \"globals\": \"^17.4.0\",\n    \"typescript\": \"~5.9.3\",\n    \"typescript-eslint\": \"^8.57.0\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/src/App.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/src/App.tsx",
    "content": "import { useState } from 'react'\nimport reactLogo from './assets/react.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './App.css'\n\nfunction App() {\n  const [count, setCount] = useState(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div className=\"hero\">\n          <img src={heroImg} className=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={reactLogo} className=\"framework\" alt=\"React logo\" />\n          <img src={viteLogo} className=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/App.tsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button\n          className=\"counter\"\n          onClick={() => setCount((count) => count + 1)}\n        >\n          Count is {count}\n        </button>\n      </section>\n\n      <div className=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg className=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img className=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://react.dev/\" target=\"_blank\">\n                <img className=\"button-icon\" src={reactLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg className=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg\n                  className=\"button-icon\"\n                  role=\"presentation\"\n                  aria-hidden=\"true\"\n                >\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div className=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/src/main.tsx",
    "content": "import { StrictMode } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport './index.css'\nimport App from './App.tsx'\n\ncreateRoot(document.getElementById('root')!).render(\n  <StrictMode>\n    <App />\n  </StrictMode>,\n)\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ]\n}\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"node\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-react-ts/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [react()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-solid/README.md",
    "content": "## Usage\n\n```bash\n$ npm install # or pnpm install or yarn install\n```\n\n### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `npm run dev`\n\nRuns the app in the development mode.<br>\nOpen [http://localhost:5173](http://localhost:5173) to view it in the browser.\n\n### `npm run build`\n\nBuilds the app for production to the `dist` folder.<br>\nIt correctly bundles Solid in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.<br>\nYour app is ready to be deployed!\n\n## Deployment\n\nLearn more about deploying your application with the [documentations](https://vite.dev/guide/static-deploy.html)\n"
  },
  {
    "path": "packages/create-vite/template-solid/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-solid/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Solid</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.jsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-solid/package.json",
    "content": "{\n  \"name\": \"vite-solid-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"solid-js\": \"^1.9.11\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"^8.0.1\",\n    \"vite-plugin-solid\": \"^2.11.11\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid/src/App.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid/src/App.jsx",
    "content": "import { createSignal } from 'solid-js'\nimport solidLogo from './assets/solid.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './App.css'\n\nfunction App() {\n  const [count, setCount] = createSignal(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={solidLogo} class=\"framework\" alt=\"Solid logo\" />\n          <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/App.jsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" onClick={() => setCount((count) => count + 1)}>\n          Count is {count()}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://solidjs.com/\" target=\"_blank\">\n                <img class=\"button-icon\" src={solidLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "packages/create-vite/template-solid/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid/src/index.jsx",
    "content": "/* @refresh reload */\nimport { render } from 'solid-js/web'\nimport './index.css'\nimport App from './App.jsx'\n\nconst root = document.getElementById('root')\n\nrender(() => <App />, root)\n"
  },
  {
    "path": "packages/create-vite/template-solid/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/README.md",
    "content": "## Usage\n\n```bash\n$ npm install # or pnpm install or yarn install\n```\n\n### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `npm run dev`\n\nRuns the app in the development mode.<br>\nOpen [http://localhost:5173](http://localhost:5173) to view it in the browser.\n\n### `npm run build`\n\nBuilds the app for production to the `dist` folder.<br>\nIt correctly bundles Solid in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.<br>\nYour app is ready to be deployed!\n\n## Deployment\n\nLearn more about deploying your application with the [documentations](https://vite.dev/guide/static-deploy.html)\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Solid + TS</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/package.json",
    "content": "{\n  \"name\": \"vite-solid-typescript-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc -b && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"solid-js\": \"^1.9.11\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.12.0\",\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\",\n    \"vite-plugin-solid\": \"^2.11.11\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/src/App.css",
    "content": ".counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/src/App.tsx",
    "content": "import { createSignal } from 'solid-js'\nimport solidLogo from './assets/solid.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport './App.css'\n\nfunction App() {\n  const [count, setCount] = createSignal(0)\n\n  return (\n    <>\n      <section id=\"center\">\n        <div class=\"hero\">\n          <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n          <img src={solidLogo} class=\"framework\" alt=\"Solid logo\" />\n          <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n        </div>\n        <div>\n          <h1>Get started</h1>\n          <p>\n            Edit <code>src/App.tsx</code> and save to test <code>HMR</code>\n          </p>\n        </div>\n        <button class=\"counter\" onClick={() => setCount((count) => count + 1)}>\n          Count is {count()}\n        </button>\n      </section>\n\n      <div class=\"ticks\"></div>\n\n      <section id=\"next-steps\">\n        <div id=\"docs\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#documentation-icon\"></use>\n          </svg>\n          <h2>Documentation</h2>\n          <p>Your questions, answered</p>\n          <ul>\n            <li>\n              <a href=\"https://vite.dev/\" target=\"_blank\">\n                <img class=\"logo\" src={viteLogo} alt=\"\" />\n                Explore Vite\n              </a>\n            </li>\n            <li>\n              <a href=\"https://solidjs.com/\" target=\"_blank\">\n                <img class=\"button-icon\" src={solidLogo} alt=\"\" />\n                Learn more\n              </a>\n            </li>\n          </ul>\n        </div>\n        <div id=\"social\">\n          <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#social-icon\"></use>\n          </svg>\n          <h2>Connect with us</h2>\n          <p>Join the Vite community</p>\n          <ul>\n            <li>\n              <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#github-icon\"></use>\n                </svg>\n                GitHub\n              </a>\n            </li>\n            <li>\n              <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#discord-icon\"></use>\n                </svg>\n                Discord\n              </a>\n            </li>\n            <li>\n              <a href=\"https://x.com/vite_js\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#x-icon\"></use>\n                </svg>\n                X.com\n              </a>\n            </li>\n            <li>\n              <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n                <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n                  <use href=\"/icons.svg#bluesky-icon\"></use>\n                </svg>\n                Bluesky\n              </a>\n            </li>\n          </ul>\n        </div>\n      </section>\n\n      <div class=\"ticks\"></div>\n      <section id=\"spacer\"></section>\n    </>\n  )\n}\n\nexport default App\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/src/index.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\n#root {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/src/index.tsx",
    "content": "/* @refresh reload */\nimport { render } from 'solid-js/web'\nimport './index.css'\nimport App from './App.tsx'\n\nconst root = document.getElementById('root')\n\nrender(() => <App />, root!)\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/tsconfig.app.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"preserve\",\n    \"jsxImportSource\": \"solid-js\",\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ]\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"node\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-solid-ts/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport solid from 'vite-plugin-solid'\n\nexport default defineConfig({\n  plugins: [solid()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-svelte/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"svelte.svelte-vscode\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte/README.md",
    "content": "# Svelte + Vite\n\nThis template should help get you started developing with Svelte in Vite.\n\n## Recommended IDE Setup\n\n[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).\n\n## Need an official Svelte framework?\n\nCheck out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.\n\n## Technical considerations\n\n**Why use this over SvelteKit?**\n\n- It brings its own routing solution which might not be preferable for some users.\n- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.\n\nThis template contains as little as possible to get started with Vite + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.\n\nShould you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.\n\n**Why include `.vscode/extensions.json`?**\n\nOther templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.\n\n**Why enable `checkJs` in the JS template?**\n\nIt is likely that most cases of changing variable types in runtime are likely to be accidental, rather than deliberate. This provides advanced typechecking out of the box. Should you like to take advantage of the dynamically-typed nature of JavaScript, it is trivial to change the configuration.\n\n**Why is HMR not preserving my local component state?**\n\nHMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/sveltejs/svelte-hmr/tree/master/packages/svelte-hmr#preservation-of-local-state).\n\nIf you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.\n\n```js\n// store.js\n// An extremely simple external store\nimport { writable } from 'svelte/store'\nexport default writable(0)\n```\n"
  },
  {
    "path": "packages/create-vite/template-svelte/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-svelte/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Svelte</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-svelte/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"moduleResolution\": \"bundler\",\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    /**\n     * svelte-preprocess cannot figure out whether you have\n     * a value or a type, so tell TypeScript to enforce using\n     * `import type` instead of `import` for Types.\n     */\n    \"verbatimModuleSyntax\": true,\n    \"isolatedModules\": true,\n    \"resolveJsonModule\": true,\n    /**\n     * To have warnings / errors of the Svelte compiler at the\n     * correct position, enable source maps by default.\n     */\n    \"sourceMap\": true,\n    \"esModuleInterop\": true,\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n    /**\n     * Typecheck JS in `.svelte` and `.js` files by default.\n     * Disable this if you'd like to use dynamic types.\n     */\n    \"checkJs\": true\n  },\n  /**\n   * Use global.d.ts instead of compilerOptions.types\n   * to avoid limiting type declarations.\n   */\n  \"include\": [\"src/**/*.d.ts\", \"src/**/*.js\", \"src/**/*.svelte\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte/package.json",
    "content": "{\n  \"name\": \"vite-svelte-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/vite-plugin-svelte\": \"^7.0.0\",\n    \"svelte\": \"^5.53.12\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte/src/App.svelte",
    "content": "<script>\n  import svelteLogo from './assets/svelte.svg'\n  import viteLogo from './assets/vite.svg'\n  import heroImg from './assets/hero.png'\n  import Counter from './lib/Counter.svelte'\n</script>\n\n<section id=\"center\">\n  <div class=\"hero\">\n    <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n    <img src={svelteLogo} class=\"framework\" alt=\"Svelte logo\" />\n    <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n  </div>\n  <div>\n    <h1>Get started</h1>\n    <p>Edit <code>src/App.svelte</code> and save to test <code>HMR</code></p>\n  </div>\n  <Counter />\n</section>\n\n<div class=\"ticks\"></div>\n\n<section id=\"next-steps\">\n  <div id=\"docs\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n      <use href=\"/icons.svg#documentation-icon\"></use>\n    </svg>\n    <h2>Documentation</h2>\n    <p>Your questions, answered</p>\n    <ul>\n      <li>\n        <a href=\"https://vite.dev/\" target=\"_blank\" rel=\"noreferrer\">\n          <img class=\"logo\" src={viteLogo} alt=\"\" />\n          Explore Vite\n        </a>\n      </li>\n      <li>\n        <a href=\"https://svelte.dev/\" target=\"_blank\" rel=\"noreferrer\">\n          <img class=\"button-icon\" src={svelteLogo} alt=\"\" />\n          Learn more\n        </a>\n      </li>\n    </ul>\n  </div>\n  <div id=\"social\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n      <use href=\"/icons.svg#social-icon\"></use>\n    </svg>\n    <h2>Connect with us</h2>\n    <p>Join the Vite community</p>\n    <ul>\n      <li>\n        <a href=\"https://github.com/vitejs/vite\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#github-icon\"></use>\n          </svg>\n          GitHub\n        </a>\n      </li>\n      <li>\n        <a href=\"https://chat.vite.dev/\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#discord-icon\"></use>\n          </svg>\n          Discord\n        </a>\n      </li>\n      <li>\n        <a href=\"https://x.com/vite_js\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#x-icon\"></use>\n          </svg>\n          X.com\n        </a>\n      </li>\n      <li>\n        <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#bluesky-icon\"></use>\n          </svg>\n          Bluesky\n        </a>\n      </li>\n    </ul>\n  </div>\n</section>\n\n<div class=\"ticks\"></div>\n<section id=\"spacer\"></section>\n"
  },
  {
    "path": "packages/create-vite/template-svelte/src/app.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n\n.counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte/src/lib/Counter.svelte",
    "content": "<script>\n  let count = $state(0)\n</script>\n\n<button class=\"counter\" onclick={() => count++}>Count is {count}</button>\n"
  },
  {
    "path": "packages/create-vite/template-svelte/src/main.js",
    "content": "import { mount } from 'svelte'\nimport './app.css'\nimport App from './App.svelte'\n\nconst app = mount(App, {\n  target: document.getElementById('app'),\n})\n\nexport default app\n"
  },
  {
    "path": "packages/create-vite/template-svelte/svelte.config.js",
    "content": "/** @type {import(\"@sveltejs/vite-plugin-svelte\").SvelteConfig} */\nexport default {}\n"
  },
  {
    "path": "packages/create-vite/template-svelte/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport { svelte } from '@sveltejs/vite-plugin-svelte'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [svelte()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"svelte.svelte-vscode\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/README.md",
    "content": "# Svelte + TS + Vite\n\nThis template should help get you started developing with Svelte and TypeScript in Vite.\n\n## Recommended IDE Setup\n\n[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).\n\n## Need an official Svelte framework?\n\nCheck out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more.\n\n## Technical considerations\n\n**Why use this over SvelteKit?**\n\n- It brings its own routing solution which might not be preferable for some users.\n- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app.\n\nThis template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project.\n\nShould you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate.\n\n**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?**\n\nSetting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information.\n\n**Why include `.vscode/extensions.json`?**\n\nOther templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project.\n\n**Why enable `allowJs` in the TS template?**\n\nWhile `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant.\n\n**Why is HMR not preserving my local component state?**\n\nHMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr).\n\nIf you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR.\n\n```ts\n// store.ts\n// An extremely simple external store\nimport { writable } from 'svelte/store'\nexport default writable(0)\n```\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Svelte + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/package.json",
    "content": "{\n  \"name\": \"vite-svelte-ts-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\",\n    \"check\": \"svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json\"\n  },\n  \"devDependencies\": {\n    \"@sveltejs/vite-plugin-svelte\": \"^7.0.0\",\n    \"@tsconfig/svelte\": \"^5.0.8\",\n    \"@types/node\": \"^24.12.0\",\n    \"svelte\": \"^5.53.12\",\n    \"svelte-check\": \"^4.4.5\",\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/src/App.svelte",
    "content": "<script>\n  import svelteLogo from './assets/svelte.svg'\n  import viteLogo from './assets/vite.svg'\n  import heroImg from './assets/hero.png'\n  import Counter from './lib/Counter.svelte'\n</script>\n\n<section id=\"center\">\n  <div class=\"hero\">\n    <img src={heroImg} class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n    <img src={svelteLogo} class=\"framework\" alt=\"Svelte logo\" />\n    <img src={viteLogo} class=\"vite\" alt=\"Vite logo\" />\n  </div>\n  <div>\n    <h1>Get started</h1>\n    <p>Edit <code>src/App.svelte</code> and save to test <code>HMR</code></p>\n  </div>\n  <Counter />\n</section>\n\n<div class=\"ticks\"></div>\n\n<section id=\"next-steps\">\n  <div id=\"docs\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n      <use href=\"/icons.svg#documentation-icon\"></use>\n    </svg>\n    <h2>Documentation</h2>\n    <p>Your questions, answered</p>\n    <ul>\n      <li>\n        <a href=\"https://vite.dev/\" target=\"_blank\" rel=\"noreferrer\">\n          <img class=\"logo\" src={viteLogo} alt=\"\" />\n          Explore Vite\n        </a>\n      </li>\n      <li>\n        <a href=\"https://svelte.dev/\" target=\"_blank\" rel=\"noreferrer\">\n          <img class=\"button-icon\" src={svelteLogo} alt=\"\" />\n          Learn more\n        </a>\n      </li>\n    </ul>\n  </div>\n  <div id=\"social\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n      <use href=\"/icons.svg#social-icon\"></use>\n    </svg>\n    <h2>Connect with us</h2>\n    <p>Join the Vite community</p>\n    <ul>\n      <li>\n        <a href=\"https://github.com/vitejs/vite\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#github-icon\"></use>\n          </svg>\n          GitHub\n        </a>\n      </li>\n      <li>\n        <a href=\"https://chat.vite.dev/\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#discord-icon\"></use>\n          </svg>\n          Discord\n        </a>\n      </li>\n      <li>\n        <a href=\"https://x.com/vite_js\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#x-icon\"></use>\n          </svg>\n          X.com\n        </a>\n      </li>\n      <li>\n        <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\" rel=\"noreferrer\">\n          <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n            <use href=\"/icons.svg#bluesky-icon\"></use>\n          </svg>\n          Bluesky\n        </a>\n      </li>\n    </ul>\n  </div>\n</section>\n\n<div class=\"ticks\"></div>\n<section id=\"spacer\"></section>\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/src/app.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n\n.counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/src/lib/Counter.svelte",
    "content": "<script lang=\"ts\">\n  let count: number = $state(0)\n  const increment = () => {\n    count += 1\n  }\n</script>\n\n<button class=\"counter\" onclick={increment}>\n  Count is {count}\n</button>\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/src/main.ts",
    "content": "import { mount } from 'svelte'\nimport './app.css'\nimport App from './App.svelte'\n\nconst app = mount(App, {\n  target: document.getElementById('app')!,\n})\n\nexport default app\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/svelte.config.js",
    "content": "/** @type {import(\"@sveltejs/vite-plugin-svelte\").SvelteConfig} */\nexport default {}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/tsconfig.app.json",
    "content": "{\n  \"extends\": \"@tsconfig/svelte/tsconfig.json\",\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"types\": [\"svelte\", \"vite/client\"],\n    \"noEmit\": true,\n    /**\n     * Typecheck JS in `.svelte` and `.js` files by default.\n     * Disable checkJs if you'd like to use dynamic types in JS.\n     * Note that setting allowJs false does not prevent the use\n     * of JS in `.svelte` files.\n     */\n    \"allowJs\": true,\n    \"checkJs\": true,\n    \"moduleDetection\": \"force\"\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.js\", \"src/**/*.svelte\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ]\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"node\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-svelte-ts/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { svelte } from '@sveltejs/vite-plugin-svelte'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [svelte()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-vanilla/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-vanilla/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + JS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-vanilla/package.json",
    "content": "{\n  \"name\": \"vite-starter\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vanilla/src/counter.js",
    "content": "export function setupCounter(element) {\n  let counter = 0\n  const setCounter = (count) => {\n    counter = count\n    element.innerHTML = `Count is ${counter}`\n  }\n  element.addEventListener('click', () => setCounter(counter + 1))\n  setCounter(0)\n}\n"
  },
  {
    "path": "packages/create-vite/template-vanilla/src/main.js",
    "content": "import './style.css'\nimport javascriptLogo from './assets/javascript.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport { setupCounter } from './counter.js'\n\ndocument.querySelector('#app').innerHTML = `\n<section id=\"center\">\n  <div class=\"hero\">\n    <img src=\"${heroImg}\" class=\"base\" width=\"170\" height=\"179\">\n    <img src=\"${javascriptLogo}\" class=\"framework\" alt=\"JavaScript logo\"/>\n    <img src=${viteLogo} class=\"vite\" alt=\"Vite logo\" />\n  </div>\n  <div>\n    <h1>Get started</h1>\n    <p>Edit <code>src/main.js</code> and save to test <code>HMR</code></p>\n  </div>\n  <button id=\"counter\" type=\"button\" class=\"counter\"></button>\n</section>\n\n<div class=\"ticks\"></div>\n\n<section id=\"next-steps\">\n  <div id=\"docs\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#documentation-icon\"></use></svg>\n    <h2>Documentation</h2>\n    <p>Your questions, answered</p>\n    <ul>\n      <li>\n        <a href=\"https://vite.dev/\" target=\"_blank\">\n          <img class=\"logo\" src=${viteLogo} alt=\"\" />\n          Explore Vite\n        </a>\n      </li>\n      <li>\n        <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript\" target=\"_blank\">\n          <img class=\"button-icon\" src=\"${javascriptLogo}\" alt=\"\">\n          Learn more\n        </a>\n      </li>\n    </ul>\n  </div>\n  <div id=\"social\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#social-icon\"></use></svg>\n    <h2>Connect with us</h2>\n    <p>Join the Vite community</p>\n    <ul>\n      <li><a href=\"https://github.com/vitejs/vite\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#github-icon\"></use></svg>GitHub</a></li>\n      <li><a href=\"https://chat.vite.dev/\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#discord-icon\"></use></svg>Discord</a></li>\n      <li><a href=\"https://x.com/vite_js\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#x-icon\"></use></svg>X.com</a></li>\n      <li><a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#bluesky-icon\"></use></svg>Bluesky</a></li>\n    </ul>\n  </div>\n</section>\n\n<div class=\"ticks\"></div>\n<section id=\"spacer\"></section>\n`\n\nsetupCounter(document.querySelector('#counter'))\n"
  },
  {
    "path": "packages/create-vite/template-vanilla/src/style.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n\n.counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/package.json",
    "content": "{\n  \"name\": \"vite-typescript-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/src/counter.ts",
    "content": "export function setupCounter(element: HTMLButtonElement) {\n  let counter = 0\n  const setCounter = (count: number) => {\n    counter = count\n    element.innerHTML = `Count is ${counter}`\n  }\n  element.addEventListener('click', () => setCounter(counter + 1))\n  setCounter(0)\n}\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/src/main.ts",
    "content": "import './style.css'\nimport typescriptLogo from './assets/typescript.svg'\nimport viteLogo from './assets/vite.svg'\nimport heroImg from './assets/hero.png'\nimport { setupCounter } from './counter.ts'\n\ndocument.querySelector<HTMLDivElement>('#app')!.innerHTML = `\n<section id=\"center\">\n  <div class=\"hero\">\n    <img src=\"${heroImg}\" class=\"base\" width=\"170\" height=\"179\">\n    <img src=\"${typescriptLogo}\" class=\"framework\" alt=\"TypeScript logo\"/>\n    <img src=${viteLogo} class=\"vite\" alt=\"Vite logo\" />\n  </div>\n  <div>\n    <h1>Get started</h1>\n    <p>Edit <code>src/main.ts</code> and save to test <code>HMR</code></p>\n  </div>\n  <button id=\"counter\" type=\"button\" class=\"counter\"></button>\n</section>\n\n<div class=\"ticks\"></div>\n\n<section id=\"next-steps\">\n  <div id=\"docs\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#documentation-icon\"></use></svg>\n    <h2>Documentation</h2>\n    <p>Your questions, answered</p>\n    <ul>\n      <li>\n        <a href=\"https://vite.dev/\" target=\"_blank\">\n          <img class=\"logo\" src=${viteLogo} alt=\"\" />\n          Explore Vite\n        </a>\n      </li>\n      <li>\n        <a href=\"https://www.typescriptlang.org\" target=\"_blank\">\n          <img class=\"button-icon\" src=\"${typescriptLogo}\" alt=\"\">\n          Learn more\n        </a>\n      </li>\n    </ul>\n  </div>\n  <div id=\"social\">\n    <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#social-icon\"></use></svg>\n    <h2>Connect with us</h2>\n    <p>Join the Vite community</p>\n    <ul>\n      <li><a href=\"https://github.com/vitejs/vite\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#github-icon\"></use></svg>GitHub</a></li>\n      <li><a href=\"https://chat.vite.dev/\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#discord-icon\"></use></svg>Discord</a></li>\n      <li><a href=\"https://x.com/vite_js\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#x-icon\"></use></svg>X.com</a></li>\n      <li><a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\"><svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\"><use href=\"/icons.svg#bluesky-icon\"></use></svg>Bluesky</a></li>\n    </ul>\n  </div>\n</section>\n\n<div class=\"ticks\"></div>\n<section id=\"spacer\"></section>\n`\n\nsetupCounter(document.querySelector<HTMLButtonElement>('#counter')!)\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/src/style.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n\n.counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vanilla-ts/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2023\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2023\", \"DOM\", \"DOM.Iterable\"],\n    \"types\": [\"vite/client\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"Vue.volar\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue/README.md",
    "content": "# Vue 3 + Vite\n\nThis template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.\n\nLearn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).\n"
  },
  {
    "path": "packages/create-vite/template-vue/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-vue/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Vue</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-vue/package.json",
    "content": "{\n  \"name\": \"vite-vue-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.5.30\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^6.0.5\",\n    \"vite\": \"^8.0.1\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue/src/App.vue",
    "content": "<script setup>\nimport HelloWorld from './components/HelloWorld.vue'\n</script>\n\n<template>\n  <HelloWorld />\n</template>\n"
  },
  {
    "path": "packages/create-vite/template-vue/src/components/HelloWorld.vue",
    "content": "<script setup>\nimport { ref } from 'vue'\nimport viteLogo from '../assets/vite.svg'\nimport heroImg from '../assets/hero.png'\nimport vueLogo from '../assets/vue.svg'\n\nconst count = ref(0)\n</script>\n\n<template>\n  <section id=\"center\">\n    <div class=\"hero\">\n      <img :src=\"heroImg\" class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n      <img :src=\"vueLogo\" class=\"framework\" alt=\"Vue logo\" />\n      <img :src=\"viteLogo\" class=\"vite\" alt=\"Vite logo\" />\n    </div>\n    <div>\n      <h1>Get started</h1>\n      <p>Edit <code>src/App.vue</code> and save to test <code>HMR</code></p>\n    </div>\n    <button class=\"counter\" @click=\"count++\">Count is {{ count }}</button>\n  </section>\n\n  <div class=\"ticks\"></div>\n\n  <section id=\"next-steps\">\n    <div id=\"docs\">\n      <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n        <use href=\"/icons.svg#documentation-icon\"></use>\n      </svg>\n      <h2>Documentation</h2>\n      <p>Your questions, answered</p>\n      <ul>\n        <li>\n          <a href=\"https://vite.dev/\" target=\"_blank\">\n            <img class=\"logo\" :src=\"viteLogo\" alt=\"\" />\n            Explore Vite\n          </a>\n        </li>\n        <li>\n          <a href=\"https://vuejs.org/\" target=\"_blank\">\n            <img class=\"button-icon\" :src=\"vueLogo\" alt=\"\" />\n            Learn more\n          </a>\n        </li>\n      </ul>\n    </div>\n    <div id=\"social\">\n      <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n        <use href=\"/icons.svg#social-icon\"></use>\n      </svg>\n      <h2>Connect with us</h2>\n      <p>Join the Vite community</p>\n      <ul>\n        <li>\n          <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#github-icon\"></use>\n            </svg>\n            GitHub\n          </a>\n        </li>\n        <li>\n          <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#discord-icon\"></use>\n            </svg>\n            Discord\n          </a>\n        </li>\n        <li>\n          <a href=\"https://x.com/vite_js\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#x-icon\"></use>\n            </svg>\n            X.com\n          </a>\n        </li>\n        <li>\n          <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#bluesky-icon\"></use>\n            </svg>\n            Bluesky\n          </a>\n        </li>\n      </ul>\n    </div>\n  </section>\n\n  <div class=\"ticks\"></div>\n  <section id=\"spacer\"></section>\n</template>\n"
  },
  {
    "path": "packages/create-vite/template-vue/src/main.js",
    "content": "import { createApp } from 'vue'\nimport './style.css'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n"
  },
  {
    "path": "packages/create-vite/template-vue/src/style.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n\n.counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [vue()],\n})\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"Vue.volar\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/README.md",
    "content": "# Vue 3 + TypeScript + Vite\n\nThis template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.\n\nLearn more about the recommended Project Setup and IDE Support in the [Vue Docs TypeScript Guide](https://vuejs.org/guide/typescript/overview.html#project-setup).\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/_gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + Vue + TS</title>\n  </head>\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/package.json",
    "content": "{\n  \"name\": \"vite-vue-typescript-starter\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vue-tsc -b && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.5.30\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^24.12.0\",\n    \"@vitejs/plugin-vue\": \"^6.0.5\",\n    \"@vue/tsconfig\": \"^0.9.0\",\n    \"typescript\": \"~5.9.3\",\n    \"vite\": \"^8.0.1\",\n    \"vue-tsc\": \"^3.2.5\"\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/src/App.vue",
    "content": "<script setup lang=\"ts\">\nimport HelloWorld from './components/HelloWorld.vue'\n</script>\n\n<template>\n  <HelloWorld />\n</template>\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/src/components/HelloWorld.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\nimport viteLogo from '../assets/vite.svg'\nimport heroImg from '../assets/hero.png'\nimport vueLogo from '../assets/vue.svg'\n\nconst count = ref(0)\n</script>\n\n<template>\n  <section id=\"center\">\n    <div class=\"hero\">\n      <img :src=\"heroImg\" class=\"base\" width=\"170\" height=\"179\" alt=\"\" />\n      <img :src=\"vueLogo\" class=\"framework\" alt=\"Vue logo\" />\n      <img :src=\"viteLogo\" class=\"vite\" alt=\"Vite logo\" />\n    </div>\n    <div>\n      <h1>Get started</h1>\n      <p>Edit <code>src/App.vue</code> and save to test <code>HMR</code></p>\n    </div>\n    <button class=\"counter\" @click=\"count++\">Count is {{ count }}</button>\n  </section>\n\n  <div class=\"ticks\"></div>\n\n  <section id=\"next-steps\">\n    <div id=\"docs\">\n      <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n        <use href=\"/icons.svg#documentation-icon\"></use>\n      </svg>\n      <h2>Documentation</h2>\n      <p>Your questions, answered</p>\n      <ul>\n        <li>\n          <a href=\"https://vite.dev/\" target=\"_blank\">\n            <img class=\"logo\" :src=\"viteLogo\" alt=\"\" />\n            Explore Vite\n          </a>\n        </li>\n        <li>\n          <a href=\"https://vuejs.org/\" target=\"_blank\">\n            <img class=\"button-icon\" :src=\"vueLogo\" alt=\"\" />\n            Learn more\n          </a>\n        </li>\n      </ul>\n    </div>\n    <div id=\"social\">\n      <svg class=\"icon\" role=\"presentation\" aria-hidden=\"true\">\n        <use href=\"/icons.svg#social-icon\"></use>\n      </svg>\n      <h2>Connect with us</h2>\n      <p>Join the Vite community</p>\n      <ul>\n        <li>\n          <a href=\"https://github.com/vitejs/vite\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#github-icon\"></use>\n            </svg>\n            GitHub\n          </a>\n        </li>\n        <li>\n          <a href=\"https://chat.vite.dev/\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#discord-icon\"></use>\n            </svg>\n            Discord\n          </a>\n        </li>\n        <li>\n          <a href=\"https://x.com/vite_js\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#x-icon\"></use>\n            </svg>\n            X.com\n          </a>\n        </li>\n        <li>\n          <a href=\"https://bsky.app/profile/vite.dev\" target=\"_blank\">\n            <svg class=\"button-icon\" role=\"presentation\" aria-hidden=\"true\">\n              <use href=\"/icons.svg#bluesky-icon\"></use>\n            </svg>\n            Bluesky\n          </a>\n        </li>\n      </ul>\n    </div>\n  </section>\n\n  <div class=\"ticks\"></div>\n  <section id=\"spacer\"></section>\n</template>\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/src/main.ts",
    "content": "import { createApp } from 'vue'\nimport './style.css'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/src/style.css",
    "content": ":root {\n  --text: #6b6375;\n  --text-h: #08060d;\n  --bg: #fff;\n  --border: #e5e4e7;\n  --code-bg: #f4f3ec;\n  --accent: #aa3bff;\n  --accent-bg: rgba(170, 59, 255, 0.1);\n  --accent-border: rgba(170, 59, 255, 0.5);\n  --social-bg: rgba(244, 243, 236, 0.5);\n  --shadow:\n    rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;\n\n  --sans: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --heading: system-ui, 'Segoe UI', Roboto, sans-serif;\n  --mono: ui-monospace, Consolas, monospace;\n\n  font: 18px/145% var(--sans);\n  letter-spacing: 0.18px;\n  color-scheme: light dark;\n  color: var(--text);\n  background: var(--bg);\n  font-synthesis: none;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n\n  @media (max-width: 1024px) {\n    font-size: 16px;\n  }\n}\n\n@media (prefers-color-scheme: dark) {\n  :root {\n    --text: #9ca3af;\n    --text-h: #f3f4f6;\n    --bg: #16171d;\n    --border: #2e303a;\n    --code-bg: #1f2028;\n    --accent: #c084fc;\n    --accent-bg: rgba(192, 132, 252, 0.15);\n    --accent-border: rgba(192, 132, 252, 0.5);\n    --social-bg: rgba(47, 48, 58, 0.5);\n    --shadow:\n      rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;\n  }\n\n  #social .button-icon {\n    filter: invert(1) brightness(2);\n  }\n}\n\nbody {\n  margin: 0;\n}\n\nh1,\nh2 {\n  font-family: var(--heading);\n  font-weight: 500;\n  color: var(--text-h);\n}\n\nh1 {\n  font-size: 56px;\n  letter-spacing: -1.68px;\n  margin: 32px 0;\n  @media (max-width: 1024px) {\n    font-size: 36px;\n    margin: 20px 0;\n  }\n}\nh2 {\n  font-size: 24px;\n  line-height: 118%;\n  letter-spacing: -0.24px;\n  margin: 0 0 8px;\n  @media (max-width: 1024px) {\n    font-size: 20px;\n  }\n}\np {\n  margin: 0;\n}\n\ncode,\n.counter {\n  font-family: var(--mono);\n  display: inline-flex;\n  border-radius: 4px;\n  color: var(--text-h);\n}\n\ncode {\n  font-size: 15px;\n  line-height: 135%;\n  padding: 4px 8px;\n  background: var(--code-bg);\n}\n\n.counter {\n  font-size: 16px;\n  padding: 5px 10px;\n  border-radius: 5px;\n  color: var(--accent);\n  background: var(--accent-bg);\n  border: 2px solid transparent;\n  transition: border-color 0.3s;\n  margin-bottom: 24px;\n\n  &:hover {\n    border-color: var(--accent-border);\n  }\n  &:focus-visible {\n    outline: 2px solid var(--accent);\n    outline-offset: 2px;\n  }\n}\n\n.hero {\n  position: relative;\n\n  .base,\n  .framework,\n  .vite {\n    inset-inline: 0;\n    margin: 0 auto;\n  }\n\n  .base {\n    width: 170px;\n    position: relative;\n    z-index: 0;\n  }\n\n  .framework,\n  .vite {\n    position: absolute;\n  }\n\n  .framework {\n    z-index: 1;\n    top: 34px;\n    height: 28px;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)\n      scale(1.4);\n  }\n\n  .vite {\n    z-index: 0;\n    top: 107px;\n    height: 26px;\n    width: auto;\n    transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)\n      scale(0.8);\n  }\n}\n\n#app {\n  width: 1126px;\n  max-width: 100%;\n  margin: 0 auto;\n  text-align: center;\n  border-inline: 1px solid var(--border);\n  min-height: 100svh;\n  display: flex;\n  flex-direction: column;\n  box-sizing: border-box;\n}\n\n#center {\n  display: flex;\n  flex-direction: column;\n  gap: 25px;\n  place-content: center;\n  place-items: center;\n  flex-grow: 1;\n\n  @media (max-width: 1024px) {\n    padding: 32px 20px 24px;\n    gap: 18px;\n  }\n}\n\n#next-steps {\n  display: flex;\n  border-top: 1px solid var(--border);\n  text-align: left;\n\n  & > div {\n    flex: 1 1 0;\n    padding: 32px;\n    @media (max-width: 1024px) {\n      padding: 24px 20px;\n    }\n  }\n\n  .icon {\n    margin-bottom: 16px;\n    width: 22px;\n    height: 22px;\n  }\n\n  @media (max-width: 1024px) {\n    flex-direction: column;\n    text-align: center;\n  }\n}\n\n#docs {\n  border-right: 1px solid var(--border);\n\n  @media (max-width: 1024px) {\n    border-right: none;\n    border-bottom: 1px solid var(--border);\n  }\n}\n\n#next-steps ul {\n  list-style: none;\n  padding: 0;\n  display: flex;\n  gap: 8px;\n  margin: 32px 0 0;\n\n  .logo {\n    height: 18px;\n  }\n\n  a {\n    color: var(--text-h);\n    font-size: 16px;\n    border-radius: 6px;\n    background: var(--social-bg);\n    display: flex;\n    padding: 6px 12px;\n    align-items: center;\n    gap: 8px;\n    text-decoration: none;\n    transition: box-shadow 0.3s;\n\n    &:hover {\n      box-shadow: var(--shadow);\n    }\n    .button-icon {\n      height: 18px;\n      width: 18px;\n    }\n  }\n\n  @media (max-width: 1024px) {\n    margin-top: 20px;\n    flex-wrap: wrap;\n    justify-content: center;\n\n    li {\n      flex: 1 1 calc(50% - 8px);\n    }\n\n    a {\n      width: 100%;\n      justify-content: center;\n      box-sizing: border-box;\n    }\n  }\n}\n\n#spacer {\n  height: 88px;\n  border-top: 1px solid var(--border);\n  @media (max-width: 1024px) {\n    height: 48px;\n  }\n}\n\n.ticks {\n  position: relative;\n  width: 100%;\n\n  &::before,\n  &::after {\n    content: '';\n    position: absolute;\n    top: -4.5px;\n    border: 5px solid transparent;\n  }\n\n  &::before {\n    left: 0;\n    border-left-color: var(--border);\n  }\n  &::after {\n    right: 0;\n    border-right-color: var(--border);\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/tsconfig.app.json",
    "content": "{\n  \"extends\": \"@vue/tsconfig/tsconfig.dom.json\",\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.app.tsbuildinfo\",\n    \"types\": [\"vite/client\"],\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\", \"src/**/*.vue\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/tsconfig.json",
    "content": "{\n  \"files\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.app.json\" },\n    { \"path\": \"./tsconfig.node.json\" }\n  ]\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"tsBuildInfoFile\": \"./node_modules/.tmp/tsconfig.node.tsbuildinfo\",\n    \"target\": \"ES2023\",\n    \"lib\": [\"ES2023\"],\n    \"module\": \"ESNext\",\n    \"types\": [\"node\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"verbatimModuleSyntax\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"erasableSyntaxOnly\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedSideEffectImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "packages/create-vite/template-vue-ts/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n\n// https://vite.dev/config/\nexport default defineConfig({\n  plugins: [vue()],\n})\n"
  },
  {
    "path": "packages/create-vite/tsconfig.json",
    "content": "{\n  \"include\": [\"tsdown.config.ts\", \"src\", \"__tests__\"],\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"target\": \"ES2023\",\n    \"module\": \"Preserve\",\n    \"moduleResolution\": \"bundler\",\n    \"types\": [],\n    \"allowImportingTsExtensions\": true,\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"noUnusedLocals\": true,\n    \"esModuleInterop\": true,\n    \"noEmit\": true\n  }\n}\n"
  },
  {
    "path": "packages/create-vite/tsdown.config.ts",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'tsdown'\nimport licensePlugin from '../vite/rollupLicensePlugin.ts'\n\nexport default defineConfig(() => ({\n  entry: ['src/index.ts'],\n  target: 'node20',\n  minify: true,\n  inlineOnly: false as const,\n  fixedExtension: false,\n  plugins: [\n    licensePlugin(\n      path.resolve(import.meta.dirname, './LICENSE'),\n      'create-vite license',\n      'create-vite',\n      '# License of the files in the directories starting with \"template-\" in create-vite\\n' +\n        'The files in the directories starting with \"template-\" in create-vite and files\\n' +\n        'generated from those files are licensed under the CC0 1.0 Universal license:\\n\\n' +\n        cc0LicenseText +\n        '\\n\\n',\n    ),\n  ],\n}))\n\nconst cc0LicenseText = `\nCC0 1.0 Universal\n\nStatement of Purpose\n\nThe laws of most jurisdictions throughout the world automatically confer\nexclusive Copyright and Related Rights (defined below) upon the creator and\nsubsequent owner(s) (each and all, an \"owner\") of an original work of\nauthorship and/or a database (each, a \"Work\").\n\nCertain owners wish to permanently relinquish those rights to a Work for the\npurpose of contributing to a commons of creative, cultural and scientific\nworks (\"Commons\") that the public can reliably and without fear of later\nclaims of infringement build upon, modify, incorporate in other works, reuse\nand redistribute as freely as possible in any form whatsoever and for any\npurposes, including without limitation commercial purposes. These owners may\ncontribute to the Commons to promote the ideal of a free culture and the\nfurther production of creative, cultural and scientific works, or to gain\nreputation or greater distribution for their Work in part through the use and\nefforts of others.\n\nFor these and/or other purposes and motivations, and without any expectation\nof additional consideration or compensation, the person associating CC0 with a\nWork (the \"Affirmer\"), to the extent that he or she is an owner of Copyright\nand Related Rights in the Work, voluntarily elects to apply CC0 to the Work\nand publicly distribute the Work under its terms, with knowledge of his or her\nCopyright and Related Rights in the Work and the meaning and intended legal\neffect of CC0 on those rights.\n\n1. Copyright and Related Rights. A Work made available under CC0 may be\nprotected by copyright and related or neighboring rights (\"Copyright and\nRelated Rights\"). Copyright and Related Rights include, but are not limited\nto, the following:\n\n  i. the right to reproduce, adapt, distribute, perform, display, communicate,\n  and translate a Work;\n\n  ii. moral rights retained by the original author(s) and/or performer(s);\n\n  iii. publicity and privacy rights pertaining to a person's image or likeness\n  depicted in a Work;\n\n  iv. rights protecting against unfair competition in regards to a Work,\n  subject to the limitations in paragraph 4(a), below;\n\n  v. rights protecting the extraction, dissemination, use and reuse of data in\n  a Work;\n\n  vi. database rights (such as those arising under Directive 96/9/EC of the\n  European Parliament and of the Council of 11 March 1996 on the legal\n  protection of databases, and under any national implementation thereof,\n  including any amended or successor version of such directive); and\n\n  vii. other similar, equivalent or corresponding rights throughout the world\n  based on applicable law or treaty, and any national implementations thereof.\n\n2. Waiver. To the greatest extent permitted by, but not in contravention of,\napplicable law, Affirmer hereby overtly, fully, permanently, irrevocably and\nunconditionally waives, abandons, and surrenders all of Affirmer's Copyright\nand Related Rights and associated claims and causes of action, whether now\nknown or unknown (including existing as well as future claims and causes of\naction), in the Work (i) in all territories worldwide, (ii) for the maximum\nduration provided by applicable law or treaty (including future time\nextensions), (iii) in any current or future medium and for any number of\ncopies, and (iv) for any purpose whatsoever, including without limitation\ncommercial, advertising or promotional purposes (the \"Waiver\"). Affirmer makes\nthe Waiver for the benefit of each member of the public at large and to the\ndetriment of Affirmer's heirs and successors, fully intending that such Waiver\nshall not be subject to revocation, rescission, cancellation, termination, or\nany other legal or equitable action to disrupt the quiet enjoyment of the Work\nby the public as contemplated by Affirmer's express Statement of Purpose.\n\n3. Public License Fallback. Should any part of the Waiver for any reason be\njudged legally invalid or ineffective under applicable law, then the Waiver\nshall be preserved to the maximum extent permitted taking into account\nAffirmer's express Statement of Purpose. In addition, to the extent the Waiver\nis so judged Affirmer hereby grants to each affected person a royalty-free,\nnon transferable, non sublicensable, non exclusive, irrevocable and\nunconditional license to exercise Affirmer's Copyright and Related Rights in\nthe Work (i) in all territories worldwide, (ii) for the maximum duration\nprovided by applicable law or treaty (including future time extensions), (iii)\nin any current or future medium and for any number of copies, and (iv) for any\npurpose whatsoever, including without limitation commercial, advertising or\npromotional purposes (the \"License\"). The License shall be deemed effective as\nof the date CC0 was applied by Affirmer to the Work. Should any part of the\nLicense for any reason be judged legally invalid or ineffective under\napplicable law, such partial invalidity or ineffectiveness shall not\ninvalidate the remainder of the License, and in such case Affirmer hereby\naffirms that he or she will not (i) exercise any of his or her remaining\nCopyright and Related Rights in the Work or (ii) assert any associated claims\nand causes of action with respect to the Work, in either case contrary to\nAffirmer's express Statement of Purpose.\n\n4. Limitations and Disclaimers.\n\n  a. No trademark or patent rights held by Affirmer are waived, abandoned,\n  surrendered, licensed or otherwise affected by this document.\n\n  b. Affirmer offers the Work as-is and makes no representations or warranties\n  of any kind concerning the Work, express, implied, statutory or otherwise,\n  including without limitation warranties of title, merchantability, fitness\n  for a particular purpose, non infringement, or the absence of latent or\n  other defects, accuracy, or the present or absence of errors, whether or not\n  discoverable, all to the greatest extent permissible under applicable law.\n\n  c. Affirmer disclaims responsibility for clearing rights of other persons\n  that may apply to the Work or any use thereof, including without limitation\n  any person's Copyright and Related Rights in the Work. Further, Affirmer\n  disclaims responsibility for obtaining any necessary consents, permissions\n  or other rights required for any use of the Work.\n\n  d. Affirmer understands and acknowledges that Creative Commons is not a\n  party to this document and has no duty or obligation with respect to this\n  CC0 or use of the Work.\n\nFor more information, please see\n<http://creativecommons.org/publicdomain/zero/1.0/>\n`.trim()\n"
  },
  {
    "path": "packages/plugin-legacy/CHANGELOG.md",
    "content": "## [8.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@7.2.1...plugin-legacy@8.0.0) (2026-03-12)\n\n### ⚠ BREAKING CHANGES\n\n* **legacy:** bump modern browser threshold to `import.meta.resolve` support (#21662)\n\n### Features\n\n* **legacy:** bump modern browser threshold to `import.meta.resolve` support ([#21662](https://github.com/vitejs/vite/issues/21662)) ([cc50822](https://github.com/vitejs/vite/commit/cc50822161f43ac60b932f2b4f63129bdb5590dc))\n* the epic `rolldown-vite` merge ([#21189](https://github.com/vitejs/vite/issues/21189)) ([4a7f8d4](https://github.com/vitejs/vite/commit/4a7f8d43e6b14b89fef278c3ea86f9e3f64b7fc2))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#21691](https://github.com/vitejs/vite/issues/21691)) ([521fdc0](https://github.com/vitejs/vite/commit/521fdc0ced51ddee7f728e6f891f36ebc6c0e1ce))\n* **deps:** update all non-major dependencies ([#21786](https://github.com/vitejs/vite/issues/21786)) ([eaa4352](https://github.com/vitejs/vite/commit/eaa4352af8f8658e3a10a9945ad9c227fcb2f28a))\n* **legacy:** skip preload helper in legacy chunks ([#21607](https://github.com/vitejs/vite/issues/21607)) ([0f2b7ae](https://github.com/vitejs/vite/commit/0f2b7aed683657f62bdce4a2fbb2883cd3af7d67))\n* **deps:** update all non-major dependencies ([#21488](https://github.com/vitejs/vite/issues/21488)) ([2b32ca2](https://github.com/vitejs/vite/commit/2b32ca24fe9d742901c2cb5c88e6b1fd734f8c73))\n* **deps:** update all non-major dependencies ([#21540](https://github.com/vitejs/vite/issues/21540)) ([9ebaeaa](https://github.com/vitejs/vite/commit/9ebaeaac094db996b1d12665052633c20ac8a9cf))\n* **legacy:** use `prebuilt-chunk` for polyfill chunks ([#21498](https://github.com/vitejs/vite/issues/21498)) ([7999843](https://github.com/vitejs/vite/commit/79998430eb7cd549a7fb803882447c4a15b11899))\n* **deps:** update all non-major dependencies ([#21231](https://github.com/vitejs/vite/issues/21231)) ([859789c](https://github.com/vitejs/vite/commit/859789c856412dfa67969232ddda1df754febf40))\n* **deps:** update all non-major dependencies ([#21389](https://github.com/vitejs/vite/issues/21389)) ([30f48df](https://github.com/vitejs/vite/commit/30f48df33ec9e9bd0b8164461eede5574398370b))\n\n### Documentation\n\n* **legacy:** update stale description ([#21610](https://github.com/vitejs/vite/issues/21610)) ([9037c29](https://github.com/vitejs/vite/commit/9037c29ec608716fe7c6803cbb5cb0dfe8746e4a))\n\n### Miscellaneous Chores\n\n* **legacy:** update peer dep Vite to 8 ([4595aeb](https://github.com/vitejs/vite/commit/4595aeb5b84126ed855ed5a25cd9959adc2d141c))\n* **deps:** update dependency tsdown to ^0.20.3 ([#21593](https://github.com/vitejs/vite/issues/21593)) ([e3f6ac9](https://github.com/vitejs/vite/commit/e3f6ac9326bf7c31a916e7c5dd90277de4c262c0))\n* **deps:** update rolldown-related dependencies ([#21487](https://github.com/vitejs/vite/issues/21487)) ([5863e51](https://github.com/vitejs/vite/commit/5863e513fab6b481cfb42da86202f9db728c077d))\n* cleanup changelog ([#21202](https://github.com/vitejs/vite/issues/21202)) ([8c8c56e](https://github.com/vitejs/vite/commit/8c8c56e1eb465e6dcd0c1b40f187228edc0e2be4))\n* **deps:** update dependency tsdown to ^0.17.4 ([#21284](https://github.com/vitejs/vite/issues/21284)) ([43f061a](https://github.com/vitejs/vite/commit/43f061adc677d40ce226de4dd07ee9a1f5e4ca73))\n* **deps:** update dependency tsdown to ^0.18.4 ([#21344](https://github.com/vitejs/vite/issues/21344)) ([964c718](https://github.com/vitejs/vite/commit/964c718a382ff46ec1f906d7d6bc3f135a6dcd3f))\n* **deps:** update rolldown-related dependencies ([#21230](https://github.com/vitejs/vite/issues/21230)) ([9349446](https://github.com/vitejs/vite/commit/9349446e9344bd81ccfb37af482f479cd1b59bbc))\n* **deps:** update rolldown-related dependencies ([#21390](https://github.com/vitejs/vite/issues/21390)) ([be9dd4e](https://github.com/vitejs/vite/commit/be9dd4e08d899f9ed27f2bdcb81bf27d018377a6))\n* **legacy:** add metadata for vite-plugin-registry ([#21453](https://github.com/vitejs/vite/issues/21453)) ([2723c6c](https://github.com/vitejs/vite/commit/2723c6c849a0022e682b7fdccb7c5d109177e1c3))\n\n### Code Refactoring\n\n* use `import.meta.dirname` everywhere ([#21509](https://github.com/vitejs/vite/issues/21509)) ([7becf5f](https://github.com/vitejs/vite/commit/7becf5f8fe9041cff60f495ef975faaba68f9eb2))\n\n### Beta Changelogs\n\n#### [8.0.0-beta.3](https://github.com/vitejs/vite/compare/plugin-legacy@8.0.0-beta.2...plugin-legacy@8.0.0-beta.3) (2026-02-12)\n\nSee [8.0.0-beta.3 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@8.0.0-beta.3/packages/plugin-legacy/CHANGELOG.md)\n\n#### [8.0.0-beta.2](https://github.com/vitejs/vite/compare/plugin-legacy@8.0.0-beta.1...plugin-legacy@8.0.0-beta.2) (2026-02-03)\n\nSee [8.0.0-beta.2 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@8.0.0-beta.2/packages/plugin-legacy/CHANGELOG.md)\n\n#### [8.0.0-beta.1](https://github.com/vitejs/vite/compare/plugin-legacy@8.0.0-beta.0...plugin-legacy@8.0.0-beta.1) (2026-01-22)\n\nSee [8.0.0-beta.1 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@8.0.0-beta.1/packages/plugin-legacy/CHANGELOG.md)\n\n#### [8.0.0-beta.0](https://github.com/vitejs/vite/compare/plugin-legacy@7.2.1...plugin-legacy@8.0.0-beta.0) (2025-12-03)\n\nSee [8.0.0-beta.0 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@8.0.0-beta.0/packages/plugin-legacy/CHANGELOG.md)\n\n## <small>[7.2.1](https://github.com/vitejs/vite/compare/plugin-legacy@7.2.0...plugin-legacy@7.2.1) (2025-08-07)</small>\n### Features\n\n* **legacy:** update plugin-legacy code for rolldown-vite ([6401a49](https://github.com/vitejs/vite/commit/6401a49d53fbff8a4a519bb2ad107b8a223250d6))\n\n## [7.2.0](https://github.com/vitejs/vite/compare/plugin-legacy@7.1.0...plugin-legacy@7.2.0) (2025-08-07)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20537](https://github.com/vitejs/vite/issues/20537)) ([fc9a9d3](https://github.com/vitejs/vite/commit/fc9a9d3f1493caa3d614f64e0a61fd5684f0928b))\n* **legacy:** `modernTargets` should set `build.target` ([#20393](https://github.com/vitejs/vite/issues/20393)) ([76c5e40](https://github.com/vitejs/vite/commit/76c5e40864f42bb33ee7ea9184e32d5156fa1a4a))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20441](https://github.com/vitejs/vite/issues/20441)) ([f689d61](https://github.com/vitejs/vite/commit/f689d613429ae9452c74f8bc482d8cc2584ea6b8))\n* **deps:** update rolldown-related dependencies ([#20536](https://github.com/vitejs/vite/issues/20536)) ([8be2787](https://github.com/vitejs/vite/commit/8be278748a92b128c49a24619d8d537dd2b08ceb))\n\n## [7.1.0](https://github.com/vitejs/vite/compare/plugin-legacy@7.0.1...plugin-legacy@7.1.0) (2025-07-22)\n### Features\n\n* **legacy:** add rolldown-vite support ([#20417](https://github.com/vitejs/vite/issues/20417)) ([ab62ca4](https://github.com/vitejs/vite/commit/ab62ca4897aa969fb72508656da2eae7fb3906be))\n\n## <small>[7.0.1](https://github.com/vitejs/vite/compare/plugin-legacy@7.0.0...plugin-legacy@7.0.1) (2025-07-17)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20324](https://github.com/vitejs/vite/issues/20324)) ([3e81af3](https://github.com/vitejs/vite/commit/3e81af38a80c7617aba6bf3300d8b4267570f9cf))\n* **deps:** update all non-major dependencies ([#20366](https://github.com/vitejs/vite/issues/20366)) ([43ac73d](https://github.com/vitejs/vite/commit/43ac73da27b3907c701e95e6a7d28fde659729ec))\n* **deps:** update all non-major dependencies ([#20406](https://github.com/vitejs/vite/issues/20406)) ([1a1cc8a](https://github.com/vitejs/vite/commit/1a1cc8a435a21996255b3e5cc75ed4680de2a7f3))\n* **legacy:** don't lower CSS if legacy chunks are not generated ([#20392](https://github.com/vitejs/vite/issues/20392)) ([d2c81f7](https://github.com/vitejs/vite/commit/d2c81f7c13030c08becd8a768182074eedb87333))\n\n### Performance Improvements\n\n* **legacy:** skip lowering when detecting polyfills ([#20387](https://github.com/vitejs/vite/issues/20387)) ([7cc0338](https://github.com/vitejs/vite/commit/7cc0338de3a67597956af58e931e46e7913c063b))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20323](https://github.com/vitejs/vite/issues/20323)) ([30d2f1b](https://github.com/vitejs/vite/commit/30d2f1b38c72387ffdca3ee4746730959a020b59))\n* group commits by category in changelog ([#20310](https://github.com/vitejs/vite/issues/20310)) ([41e83f6](https://github.com/vitejs/vite/commit/41e83f62b1adb65f5af4c1ec006de1c845437edc))\n\n### Code Refactoring\n\n* **legacy:** use Rollup type export from Vite ([#20335](https://github.com/vitejs/vite/issues/20335)) ([d62dc33](https://github.com/vitejs/vite/commit/d62dc3321db05d91e74facff51799496ce8601f3))\n* use `foo.endsWith(\"bar\")` instead of `/bar$/.test(foo)` ([#20413](https://github.com/vitejs/vite/issues/20413)) ([862e192](https://github.com/vitejs/vite/commit/862e192d21f66039635a998724bdc6b94fd293a0))\n\n## [7.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@6.1.1...plugin-legacy@7.0.0) (2025-06-24)\n\n### ⚠ BREAKING CHANGES\n\n* **legacy:** remove `location.protocol!=\"file:\"` condition for modern android webview (#20179)\n* bump required node version to 20.19+, 22.12+ and remove cjs build (#20032)\n* remove node 18 support (#19972)\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20141](https://github.com/vitejs/vite/issues/20141)) ([89ca65b](https://github.com/vitejs/vite/commit/89ca65ba1d849046dccdea52e9eca980f331be26))\n* **deps:** update all non-major dependencies ([#20181](https://github.com/vitejs/vite/issues/20181)) ([d91d4f7](https://github.com/vitejs/vite/commit/d91d4f7ad55edbcb4a51fc23376cbff89f776d30))\n* **legacy:** remove `location.protocol!=\"file:\"` condition for modern android webview ([#20179](https://github.com/vitejs/vite/issues/20179)) ([a6d5997](https://github.com/vitejs/vite/commit/a6d599718ee109798e8f552e317f175513d157e7))\n* **deps:** update all non-major dependencies ([#19953](https://github.com/vitejs/vite/issues/19953)) ([ac8e1fb](https://github.com/vitejs/vite/commit/ac8e1fb289a06fc0671dab1f4ef68e508e34360e))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20270](https://github.com/vitejs/vite/issues/20270)) ([f7377c3](https://github.com/vitejs/vite/commit/f7377c3eae6323bd3237ff5de5ae55c879fe7325))\n* **legacy:** update peer dep Vite to 7 ([8ff13cd](https://github.com/vitejs/vite/commit/8ff13cdba1c57284eb8f4586b52f814fcf5afcdf))\n* **deps:** update rolldown-related dependencies ([#20140](https://github.com/vitejs/vite/issues/20140)) ([0387447](https://github.com/vitejs/vite/commit/03874471e3de14e7d2f474ecb354499e7f5eb418))\n* **deps:** update rolldown-related dependencies ([#20182](https://github.com/vitejs/vite/issues/20182)) ([6172f41](https://github.com/vitejs/vite/commit/6172f410b44cbae8d052997bb1819a6197a4d397))\n* remove node 18 support ([#19972](https://github.com/vitejs/vite/issues/19972)) ([00b8a98](https://github.com/vitejs/vite/commit/00b8a98f36376804437e1342265453915ae613de))\n* use tsdown ([#20065](https://github.com/vitejs/vite/issues/20065)) ([d488efd](https://github.com/vitejs/vite/commit/d488efda95ff40f63684194d51858f84c3d05379))\n\n### Code Refactoring\n\n* bump required node version to 20.19+, 22.12+ and remove cjs build ([#20032](https://github.com/vitejs/vite/issues/20032)) ([2b80243](https://github.com/vitejs/vite/commit/2b80243fada75378e80475028fdcc78f4432bd6f))\n\n### Beta Changelogs\n\n#### [7.0.0-beta.1](https://github.com/vitejs/vite/compare/plugin-legacy@7.0.0-beta.0...plugin-legacy@7.0.0-beta.1) (2025-06-17)\n\nSee [7.0.0-beta.1 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@7.0.0-beta.1/packages/plugin-legacy/CHANGELOG.md)\n\n#### [7.0.0-beta.0](https://github.com/vitejs/vite/compare/plugin-legacy@6.1.1...plugin-legacy@7.0.0-beta.0) (2025-06-02)\n\nSee [7.0.0-beta.0 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@7.0.0-beta.0/packages/plugin-legacy/CHANGELOG.md)\n\n## <small>[6.1.1](https://github.com/vitejs/vite/compare/plugin-legacy@6.1.0...plugin-legacy@6.1.1) (2025-04-28)</small>\n### Bug Fixes\n\n* **legacy:** use unbuild 3.4 for now ([#19928](https://github.com/vitejs/vite/issues/19928)) ([96f73d1](https://github.com/vitejs/vite/commit/96f73d16c8501013be57aee1c8a2353a56460281))\n\n## [6.1.0](https://github.com/vitejs/vite/compare/plugin-legacy@6.0.2...plugin-legacy@6.1.0) (2025-04-16)\n### Features\n\n* **legacy:** add 'assumptions' option ([#19719](https://github.com/vitejs/vite/issues/19719)) ([d1d99c9](https://github.com/vitejs/vite/commit/d1d99c9220989ce903dea9cae6c3608f57f377ea))\n* **legacy:** add sourcemapBaseUrl support ([#19281](https://github.com/vitejs/vite/issues/19281)) ([a92c74b](https://github.com/vitejs/vite/commit/a92c74b088a253257c01596bd7c67e0f8fa39512))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19555](https://github.com/vitejs/vite/issues/19555)) ([f612e0f](https://github.com/vitejs/vite/commit/f612e0fdf6810317b61fcca1ded125755f261d78))\n* **deps:** update all non-major dependencies ([#19613](https://github.com/vitejs/vite/issues/19613)) ([363d691](https://github.com/vitejs/vite/commit/363d691b4995d72f26a14eb59ed88a9483b1f931))\n* **deps:** update all non-major dependencies ([#19649](https://github.com/vitejs/vite/issues/19649)) ([f4e712f](https://github.com/vitejs/vite/commit/f4e712ff861f8a9504594a4a5e6d35a7547e5a7e))\n\n### Code Refactoring\n\n* restore endsWith usage ([#19554](https://github.com/vitejs/vite/issues/19554)) ([6113a96](https://github.com/vitejs/vite/commit/6113a9670cc9b7d29fe0bffe033f7823e36ded00))\n\n## <small>[6.0.2](https://github.com/vitejs/vite/compare/plugin-legacy@6.0.1...plugin-legacy@6.0.2) (2025-02-25)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19392](https://github.com/vitejs/vite/issues/19392)) ([60456a5](https://github.com/vitejs/vite/commit/60456a54fe90872dbd4bed332ecbd85bc88deb92))\n* **deps:** update all non-major dependencies ([#19440](https://github.com/vitejs/vite/issues/19440)) ([ccac73d](https://github.com/vitejs/vite/commit/ccac73d9d0e92c7232f09207d1d6b893e823ed8e))\n* **legacy:** warn if plugin-legacy is passed to `worker.plugins` ([#19079](https://github.com/vitejs/vite/issues/19079)) ([171f2fb](https://github.com/vitejs/vite/commit/171f2fbe0afe09eeb49f5f29f9ecd845c39a8401))\n\n### Miscellaneous Chores\n\n* fix typos ([#19398](https://github.com/vitejs/vite/issues/19398)) ([b44e3d4](https://github.com/vitejs/vite/commit/b44e3d43db65babe1c32e143964add02e080dc15))\n\n## <small>[6.0.1](https://github.com/vitejs/vite/compare/plugin-legacy@6.0.0...plugin-legacy@6.0.1) (2025-02-05)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#18853](https://github.com/vitejs/vite/issues/18853)) ([5c02236](https://github.com/vitejs/vite/commit/5c0223636fa277d5daeb4d93c3f32d9f3cd69fc5))\n* **deps:** update all non-major dependencies ([#18967](https://github.com/vitejs/vite/issues/18967)) ([d88d000](https://github.com/vitejs/vite/commit/d88d0004a8e891ca6026d356695e0b319caa7fce))\n* **deps:** update all non-major dependencies ([#19098](https://github.com/vitejs/vite/issues/19098)) ([8639538](https://github.com/vitejs/vite/commit/8639538e6498d1109da583ad942c1472098b5919))\n* **deps:** update all non-major dependencies ([#19190](https://github.com/vitejs/vite/issues/19190)) ([f2c07db](https://github.com/vitejs/vite/commit/f2c07dbfc874b46f6e09bb04996d0514663e4544))\n* **deps:** update all non-major dependencies ([#19296](https://github.com/vitejs/vite/issues/19296)) ([2bea7ce](https://github.com/vitejs/vite/commit/2bea7cec4b7fddbd5f2fb6090a7eaf5ae7ca0f1b))\n* **legacy:** build respect `hashCharacters` config ([#19262](https://github.com/vitejs/vite/issues/19262)) ([3aa10b7](https://github.com/vitejs/vite/commit/3aa10b7d618b178aec0f027b1f5fcd3353d2b166))\n* **legacy:** import babel once ([#19152](https://github.com/vitejs/vite/issues/19152)) ([282496d](https://github.com/vitejs/vite/commit/282496daaca43494feceaa59809f6ceafd62dedd))\n\n### Reverts\n\n* update moduleResolution value casing ([#18409](https://github.com/vitejs/vite/issues/18409)) ([#18774](https://github.com/vitejs/vite/issues/18774)) ([b0fc6e3](https://github.com/vitejs/vite/commit/b0fc6e3c2591a30360d3714263cf7cc0e2acbfdf))\n\n## [6.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@5.4.3...plugin-legacy@6.0.0) (2024-11-26)\n### ⚠ BREAKING CHANGES\n\n* drop node 21 support in version ranges (#18729)\n\n### Features\n\n* drop node 21 support in version ranges ([#18729](https://github.com/vitejs/vite/issues/18729)) ([a384d8f](https://github.com/vitejs/vite/commit/a384d8fd39162190675abcfea31ba657383a3d03))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#18484](https://github.com/vitejs/vite/issues/18484)) ([2ec12df](https://github.com/vitejs/vite/commit/2ec12df98d07eb4c986737e86a4a9f8066724658))\n* **deps:** update all non-major dependencies ([#18691](https://github.com/vitejs/vite/issues/18691)) ([f005461](https://github.com/vitejs/vite/commit/f005461ecce89ada21cb0c021f7af460b5479736))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#18562](https://github.com/vitejs/vite/issues/18562)) ([fb227ec](https://github.com/vitejs/vite/commit/fb227ec4402246b5a13e274c881d9de6dd8082dd))\n* **legacy:** bump terser peer dep to ^5.16 ([#18772](https://github.com/vitejs/vite/issues/18772)) ([3f6d5fe](https://github.com/vitejs/vite/commit/3f6d5fed8739f30cddb821a680576d93b3a60bba))\n* **legacy:** update peer dep Vite to 6 ([#18771](https://github.com/vitejs/vite/issues/18771)) ([63c62b3](https://github.com/vitejs/vite/commit/63c62b3059b589a51d1673bfdcefdb0b4e87c089))\n* **plugin-legacy:** add type module in package.json ([#18535](https://github.com/vitejs/vite/issues/18535)) ([28cefca](https://github.com/vitejs/vite/commit/28cefcaf2861b72901abe1f047d9ec6298b745f8))\n* upgrade to unbuild v3 rc ([#18502](https://github.com/vitejs/vite/issues/18502)) ([ddd5c5d](https://github.com/vitejs/vite/commit/ddd5c5d00ff7894462a608841560883f9c771f22))\n\n## <small>[5.4.3](https://github.com/vitejs/vite/compare/plugin-legacy@5.4.2...plugin-legacy@5.4.3) (2024-10-25)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#18170](https://github.com/vitejs/vite/issues/18170)) ([c8aea5a](https://github.com/vitejs/vite/commit/c8aea5ae0af90dc6796ef3bdd612d1eb819f157b))\n* **deps:** update all non-major dependencies ([#18292](https://github.com/vitejs/vite/issues/18292)) ([5cac054](https://github.com/vitejs/vite/commit/5cac0544dca2764f0114aac38e9922a0c13d7ef4))\n* **deps:** update all non-major dependencies ([#18345](https://github.com/vitejs/vite/issues/18345)) ([5552583](https://github.com/vitejs/vite/commit/5552583a2272cd4208b30ad60e99d984e34645f0))\n* **legacy:** generate sourcemap for polyfill chunks ([#18250](https://github.com/vitejs/vite/issues/18250)) ([f311ff3](https://github.com/vitejs/vite/commit/f311ff3c2b19636457c3023095ef32ab9a96b84a))\n\n### Performance Improvements\n\n* use `crypto.hash` when available ([#18317](https://github.com/vitejs/vite/issues/18317)) ([2a14884](https://github.com/vitejs/vite/commit/2a148844cf2382a5377b75066351f00207843352))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#17945](https://github.com/vitejs/vite/issues/17945)) ([cfb621e](https://github.com/vitejs/vite/commit/cfb621e7a5a3e24d710a9af156e6855e73caf891))\n* **deps:** update all non-major dependencies ([#18050](https://github.com/vitejs/vite/issues/18050)) ([7cac03f](https://github.com/vitejs/vite/commit/7cac03fa5197a72d2e2422bd0243a85a9a18abfc))\n* **deps:** update all non-major dependencies ([#18404](https://github.com/vitejs/vite/issues/18404)) ([802839d](https://github.com/vitejs/vite/commit/802839d48335a69eb15f71f2cd816d0b6e4d3556))\n* enable some eslint rules ([#18084](https://github.com/vitejs/vite/issues/18084)) ([e9a2746](https://github.com/vitejs/vite/commit/e9a2746ca77473b1814fd05db3d299c074135fe5))\n* remove stale TODOs ([#17866](https://github.com/vitejs/vite/issues/17866)) ([e012f29](https://github.com/vitejs/vite/commit/e012f296df583bd133d26399397bd4ae49de1497))\n* update license copyright ([#18278](https://github.com/vitejs/vite/issues/18278)) ([56eb869](https://github.com/vitejs/vite/commit/56eb869a67551a257d20cba00016ea59b1e1a2c4))\n\n## <small>[5.4.2](https://github.com/vitejs/vite/compare/plugin-legacy@5.4.1...plugin-legacy@5.4.2) (2024-08-15)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#17430](https://github.com/vitejs/vite/issues/17430)) ([4453d35](https://github.com/vitejs/vite/commit/4453d3578b343d16a8a5298bf154f280088968d9))\n* **deps:** update all non-major dependencies ([#17494](https://github.com/vitejs/vite/issues/17494)) ([bf123f2](https://github.com/vitejs/vite/commit/bf123f2c6242424a3648cf9234281fd9ff44e3d5))\n* **deps:** update all non-major dependencies ([#17629](https://github.com/vitejs/vite/issues/17629)) ([93281b0](https://github.com/vitejs/vite/commit/93281b0e09ff8b00e21c24b80ed796db89cbc1ef))\n* **deps:** update all non-major dependencies ([#17780](https://github.com/vitejs/vite/issues/17780)) ([e408542](https://github.com/vitejs/vite/commit/e408542748edebd93dba07f21e3fd107725cadca))\n* handle encoded base paths ([#17577](https://github.com/vitejs/vite/issues/17577)) ([720447e](https://github.com/vitejs/vite/commit/720447ee725046323387f661341d44e2ad390f41))\n\n### Performance Improvements\n\n* improve regex performance ([#17789](https://github.com/vitejs/vite/issues/17789)) ([952bae3](https://github.com/vitejs/vite/commit/952bae3efcbd871fc3df5b1947060de7ebdafa36))\n\n### Documentation\n\n* rename cdnjs link ([#17565](https://github.com/vitejs/vite/issues/17565)) ([61357f6](https://github.com/vitejs/vite/commit/61357f67cdb8eca2c551150a1f0329e272f4da62))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#17820](https://github.com/vitejs/vite/issues/17820)) ([bb2f8bb](https://github.com/vitejs/vite/commit/bb2f8bb55fdd64e4f16831ff98921c221a5e734a))\n* extend commit hash ([#17709](https://github.com/vitejs/vite/issues/17709)) ([4fc9b64](https://github.com/vitejs/vite/commit/4fc9b6424c27aca8004c368b69991a56264e4fdb))\n\n## <small>[5.4.1](https://github.com/vitejs/vite/compare/plugin-legacy@5.4.0...plugin-legacy@5.4.1) (2024-05-30)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#17321](https://github.com/vitejs/vite/issues/17321)) ([4a89766](https://github.com/vitejs/vite/commit/4a89766d838527c144f14e842211100b16792018))\n* **plugin-legacy:** group discovered polyfills by output ([#17347](https://github.com/vitejs/vite/issues/17347)) ([c735cc7](https://github.com/vitejs/vite/commit/c735cc7895b34dd760f57145a00ddc1da7526b8c))\n* **plugin-legacy:** improve deterministic polyfills discovery ([#16566](https://github.com/vitejs/vite/issues/16566)) ([48edfcd](https://github.com/vitejs/vite/commit/48edfcd91386a28817cbe5a361beb87c7d17f490))\n\n### Documentation\n\n* **plugin-legacy:** update outdated warning about `modernPolyfills` ([#17335](https://github.com/vitejs/vite/issues/17335)) ([e6a70b7](https://github.com/vitejs/vite/commit/e6a70b7c2d8a23cd2c3a20fbd9c33f199fdc3944))\n\n### Miscellaneous Chores\n\n* **deps:** remove unused deps ([#17329](https://github.com/vitejs/vite/issues/17329)) ([5a45745](https://github.com/vitejs/vite/commit/5a457454bfee1892b0d58c4b1c401cfb15986097))\n* **deps:** update all non-major dependencies ([#16722](https://github.com/vitejs/vite/issues/16722)) ([b45922a](https://github.com/vitejs/vite/commit/b45922a91d4a73c27f78f26e369b7b1fd8d800e3))\n\n## [5.4.0](https://github.com/vitejs/vite/compare/plugin-legacy@5.3.2...plugin-legacy@5.4.0) (2024-05-08)\n### Features\n\n* **plugin-legacy:** support `additionalModernPolyfills` ([#16514](https://github.com/vitejs/vite/issues/16514)) ([2322657](https://github.com/vitejs/vite/commit/232265783670563e34cf96240bf0e383a3653e6c))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#16258](https://github.com/vitejs/vite/issues/16258)) ([7caef42](https://github.com/vitejs/vite/commit/7caef4216e16d9ac71e38598a9ecedce2281d42f))\n* **deps:** update all non-major dependencies ([#16376](https://github.com/vitejs/vite/issues/16376)) ([58a2938](https://github.com/vitejs/vite/commit/58a2938a9766981fdc2ed89bec8ff1c96cae0716))\n* **deps:** update all non-major dependencies ([#16488](https://github.com/vitejs/vite/issues/16488)) ([2d50be2](https://github.com/vitejs/vite/commit/2d50be2a5424e4f4c22774652ed313d2a232f8af))\n* **deps:** update all non-major dependencies ([#16549](https://github.com/vitejs/vite/issues/16549)) ([2d6a13b](https://github.com/vitejs/vite/commit/2d6a13b0aa1f3860482dac2ce260cfbb0713033f))\n* **legacy:** modern polyfill autodetection was not injecting enough polyfills ([#16367](https://github.com/vitejs/vite/issues/16367)) ([4af9f97](https://github.com/vitejs/vite/commit/4af9f97cade9fdb349e4928871bbf15c190f9e2b))\n\n### Documentation\n\n* **legacy:** update `modernTargets` option default value description ([#16491](https://github.com/vitejs/vite/issues/16491)) ([7171837](https://github.com/vitejs/vite/commit/7171837abbf8634be2c2e9c32d5dc6a8cbf31e0d))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#16131](https://github.com/vitejs/vite/issues/16131)) ([a862ecb](https://github.com/vitejs/vite/commit/a862ecb941a432b6e3bab62331012e4b53ddd4e8))\n\n## <small>[5.3.2](https://github.com/vitejs/vite/compare/plugin-legacy@5.3.1...plugin-legacy@5.3.2) (2024-03-08)</small>\n### Bug Fixes\n\n* **plugin-legacy:** dynamic import browserslist-to-esbuild ([#16011](https://github.com/vitejs/vite/issues/16011)) ([42fd11c](https://github.com/vitejs/vite/commit/42fd11c1c6d37402bd15ba816fbf65dbed3abe55))\n* **plugin-legacy:** replace `esbuild-plugin-browserslist` with `browserslist-to-esbuild` ([#15988](https://github.com/vitejs/vite/issues/15988)) ([37af8a7](https://github.com/vitejs/vite/commit/37af8a7be417f1fb2cf9a0d5e9ad90b76ff211b4))\n* **plugin-legacy:** respect modernTargets option if renderLegacyChunks disabled ([#15789](https://github.com/vitejs/vite/issues/15789)) ([0813531](https://github.com/vitejs/vite/commit/081353179a4029d8aedaf3dfd78b95d95b757668))\n\n## <small>[5.3.1](https://github.com/vitejs/vite/compare/plugin-legacy@5.3.0...plugin-legacy@5.3.1) (2024-02-21)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#15675](https://github.com/vitejs/vite/issues/15675)) ([4d9363a](https://github.com/vitejs/vite/commit/4d9363ad6bc460fe2da811cb48b036e53b8cfc75))\n* **deps:** update all non-major dependencies ([#15803](https://github.com/vitejs/vite/issues/15803)) ([e0a6ef2](https://github.com/vitejs/vite/commit/e0a6ef2b9e6f1df8c5e71efab6182b7cf662d18d))\n* **deps:** update all non-major dependencies ([#15959](https://github.com/vitejs/vite/issues/15959)) ([571a3fd](https://github.com/vitejs/vite/commit/571a3fde438d60540cfeba132e24646badf5ff2f))\n\n## [5.3.0](https://github.com/vitejs/vite/compare/plugin-legacy@5.2.0...plugin-legacy@5.3.0) (2024-01-25)\n### Features\n\n* **legacy:** build file name optimization ([#15115](https://github.com/vitejs/vite/issues/15115)) ([39f435d](https://github.com/vitejs/vite/commit/39f435d8ce329870754f33509e9fdbb61883c9fc))\n* **legacy:** support any separator before hash in fileNames ([#15170](https://github.com/vitejs/vite/issues/15170)) ([ecab41a](https://github.com/vitejs/vite/commit/ecab41a7f8ee09c43e7ace6ef20d2f8693a5978a))\n* **plugin-legacy:** add `modernTargets` option ([#15506](https://github.com/vitejs/vite/issues/15506)) ([cf56507](https://github.com/vitejs/vite/commit/cf56507dbfd41c4af63de511a320971668d5204f))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#15233](https://github.com/vitejs/vite/issues/15233)) ([ad3adda](https://github.com/vitejs/vite/commit/ad3adda7215c33874a07cbd4d430fcffe4c85dce))\n* **deps:** update all non-major dependencies ([#15304](https://github.com/vitejs/vite/issues/15304)) ([bb07f60](https://github.com/vitejs/vite/commit/bb07f605cca698a81f1b4606ddefb34485069dd1))\n* **deps:** update all non-major dependencies ([#15375](https://github.com/vitejs/vite/issues/15375)) ([ab56227](https://github.com/vitejs/vite/commit/ab56227d89c92bfa781264e1474ed522892e3b8f))\n\n### Documentation\n\n* fix commit id collision ([#15105](https://github.com/vitejs/vite/issues/15105)) ([0654d1b](https://github.com/vitejs/vite/commit/0654d1b52448db4d7a9b69aee6aad9e015481452))\n* fix dead link ([#15700](https://github.com/vitejs/vite/issues/15700)) ([aa7916a](https://github.com/vitejs/vite/commit/aa7916a5c2d580cdd9968fc221826ddd17443bac))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#15145](https://github.com/vitejs/vite/issues/15145)) ([7ff2c0a](https://github.com/vitejs/vite/commit/7ff2c0afe8c6b6901385af829f2e7e80c1fe344c))\n\n## [5.2.0](https://github.com/vitejs/vite/compare/plugin-legacy@5.1.0...plugin-legacy@5.2.0) (2023-11-22)\n### Bug Fixes\n\n* **plugin-legacy:** syntax error in variable `detectModernBrowserCode` ([#15095](https://github.com/vitejs/vite/issues/15095)) ([1c605ff](https://github.com/vitejs/vite/commit/1c605ffe9b56dcf731f341a687b1d5b55bba48c6))\n\n### Tests\n\n* **legacy:** add a test to checks all inline snippets are valid JS ([#15098](https://github.com/vitejs/vite/issues/15098)) ([1b9ca66](https://github.com/vitejs/vite/commit/1b9ca66b6d777bd4a03165512de5d65d83a2f25b))\n\n## [5.1.0](https://github.com/vitejs/vite/compare/plugin-legacy@5.0.0...plugin-legacy@5.1.0) (2023-11-21)\n### Bug Fixes\n\n* **legacy:** preserve async generator function invocation ([#15021](https://github.com/vitejs/vite/issues/15021)) ([47551a6](https://github.com/vitejs/vite/commit/47551a6f32eace64a4f5b669f997892c5ab867af))\n\n### Documentation\n\n* **legacy:** clarify that csp hashes could change between minors ([#15057](https://github.com/vitejs/vite/issues/15057)) ([cd35330](https://github.com/vitejs/vite/commit/cd353306eefa9787c07b257c8c7f3f68e0949240))\n\n## [5.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@4.1.1...plugin-legacy@5.0.0) (2023-11-16)\n\n### ⚠ BREAKING CHANGES\n\n* **plugin-legacy:** bump vite peer dep (#15004)\n* **legacy:** should rename `x.[hash].js` to `x-legacy.[hash].js` (#11599)\n* **legacy:** remove `ignoreBrowserslistConfig` option (#14429)\n* bump minimum node version to 18 (#14030)\n\n### Features\n\n* **plugin-legacy:** bump vite peer dep ([#15004](https://github.com/vitejs/vite/issues/15004)) ([3c92c7b](https://github.com/vitejs/vite/commit/3c92c7bca23616f156b70311b149cbc1af59d40b))\n* **legacy:** export `Options` ([#14933](https://github.com/vitejs/vite/issues/14933)) ([071bfc8](https://github.com/vitejs/vite/commit/071bfc8e18ebe3981bded8e7bab605bd473d72b9))\n* bump minimum node version to 18 ([#14030](https://github.com/vitejs/vite/issues/14030)) ([2c1a45c](https://github.com/vitejs/vite/commit/2c1a45c86cab6ecf02abb6e50385f773d5ed568e))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#14635](https://github.com/vitejs/vite/issues/14635)) ([21017a9](https://github.com/vitejs/vite/commit/21017a9408643cbc7204215ecc5a3fdaf74dc81e))\n* **deps:** update all non-major dependencies ([#14729](https://github.com/vitejs/vite/issues/14729)) ([d5d96e7](https://github.com/vitejs/vite/commit/d5d96e712788bc762d9c135bc84628dbcfc7fb58))\n* **deps:** update all non-major dependencies ([#14883](https://github.com/vitejs/vite/issues/14883)) ([e5094e5](https://github.com/vitejs/vite/commit/e5094e5bf2aee3516d04ce35ba2fb27e70ea9858))\n* **deps:** update all non-major dependencies ([#14961](https://github.com/vitejs/vite/issues/14961)) ([0bb3995](https://github.com/vitejs/vite/commit/0bb3995a7d2245ef1cc7b2ed8a5242e33af16874))\n* **plugin-legacy:** add invoke to modern detector to avoid terser treeshaking ([#14968](https://github.com/vitejs/vite/issues/14968)) ([4033a32](https://github.com/vitejs/vite/commit/4033a320d6809c9a0c2552f0ef2bf686c63aa35a))\n* **deps:** update all non-major dependencies ([#14510](https://github.com/vitejs/vite/issues/14510)) ([eb204fd](https://github.com/vitejs/vite/commit/eb204fd3c5bffb6c6fb40f562f762e426fbaf183))\n* **legacy:** fix broken build when renderModernChunks=false & polyfills=false (fix [#14324](https://github.com/vitejs/vite/issues/14324)) ([#14346](https://github.com/vitejs/vite/issues/14346)) ([27e5b11](https://github.com/vitejs/vite/commit/27e5b1114ce653b5716cd175aed9e2775da2f97a))\n* **legacy:** should rename `x.[hash].js` to `x-legacy.[hash].js` ([#11599](https://github.com/vitejs/vite/issues/11599)) ([e7d7a6f](https://github.com/vitejs/vite/commit/e7d7a6f4ee095bca4ed4fddf387a9ff06fcea7bb))\n* **deps:** update all non-major dependencies ([#14460](https://github.com/vitejs/vite/issues/14460)) ([b77bff0](https://github.com/vitejs/vite/commit/b77bff0b93ba9449f63c8373ecf82289a39832a0))\n* **legacy:** add guard to modern polyfill chunk ([#13719](https://github.com/vitejs/vite/issues/13719)) ([945dc4d](https://github.com/vitejs/vite/commit/945dc4de52e64a1a8f6e2451fadf6aba7e460234))\n* **legacy:** modern polyfill autodetection was injecting more polyfills than needed ([#14428](https://github.com/vitejs/vite/issues/14428)) ([1c2e941](https://github.com/vitejs/vite/commit/1c2e941d03621a4b77d9dfca8841e336b716691c))\n* **legacy:** suppress babel warning during polyfill scan ([#14425](https://github.com/vitejs/vite/issues/14425)) ([aae3a83](https://github.com/vitejs/vite/commit/aae3a83b5fb49bbd9f174cfeac66f00483829da4))\n* **plugin-legacy:** ensure correct typing for node esm ([#13892](https://github.com/vitejs/vite/issues/13892)) ([d914a9d](https://github.com/vitejs/vite/commit/d914a9d79adfe0aed2ee5d69f6f6d1e80b613b98))\n* **deps:** update all non-major dependencies ([#14092](https://github.com/vitejs/vite/issues/14092)) ([68638f7](https://github.com/vitejs/vite/commit/68638f7b0b04ddfdf35dc8686c6a022aadbb9453))\n\n### Performance Improvements\n\n* use magic-string hires boundary for sourcemaps ([#13971](https://github.com/vitejs/vite/issues/13971)) ([b9a8d65](https://github.com/vitejs/vite/commit/b9a8d65fd64d101ea596bc98a0aea0f95674a95a))\n\n### Documentation\n\n* **legacy:** correct `modernPolyfills` description ([#14233](https://github.com/vitejs/vite/issues/14233)) ([a57f388](https://github.com/vitejs/vite/commit/a57f388f53bdcbcacd7585724b43953c32e6806e))\n* **plugin-legacy:** fix typo ([#13936](https://github.com/vitejs/vite/issues/13936)) ([28ddd43](https://github.com/vitejs/vite/commit/28ddd43906825db9e1ffa030551e8f975d97f3a9))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency eslint-plugin-regexp to v2 ([#14730](https://github.com/vitejs/vite/issues/14730)) ([0a7c753](https://github.com/vitejs/vite/commit/0a7c75305a312161979eaf13d7b48d784bdb6b76))\n* **deps:** update all non-major dependencies ([#13938](https://github.com/vitejs/vite/issues/13938)) ([a1b519e](https://github.com/vitejs/vite/commit/a1b519e2c71593b6b4286c2f0bd8bfe2e0ad046d))\n* **eslint:** allow type annotations ([#13920](https://github.com/vitejs/vite/issues/13920)) ([d1264fd](https://github.com/vitejs/vite/commit/d1264fd34313a2da80af8dadbeab1c8e6013bb10))\n* upgrade babel and release-scripts ([#14330](https://github.com/vitejs/vite/issues/14330)) ([b361ffa](https://github.com/vitejs/vite/commit/b361ffa6724d9191fc6a581acfeab5bc3ebbd931))\n\n### Code Refactoring\n\n* **legacy:** remove `ignoreBrowserslistConfig` option ([#14429](https://github.com/vitejs/vite/issues/14429)) ([941bb16](https://github.com/vitejs/vite/commit/941bb1610c9c9576e0b5738c9075b3eb2f16a357))\n\n### Beta Changelogs\n\n#### [5.0.0-beta.3](https://github.com/vitejs/vite/compare/plugin-legacy@5.0.0-beta.2...plugin-legacy@5.0.0-beta.3) (2023-11-14)\n\nSee [5.0.0-beta.3 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@5.0.0-beta.3/packages/plugin-legacy/CHANGELOG.md)\n\n#### [5.0.0-beta.2](https://github.com/vitejs/vite/compare/plugin-legacy@5.0.0-beta.1...plugin-legacy@5.0.0-beta.2) (2023-10-09)\n\nSee [5.0.0-beta.2 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@5.0.0-beta.2/packages/plugin-legacy/CHANGELOG.md)\n\n#### [5.0.0-beta.1](https://github.com/vitejs/vite/compare/plugin-legacy@5.0.0-beta.0...plugin-legacy@5.0.0-beta.1) (2023-09-25)\n\nSee [5.0.0-beta.1 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@5.0.0-beta.1/packages/plugin-legacy/CHANGELOG.md)\n\n#### [5.0.0-beta.0](https://github.com/vitejs/vite/compare/plugin-legacy@4.1.1...plugin-legacy@5.0.0-beta.0) (2023-09-19)\n\nSee [5.0.0-beta.0 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@5.0.0-beta.0/packages/plugin-legacy/CHANGELOG.md)\n\n## <small>[4.1.1](https://github.com/vitejs/vite/compare/plugin-legacy@4.1.0...plugin-legacy@4.1.1) (2023-07-20)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#13758](https://github.com/vitejs/vite/issues/13758)) ([8ead116](https://github.com/vitejs/vite/commit/8ead11648514ae4975bf4328d6e15bd4dd42e45e))\n* **deps:** update all non-major dependencies ([#13872](https://github.com/vitejs/vite/issues/13872)) ([975a631](https://github.com/vitejs/vite/commit/975a631ec7c2373354aeeac6bc2977f24b54d13d))\n\n## [4.1.0](https://github.com/vitejs/vite/compare/plugin-legacy@4.0.5...plugin-legacy@4.1.0) (2023-07-06)\n### Features\n\n* **plugin-legacy:** add option to output only legacy builds ([#10139](https://github.com/vitejs/vite/issues/10139)) ([931b24f](https://github.com/vitejs/vite/commit/931b24f5eac4b9b5422a235782ca13baa9a99563))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#13701](https://github.com/vitejs/vite/issues/13701)) ([02c6bc3](https://github.com/vitejs/vite/commit/02c6bc38645ce18f9e1c8a71421fb8aad7081688))\n\n## <small>[4.0.5](https://github.com/vitejs/vite/compare/plugin-legacy@4.0.4...plugin-legacy@4.0.5) (2023-06-21)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#13059](https://github.com/vitejs/vite/issues/13059)) ([123ef4c](https://github.com/vitejs/vite/commit/123ef4c47c611ebd99d8b41c89c547422aea9c1d))\n* **deps:** update all non-major dependencies ([#13488](https://github.com/vitejs/vite/issues/13488)) ([bd09248](https://github.com/vitejs/vite/commit/bd09248e50ae50ec57b9a72efe0a27aa397ec2e1))\n\n### Documentation\n\n* **legacy:** add test case to ensure correct csp hashes in readme.md ([#13384](https://github.com/vitejs/vite/issues/13384)) ([bf0cd25](https://github.com/vitejs/vite/commit/bf0cd25adb3b8bb5d53433ba9323d0a95e9f756a))\n\n### Miscellaneous Chores\n\n* add funding field ([#13585](https://github.com/vitejs/vite/issues/13585)) ([2501627](https://github.com/vitejs/vite/commit/250162775031a8798f67e8be71fd226a79c9831b))\n* **deps:** update all non-major dependencies ([#13553](https://github.com/vitejs/vite/issues/13553)) ([3ea0534](https://github.com/vitejs/vite/commit/3ea05342d41277baf11a73763f082e6e75c46a8f))\n\n## <small>[4.0.4](https://github.com/vitejs/vite/compare/plugin-legacy@4.0.3...plugin-legacy@4.0.4) (2023-05-24)</small>\n### Bug Fixes\n\n* **legacy:** import `@babel/preset-env` ([#12961](https://github.com/vitejs/vite/issues/12961)) ([d53c650](https://github.com/vitejs/vite/commit/d53c650a69aeb43efd99b210ccc3a5606f2fc31b))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#12805](https://github.com/vitejs/vite/issues/12805)) ([5731ac9](https://github.com/vitejs/vite/commit/5731ac9caaef629e892e20394f0cc73c565d9a87))\n\n## <small>[4.0.3](https://github.com/vitejs/vite/compare/plugin-legacy@4.0.2...plugin-legacy@4.0.3) (2023-04-25)</small>\n### Features\n\n* **plugin-legacy:** support file protocol ([#8524](https://github.com/vitejs/vite/issues/8524)) ([7a87ff4](https://github.com/vitejs/vite/commit/7a87ff4b0950012ad0d85b05fe36b17e1ee2ee76))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#12389](https://github.com/vitejs/vite/issues/12389)) ([3e60b77](https://github.com/vitejs/vite/commit/3e60b778b0ed178a83f674031f5edb123e6c123c))\n\n### Code Refactoring\n\n* **eslint:** migrate to `eslint-plugin-n` ([#12895](https://github.com/vitejs/vite/issues/12895)) ([62ebe28](https://github.com/vitejs/vite/commit/62ebe28d4023c1f67578b1977edd3371f44f475a))\n\n## <small>[4.0.2](https://github.com/vitejs/vite/compare/plugin-legacy@4.0.1...plugin-legacy@4.0.2) (2023-03-16)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#12036](https://github.com/vitejs/vite/issues/12036)) ([48150f2](https://github.com/vitejs/vite/commit/48150f2ea4d7ff8e3b67f15239ae05f5be317436))\n* **plugin-legacy:** no `build.target` override on SSR build ([#12171](https://github.com/vitejs/vite/issues/12171)) ([a1019f8](https://github.com/vitejs/vite/commit/a1019f80a5d5b6242d8fb0975994ce1ae6e78e94))\n\n### Documentation\n\n* **plugin-legacy:** outdated csp hash (fix [#12112](https://github.com/vitejs/vite/issues/12112)) ([#12118](https://github.com/vitejs/vite/issues/12118)) ([5f7f5dc](https://github.com/vitejs/vite/commit/5f7f5dcb0c006012631c1d5df61d79307d9097f4))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#12299](https://github.com/vitejs/vite/issues/12299)) ([b41336e](https://github.com/vitejs/vite/commit/b41336e450b093fb3e454806ec4245ebad7ba9c5))\n* **deps:** update rollup to 3.17.2 ([#12110](https://github.com/vitejs/vite/issues/12110)) ([e54ffbd](https://github.com/vitejs/vite/commit/e54ffbdcbd5d90d560a1bda7a140de046019fcf5))\n\n## <small>[4.0.1](https://github.com/vitejs/vite/compare/plugin-legacy@4.0.0...plugin-legacy@4.0.1) (2023-02-02)</small>\n### Bug Fixes\n\n* **legacy:** fix browserslist import, close https://github.com/vitejs/vite/issues/11898 ([#11899](https://github.com/vitejs/vite/issues/11899)) ([9241d08](https://github.com/vitejs/vite/commit/9241d0895b37c658a2dccfd961958c0c5238a49b))\n\n## [4.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@3.0.1...plugin-legacy@4.0.0) (2023-02-02)\n### ⚠ BREAKING CHANGES\n\n* **legacy:** bump modern target to support async generator (#11896)\n* **plugin-legacy:** support browserslist and update default target (#11318)\n\n### Features\n\n* **legacy:** bump modern target to support async generator ([#11896](https://github.com/vitejs/vite/issues/11896)) ([55b9711](https://github.com/vitejs/vite/commit/55b971139557f65f249f5385b580fa45946cb1d3))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#11846](https://github.com/vitejs/vite/issues/11846)) ([5d55083](https://github.com/vitejs/vite/commit/5d5508311f9856de69babd72dc4de0e7c21c7ae8))\n* **plugin-legacy:** legacy sourcemap not generate (fix [#11693](https://github.com/vitejs/vite/issues/11693)) ([#11841](https://github.com/vitejs/vite/issues/11841)) ([2ff5930](https://github.com/vitejs/vite/commit/2ff5930e02d80d6254037281b4c62b8e489d63ba))\n* **plugin-legacy:** support browserslist and update default target ([#11318](https://github.com/vitejs/vite/issues/11318)) ([d5b8f86](https://github.com/vitejs/vite/commit/d5b8f8615e880e854a3e1105e3193c24cc964f30))\n* typo ([#11283](https://github.com/vitejs/vite/issues/11283)) ([bf234a6](https://github.com/vitejs/vite/commit/bf234a63b46f0dc7a629abe0d69863ac15c381e1))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#11419](https://github.com/vitejs/vite/issues/11419)) ([896475d](https://github.com/vitejs/vite/commit/896475dc6c7e5f1168e21d556201a61659552617))\n* **deps:** update all non-major dependencies ([#11787](https://github.com/vitejs/vite/issues/11787)) ([271394f](https://github.com/vitejs/vite/commit/271394fc7157a08b19f22d3751c8ec6e69f0bd5f))\n* enable `@typescript-eslint/ban-ts-comment` ([#11326](https://github.com/vitejs/vite/issues/11326)) ([e58a4f0](https://github.com/vitejs/vite/commit/e58a4f00e201e9c0d43ddda51ccac7b612d58650))\n* update packages' (vite, vite-legacy) keywords ([#11402](https://github.com/vitejs/vite/issues/11402)) ([a56bc34](https://github.com/vitejs/vite/commit/a56bc3434e9d4bc7f9d580ae630ccc633e7d436a))\n\n### Code Refactoring\n\n* **plugin-legacy:** optimize cspHashes array ([#11734](https://github.com/vitejs/vite/issues/11734)) ([b1a8e58](https://github.com/vitejs/vite/commit/b1a8e5856db91df264a7d1e40bf847dde5eb0981))\n\n## <small>[3.0.1](https://github.com/vitejs/vite/compare/plugin-legacy@3.0.0...plugin-legacy@3.0.1) (2022-12-09)</small>\n### Miscellaneous Chores\n\n* udpate vite and plugins to stable ([#11278](https://github.com/vitejs/vite/issues/11278)) ([026f41e](https://github.com/vitejs/vite/commit/026f41e87e6eb89491c88f62952d7a094f810811))\n\n## [3.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.3.1...plugin-legacy@3.0.0) (2022-12-09)\n\n### Features\n\n* align default chunk and asset file names with rollup ([#10927](https://github.com/vitejs/vite/issues/10927)) ([cc2adb3](https://github.com/vitejs/vite/commit/cc2adb39254d6de139bc3dfad976430c03250b27))\n* rollup 3 ([#9870](https://github.com/vitejs/vite/issues/9870)) ([beb7166](https://github.com/vitejs/vite/commit/beb716695d5dd11fd9f3d7350c1c807dfa37a216))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#10804](https://github.com/vitejs/vite/issues/10804)) ([f686afa](https://github.com/vitejs/vite/commit/f686afa6d3bc0f501b936dcbc2c4552c865fa3f9))\n* **deps:** update all non-major dependencies ([#11091](https://github.com/vitejs/vite/issues/11091)) ([073a4bf](https://github.com/vitejs/vite/commit/073a4bfe2642a4dda2183a9dfecac864524893e1))\n* support polyfill import paths containing an escaping char (e.g. '\\') ([#10859](https://github.com/vitejs/vite/issues/10859)) ([7ac2535](https://github.com/vitejs/vite/commit/7ac2535cfc1eb276237a66f9776f9cda3db1148a))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#11182](https://github.com/vitejs/vite/issues/11182)) ([8b83089](https://github.com/vitejs/vite/commit/8b830899ef0ce4ebe257ed18222543f60b775832))\n* enable prettier trailing commas ([#11167](https://github.com/vitejs/vite/issues/11167)) ([134ce68](https://github.com/vitejs/vite/commit/134ce6817984bad0f5fb043481502531fee9b1db))\n* **deps:** update all non-major dependencies ([#10910](https://github.com/vitejs/vite/issues/10910)) ([f6ad607](https://github.com/vitejs/vite/commit/f6ad607d2430a44ea7dc71ecd3c44c1e8bf8446f))\n* **deps:** update all non-major dependencies ([#11006](https://github.com/vitejs/vite/issues/11006)) ([96f2e98](https://github.com/vitejs/vite/commit/96f2e98f6a196652962ccb5f2fa6195c050c463f))\n\n### Beta Changelogs\n\n#### [3.0.0-alpha.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.3.1...plugin-legacy@3.0.0-alpha.0) (2022-11-30)\n\nSee [3.0.0-alpha.0 changelog](https://github.com/vitejs/vite/blob/plugin-legacy@3.0.0-alpha.0/packages/plugin-legacy/CHANGELOG.md)\n\n## <small>[2.3.1](https://github.com/vitejs/vite/compare/plugin-legacy@2.3.0...plugin-legacy@2.3.1) (2022-11-07)</small>\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#10725](https://github.com/vitejs/vite/issues/10725)) ([22cfad8](https://github.com/vitejs/vite/commit/22cfad87c824e717b6c616129f3b579be2e979b2))\n\n## [2.3.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.3.0-beta.0...plugin-legacy@2.3.0) (2022-10-26)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#10610](https://github.com/vitejs/vite/issues/10610)) ([bb95467](https://github.com/vitejs/vite/commit/bb954672e3ee863e5cb37fa78167e5fc6df9ae4e))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#10393](https://github.com/vitejs/vite/issues/10393)) ([f519423](https://github.com/vitejs/vite/commit/f519423170fafeee9d58aeb2052cb3bc224f25f8))\n* **deps:** update all non-major dependencies ([#10488](https://github.com/vitejs/vite/issues/10488)) ([15aa827](https://github.com/vitejs/vite/commit/15aa827283d6cbf9f55c02d6d8a3fe43dbd792e4))\n\n## [2.3.0-beta.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.2.0...plugin-legacy@2.3.0-beta.0) (2022-10-05)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#10160](https://github.com/vitejs/vite/issues/10160)) ([6233c83](https://github.com/vitejs/vite/commit/6233c830201085d869fbbd2a7e622a59272e0f43))\n* **deps:** update all non-major dependencies ([#10246](https://github.com/vitejs/vite/issues/10246)) ([81d4d04](https://github.com/vitejs/vite/commit/81d4d04c37b805843ea83075d1c0819c31726c4e))\n* **deps:** update all non-major dependencies ([#10316](https://github.com/vitejs/vite/issues/10316)) ([a38b450](https://github.com/vitejs/vite/commit/a38b450441eea02a680b80ac0624126ba6abe3f7))\n* **legacy:** don't force set `build.target` when `renderLegacyChunks=false` (fixes [#10201](https://github.com/vitejs/vite/issues/10201)) ([#10220](https://github.com/vitejs/vite/issues/10220)) ([7f548e8](https://github.com/vitejs/vite/commit/7f548e874a2fb2b09f08fe123bb3ebc10aa2f54b))\n\n### Code Refactoring\n\n* **types:** bundle client types ([#9966](https://github.com/vitejs/vite/issues/9966)) ([da632bf](https://github.com/vitejs/vite/commit/da632bf36f561c0fc4031830721a7d4d86135efb))\n\n## [2.2.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.1.0...plugin-legacy@2.2.0) (2022-09-19)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#10077](https://github.com/vitejs/vite/issues/10077)) ([caf00c8](https://github.com/vitejs/vite/commit/caf00c8c7a5c81a92182116ffa344b34ce4c3b5e))\n* **deps:** update all non-major dependencies ([#9985](https://github.com/vitejs/vite/issues/9985)) ([855f2f0](https://github.com/vitejs/vite/commit/855f2f077eb8dc41b395bccecb6a5b836eb526a9))\n* **plugin-legacy:** force set `build.target` ([#10072](https://github.com/vitejs/vite/issues/10072)) ([a13a7eb](https://github.com/vitejs/vite/commit/a13a7eb4165d38ce0ab6eefd4e4d38104ce63699))\n\n### Documentation\n\n* **plugin-legacy:** fix Vite default target ([#10158](https://github.com/vitejs/vite/issues/10158)) ([62ff788](https://github.com/vitejs/vite/commit/62ff7887870392f0cce2a40b3cc5d1b7c48a9a47))\n\n## [2.1.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.1.0-beta.0...plugin-legacy@2.1.0) (2022-09-05)\n## [2.1.0-beta.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.1...plugin-legacy@2.1.0-beta.0) (2022-08-29)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#9888](https://github.com/vitejs/vite/issues/9888)) ([e35a58b](https://github.com/vitejs/vite/commit/e35a58ba46f906feea8ab46886c3306257c61560))\n* **plugin-legacy:** prevent global process.env.NODE_ENV mutation ([#9741](https://github.com/vitejs/vite/issues/9741)) ([a8279af](https://github.com/vitejs/vite/commit/a8279af608657861b64af5980942cced0b04c8ac))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#9675](https://github.com/vitejs/vite/issues/9675)) ([4e56e87](https://github.com/vitejs/vite/commit/4e56e87623501109198e019ebe809872528ab088))\n* **deps:** update all non-major dependencies ([#9778](https://github.com/vitejs/vite/issues/9778)) ([aceaefc](https://github.com/vitejs/vite/commit/aceaefc19eaa05c76b8a7adec035a0e4b33694c6))\n\n### Code Refactoring\n\n* **legacy:** build polyfill chunk ([#9639](https://github.com/vitejs/vite/issues/9639)) ([7ba0c9f](https://github.com/vitejs/vite/commit/7ba0c9f60e147a0039d2607a10c55e4feecd4bee))\n* **legacy:** remove code for Vite 2 ([#9640](https://github.com/vitejs/vite/issues/9640)) ([b1bbc5b](https://github.com/vitejs/vite/commit/b1bbc5bcc01bfc9b5923e9e58d744c594799a873))\n\n## <small>[2.0.1](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.0...plugin-legacy@2.0.1) (2022-08-11)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#9176](https://github.com/vitejs/vite/issues/9176)) ([31d3b70](https://github.com/vitejs/vite/commit/31d3b70672ea8759a8d7ff1993d64bb4f0e30fab))\n* **deps:** update all non-major dependencies ([#9575](https://github.com/vitejs/vite/issues/9575)) ([8071325](https://github.com/vitejs/vite/commit/80713256d0dd5716e42086fb617e96e9e92c3675))\n* **legacy:** skip esbuild transform for systemjs ([#9635](https://github.com/vitejs/vite/issues/9635)) ([ac16abd](https://github.com/vitejs/vite/commit/ac16abda0a3f96daa61507bda666ade5867ec909))\n* mention that Node.js 13/15 support is dropped (fixes [#9113](https://github.com/vitejs/vite/issues/9113)) ([#9116](https://github.com/vitejs/vite/issues/9116)) ([2826303](https://github.com/vitejs/vite/commit/2826303bd253e20df2746f84f6a7c06cb5cf3d6b))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#9347](https://github.com/vitejs/vite/issues/9347)) ([2fcb027](https://github.com/vitejs/vite/commit/2fcb0272442664c395322acfc7899ab6a32bd86c))\n* **deps:** update all non-major dependencies ([#9478](https://github.com/vitejs/vite/issues/9478)) ([c530d16](https://github.com/vitejs/vite/commit/c530d168309557c7a254128364f07f7b4f017e14))\n* fix code typos ([#9033](https://github.com/vitejs/vite/issues/9033)) ([ed02861](https://github.com/vitejs/vite/commit/ed0286186b24748ec7bfa336f83c382363a22f1d))\n\n## [2.0.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.0-beta.1...plugin-legacy@2.0.0) (2022-07-13)\n### Documentation\n\n* cleanup changes ([#8989](https://github.com/vitejs/vite/issues/8989)) ([07aef1b](https://github.com/vitejs/vite/commit/07aef1b4c02a64732b31b00591d2d9d9c8025aab))\n\n### Miscellaneous Chores\n\n* 3.0 release notes and bump peer deps ([#9072](https://github.com/vitejs/vite/issues/9072)) ([427ba26](https://github.com/vitejs/vite/commit/427ba26fa720a11530d135b2ee39876fc9a778fb))\n* **deps:** update all non-major dependencies ([#9022](https://github.com/vitejs/vite/issues/9022)) ([6342140](https://github.com/vitejs/vite/commit/6342140e6ac7e033ca83d3494f94ea20ca2eaf07))\n\n## [2.0.0-beta.1](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.0-beta.0...plugin-legacy@2.0.0-beta.1) (2022-07-06)\n### Features\n\n* experimental.renderBuiltUrl (revised build base options) ([#8762](https://github.com/vitejs/vite/issues/8762)) ([895a7d6](https://github.com/vitejs/vite/commit/895a7d66bc93beaf18ebcbee23b00fda9ca4c33c))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#8802](https://github.com/vitejs/vite/issues/8802)) ([a4a634d](https://github.com/vitejs/vite/commit/a4a634d6a08f8b54f052cfc2cc1b60c1bca6d48a))\n\n### Miscellaneous Chores\n\n* use `tsx` directly instead of indirect `esno` ([#8773](https://github.com/vitejs/vite/issues/8773)) ([f018f13](https://github.com/vitejs/vite/commit/f018f135ffa5a2885c063d4509d39958c788120c))\n\n## [2.0.0-beta.0](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.0-alpha.2...plugin-legacy@2.0.0-beta.0) (2022-06-21)\n### Features\n\n* bump minimum node version to 14.18.0 ([#8662](https://github.com/vitejs/vite/issues/8662)) ([8a05432](https://github.com/vitejs/vite/commit/8a05432e6dcc0e11d78c7b029e7340fa47fceb92))\n* experimental.buildAdvancedBaseOptions ([#8450](https://github.com/vitejs/vite/issues/8450)) ([8ef7333](https://github.com/vitejs/vite/commit/8ef733368fd6618a252e44616f7577f593fd4fbc))\n\n### Bug Fixes\n\n* **plugin-legacy:** prevent esbuild injecting arrow function ([#8660](https://github.com/vitejs/vite/issues/8660)) ([c0e74e5](https://github.com/vitejs/vite/commit/c0e74e5f687b8f2bb308acb51cd94c31aea2808b))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#8669](https://github.com/vitejs/vite/issues/8669)) ([628863d](https://github.com/vitejs/vite/commit/628863dc6120804cc1af8bda2ea98e802ded0e84))\n* use node prefix ([#8309](https://github.com/vitejs/vite/issues/8309)) ([60721ac](https://github.com/vitejs/vite/commit/60721ac53a1bf326d1cac097f23642faede234ff))\n\n## [2.0.0-alpha.2](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.0-alpha.1...plugin-legacy@2.0.0-alpha.2) (2022-06-19)\n### ⚠ BREAKING CHANGES\n\n* make terser an optional dependency (#8049)\n\n### Bug Fixes\n\n* **build:** use crossorigin for nomodule ([#8322](https://github.com/vitejs/vite/issues/8322)) ([7f59989](https://github.com/vitejs/vite/commit/7f59989ec1fee7f8b71d297169589e010d3b84e3))\n* **deps:** update all non-major dependencies ([#8281](https://github.com/vitejs/vite/issues/8281)) ([c68db4d](https://github.com/vitejs/vite/commit/c68db4d7ad2c1baee41f280b34ae89a85ba0373d))\n* **deps:** update all non-major dependencies ([#8391](https://github.com/vitejs/vite/issues/8391)) ([842f995](https://github.com/vitejs/vite/commit/842f995ca69600c4c06c46d202fe713b80373418))\n* **plugin-legacy:** disable babel.compact when minify is disabled ([#8244](https://github.com/vitejs/vite/issues/8244)) ([742188c](https://github.com/vitejs/vite/commit/742188cc04526439060bdac7125237c20463d5a5))\n* **plugin-legacy:** don't include SystemJS in modern polyfills ([#6902](https://github.com/vitejs/vite/issues/6902)) ([eb47b1e](https://github.com/vitejs/vite/commit/eb47b1e2580cd6f8285dadba8f943e1b667ec390))\n* **plugin-legacy:** empty base makes import fail (fixes [#4212](https://github.com/vitejs/vite/issues/4212)) ([#8387](https://github.com/vitejs/vite/issues/8387)) ([1a16f12](https://github.com/vitejs/vite/commit/1a16f123e0781449c511af2d0112b8c4639972f1))\n* **plugin-legacy:** modern polyfill latest features (fixes [#8399](https://github.com/vitejs/vite/issues/8399)) ([#8408](https://github.com/vitejs/vite/issues/8408)) ([ed25817](https://github.com/vitejs/vite/commit/ed2581778baff3201f47866799f006a490a7e35b))\n* **plugin-legacy:** prevent failed to load module ([#8285](https://github.com/vitejs/vite/issues/8285)) ([d671811](https://github.com/vitejs/vite/commit/d67181195aec99ee6aa71bd8fdb69f1f09f57c9d))\n* **plugin-legacy:** respect `entryFileNames` for polyfill chunks ([#8247](https://github.com/vitejs/vite/issues/8247)) ([baa9632](https://github.com/vitejs/vite/commit/baa9632a2c2befafdfde0f131f84f247fa8b6478))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#8474](https://github.com/vitejs/vite/issues/8474)) ([6d0ede7](https://github.com/vitejs/vite/commit/6d0ede7c60aaa4c010207a047bf30a2b87b5049f))\n* enable `@typescript-eslint/explicit-module-boundary-types` ([#8372](https://github.com/vitejs/vite/issues/8372)) ([104caf9](https://github.com/vitejs/vite/commit/104caf95ecd8cdf2d21ca7171931622b52fd74ff))\n* update major deps ([#8572](https://github.com/vitejs/vite/issues/8572)) ([0e20949](https://github.com/vitejs/vite/commit/0e20949dbf0ba38bdaefbf32a36764fe29858e20))\n* use `esno` to replace `ts-node` ([#8162](https://github.com/vitejs/vite/issues/8162)) ([c18a5f3](https://github.com/vitejs/vite/commit/c18a5f36410e418aaf8309102f1cacf7aef31b43))\n\n### Code Refactoring\n\n* make terser an optional dependency ([#8049](https://github.com/vitejs/vite/issues/8049)) ([164f528](https://github.com/vitejs/vite/commit/164f528838f3a146c82d68992d38316b9214f9b8))\n* **plugin-legacy:** improve default polyfill ([#8312](https://github.com/vitejs/vite/issues/8312)) ([4370d91](https://github.com/vitejs/vite/commit/4370d9123da20c586938753d9f606d84907334c9))\n\n## [2.0.0-alpha.1](https://github.com/vitejs/vite/compare/plugin-legacy@2.0.0-alpha.0...plugin-legacy@2.0.0-alpha.1) (2022-05-19)\n### ⚠ BREAKING CHANGES\n\n* bump targets (#8045)\n* relative base (#7644)\n\n### Features\n\n* relative base ([#7644](https://github.com/vitejs/vite/issues/7644)) ([09648c2](https://github.com/vitejs/vite/commit/09648c220a67852c38da0ba742501a15837e16c2))\n\n### Bug Fixes\n\n* **plugin-legacy:** fail to get the fileName ([#5250](https://github.com/vitejs/vite/issues/5250)) ([c7fc1d4](https://github.com/vitejs/vite/commit/c7fc1d4a532eae7b519bd70c6eba701e23b0635a))\n* rewrite CJS specific funcs/vars in plugins ([#8227](https://github.com/vitejs/vite/issues/8227)) ([9baa70b](https://github.com/vitejs/vite/commit/9baa70b788ec0b0fc419db30d627567242c6af7d))\n\n### Documentation\n\n* use latest core-js unpkg link ([#8190](https://github.com/vitejs/vite/issues/8190)) ([102b678](https://github.com/vitejs/vite/commit/102b678335ba74ac8f0ab94c8c49cba97e836e6d))\n\n### Build System\n\n* bump targets ([#8045](https://github.com/vitejs/vite/issues/8045)) ([66efd69](https://github.com/vitejs/vite/commit/66efd69a399fd73284cc7a3bffc904e154291a14))\n\n## [2.0.0-alpha.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.8.2...plugin-legacy@2.0.0-alpha.0) (2022-05-13)\n### ⚠ BREAKING CHANGES\n\n* remove node v12 support (#7833)\n\n### Documentation\n\n* **plugin-legacy:** remove regenerator-runtime note ([#8007](https://github.com/vitejs/vite/issues/8007)) ([834efe9](https://github.com/vitejs/vite/commit/834efe94fe2c26fcdeabcc34a667dcc6a52326ee))\n\n### Miscellaneous Chores\n\n* bump minors and rebuild lock ([#8074](https://github.com/vitejs/vite/issues/8074)) ([aeb5b74](https://github.com/vitejs/vite/commit/aeb5b7436df5a4d7cf0ee1a9f6f110d00ef7aac1))\n* **deps:** use `esno` to replace `ts-node` ([#8152](https://github.com/vitejs/vite/issues/8152)) ([2363bd3](https://github.com/vitejs/vite/commit/2363bd3e5443aad43351ac16400b5a6ab7e0ef83))\n* revert vitejs/vite[#8152](https://github.com/vitejs/vite/issues/8152) ([#8161](https://github.com/vitejs/vite/issues/8161)) ([85b8b55](https://github.com/vitejs/vite/commit/85b8b55c0d39f53581047f622717d4a009c594f6))\n* update plugins peer deps ([d57c23c](https://github.com/vitejs/vite/commit/d57c23ca9b59491160017cea996fdbff4216263c))\n* use `unbuild` to bundle plugins ([#8139](https://github.com/vitejs/vite/issues/8139)) ([638b168](https://github.com/vitejs/vite/commit/638b1686288ad685243d34cd9f1db3814f4db1c0))\n\n### Build System\n\n* remove node v12 support ([#7833](https://github.com/vitejs/vite/issues/7833)) ([eeac2d2](https://github.com/vitejs/vite/commit/eeac2d2e217ddbca79d5b1dfde9bb5097e821b6a))\n\n## <small>[1.8.2](https://github.com/vitejs/vite/compare/plugin-legacy@1.8.1...plugin-legacy@1.8.2) (2022-05-02)</small>\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#7780](https://github.com/vitejs/vite/issues/7780)) ([eba9d05](https://github.com/vitejs/vite/commit/eba9d05d7adbb5d4dd25f14b085b15eb3488dfe4))\n* **deps:** update all non-major dependencies ([#7847](https://github.com/vitejs/vite/issues/7847)) ([e29d1d9](https://github.com/vitejs/vite/commit/e29d1d92f7810c5160aac2f1e56f7b03bfa4c933))\n* **deps:** update all non-major dependencies ([#7949](https://github.com/vitejs/vite/issues/7949)) ([b877d30](https://github.com/vitejs/vite/commit/b877d30a05691bb6ea2da4e67b931a5a3d32809f))\n\n### Code Refactoring\n\n* **legacy:** remove unneeded dynamic import var init code ([#7759](https://github.com/vitejs/vite/issues/7759)) ([12a4e7d](https://github.com/vitejs/vite/commit/12a4e7d8bbf06d35d6fcc0135dcb76fd06a57c22))\n\n## <small>[1.8.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.8.0...plugin-legacy@1.8.1) (2022-04-13)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#7668](https://github.com/vitejs/vite/issues/7668)) ([485263c](https://github.com/vitejs/vite/commit/485263cdca78e5b30fce77f1af9862b3ea3d76f1))\n\n### Documentation\n\n* **legacy:** note works in build only ([#7596](https://github.com/vitejs/vite/issues/7596)) ([f26b14a](https://github.com/vitejs/vite/commit/f26b14a0d8f4c909cb8cf3188684333b488c0714))\n\n## [1.8.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.7.0...plugin-legacy@1.8.0) (2022-03-30)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#6782](https://github.com/vitejs/vite/issues/6782)) ([e38be3e](https://github.com/vitejs/vite/commit/e38be3e6ca7bf79319d5d7188e1d347b1d6091ef))\n* **deps:** update all non-major dependencies ([#7392](https://github.com/vitejs/vite/issues/7392)) ([b63fc3b](https://github.com/vitejs/vite/commit/b63fc3bbdaf59358b89a0844c264deea1b25c034))\n* **plugin-legacy:** always fallback legacy build when CSP ([#6535](https://github.com/vitejs/vite/issues/6535)) ([a118a1d](https://github.com/vitejs/vite/commit/a118a1d98c63028ddc8b2b3389b8cfa58d771e76))\n* **plugin-legacy:** polyfill latest features ([#7514](https://github.com/vitejs/vite/issues/7514)) ([cb388e2](https://github.com/vitejs/vite/commit/cb388e2dfd39fab751d0656a811c39f8440c48e2))\n* **plugin-legacy:** require Vite 2.8.0 ([#6272](https://github.com/vitejs/vite/issues/6272)) ([#6869](https://github.com/vitejs/vite/issues/6869)) ([997b8f1](https://github.com/vitejs/vite/commit/997b8f11cb156cc374ae991875a09534b5489a93))\n\n### Documentation\n\n* **vite-legacy:** Note about using `regenerator-runtime` in Content Security Policy environment ([#7234](https://github.com/vitejs/vite/issues/7234)) ([0fd6422](https://github.com/vitejs/vite/commit/0fd64223304442bb483c55d818fcf808b7ffbaa8))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#6905](https://github.com/vitejs/vite/issues/6905)) ([839665c](https://github.com/vitejs/vite/commit/839665c5985101c1765f0d68cf429ac96157d062))\n\n## [1.7.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.6.4...plugin-legacy@1.7.0) (2022-02-09)\n### Bug Fixes\n\n* don't force terser on non-legacy (fix [#6266](https://github.com/vitejs/vite/issues/6266)) ([#6272](https://github.com/vitejs/vite/issues/6272)) ([1da104e](https://github.com/vitejs/vite/commit/1da104e8597e2965313e8cd582d032bca551e4ee))\n* **legacy:** fix conflict with the modern build on css emitting ([#6584](https://github.com/vitejs/vite/issues/6584)) ([f48255e](https://github.com/vitejs/vite/commit/f48255e6e0058e973b949fb4a2372974f0480e11)), closes [#3296](https://github.com/vitejs/vite/issues/3296) [#3317](https://github.com/vitejs/vite/issues/3317)\n\n### Miscellaneous Chores\n\n* convert scripts to TS ([#6160](https://github.com/vitejs/vite/issues/6160)) ([15b6f1b](https://github.com/vitejs/vite/commit/15b6f1ba82731c16b19e00ca3b28b1a898caa4d4))\n* **deps:** update all non-major dependencies ([#5879](https://github.com/vitejs/vite/issues/5879)) ([aab303f](https://github.com/vitejs/vite/commit/aab303f7bd333307c77363259f97a310762c4848))\n* **deps:** update all non-major dependencies ([#6185](https://github.com/vitejs/vite/issues/6185)) ([b45f4ad](https://github.com/vitejs/vite/commit/b45f4ad9f1336d1e88d271d7aca9498dde2e5013))\n* **deps:** update all non-major dependencies ([#6357](https://github.com/vitejs/vite/issues/6357)) ([a272c07](https://github.com/vitejs/vite/commit/a272c07e5c442f54e4439a4f3a9da0ebb10f73c9))\n* prefer type imports ([#5835](https://github.com/vitejs/vite/issues/5835)) ([7186857](https://github.com/vitejs/vite/commit/71868579058512b51991718655e089a78b99d39c))\n* properly parse process.env.DEBUG in plugin-legacy ([#6545](https://github.com/vitejs/vite/issues/6545)) ([155fd11](https://github.com/vitejs/vite/commit/155fd11b783eddd33f0cd7e411eea40a3585217a))\n\n## <small>[1.6.4](https://github.com/vitejs/vite/compare/plugin-legacy@1.6.3...plugin-legacy@1.6.4) (2021-12-07)</small>\n### Miscellaneous Chores\n\n* use cjs extension with scripts ([#5877](https://github.com/vitejs/vite/issues/5877)) ([775baba](https://github.com/vitejs/vite/commit/775babac40da546b01b8b8cbd7dff32b5cfcee6d))\n\n## <small>[1.6.3](https://github.com/vitejs/vite/compare/plugin-legacy@1.6.2...plugin-legacy@1.6.3) (2021-11-22)</small>\n### Bug Fixes\n\n* **build:** resolve `rollupOptions.input` paths ([#5601](https://github.com/vitejs/vite/issues/5601)) ([5b6b016](https://github.com/vitejs/vite/commit/5b6b01693720290e8998b2613f0dcb2d699ee84f))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#5679](https://github.com/vitejs/vite/issues/5679)) ([09f4d57](https://github.com/vitejs/vite/commit/09f4d57e12de46ffc5fa151c218f31845ad4b471))\n* **deps:** update all non-major dependencies ([#5783](https://github.com/vitejs/vite/issues/5783)) ([eee9406](https://github.com/vitejs/vite/commit/eee940678b76966647b543e1f10fdb113da64b21))\n* **deps:** update non critical deps ([#5569](https://github.com/vitejs/vite/issues/5569)) ([09e2a5f](https://github.com/vitejs/vite/commit/09e2a5f16f36d84e95448a9ae819cec5faeb41f3))\n* **deps:** update plugins ([#5462](https://github.com/vitejs/vite/issues/5462)) ([50b5e2e](https://github.com/vitejs/vite/commit/50b5e2ea2605ba392fa622c9419b8cb5da69e0d2))\n\n## <small>[1.6.2](https://github.com/vitejs/vite/compare/plugin-legacy@1.6.1...plugin-legacy@1.6.2) (2021-10-11)</small>\n### Features\n\n* add `build.cssTarget` option ([#5132](https://github.com/vitejs/vite/issues/5132)) ([b17444f](https://github.com/vitejs/vite/commit/b17444fd97b02bc54410c8575e7d3cb25e4058c2)), closes [#4746](https://github.com/vitejs/vite/issues/4746) [#5070](https://github.com/vitejs/vite/issues/5070) [#4930](https://github.com/vitejs/vite/issues/4930)\n\n## <small>[1.6.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.6.0...plugin-legacy@1.6.1) (2021-10-05)</small>\n### Bug Fixes\n\n* **plugin-legacy:** use terser as the default minifier ([#5168](https://github.com/vitejs/vite/issues/5168)) ([9ee7234](https://github.com/vitejs/vite/commit/9ee72343884a7d679767833f7a659bbca6b96595))\n\n## [1.6.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.5.3...plugin-legacy@1.6.0) (2021-09-29)\n### Features\n\n* **plugin-legacy:** add externalSystemJS option ([#5024](https://github.com/vitejs/vite/issues/5024)) ([60b6f55](https://github.com/vitejs/vite/commit/60b6f5595a00cbf014a30d57721081eb79436a97))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#4545](https://github.com/vitejs/vite/issues/4545)) ([a44fd5d](https://github.com/vitejs/vite/commit/a44fd5d38679da0be2536103e83af730cda73a95))\n* esbuild minification and renderLegacyChunks false ([#5054](https://github.com/vitejs/vite/issues/5054)) ([ed384cf](https://github.com/vitejs/vite/commit/ed384cfeff9e3ccb0fdbb07ec91758308da66226))\n* normalize internal plugin names ([#4976](https://github.com/vitejs/vite/issues/4976)) ([37f0b2f](https://github.com/vitejs/vite/commit/37f0b2fff74109d381513ed052a32b43655ee11d))\n* **plugin-legacy:** fix type errors ([#4762](https://github.com/vitejs/vite/issues/4762)) ([5491143](https://github.com/vitejs/vite/commit/5491143be0b4214d2dab91076a85739d6d106481))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#4992](https://github.com/vitejs/vite/issues/4992)) ([5274c2e](https://github.com/vitejs/vite/commit/5274c2e9fbfd7d80392b5d0c9daacbe2d7237649))\n* **deps:** update all non-major dependencies ([#5100](https://github.com/vitejs/vite/issues/5100)) ([b2ae627](https://github.com/vitejs/vite/commit/b2ae627c74ee8aeff82c80d3461ae3004d0d8369))\n* prettier format ([#5121](https://github.com/vitejs/vite/issues/5121)) ([16fc894](https://github.com/vitejs/vite/commit/16fc8942e2b2181d78359cdc37e85a17be031af4))\n\n## <small>[1.5.3](https://github.com/vitejs/vite/compare/plugin-legacy@1.5.2...plugin-legacy@1.5.3) (2021-09-07)</small>\n### Bug Fixes\n\n* **plugin-legacy:** fix regression introduced in [#4536](https://github.com/vitejs/vite/issues/4536) ([#4861](https://github.com/vitejs/vite/issues/4861)) ([fdc3212](https://github.com/vitejs/vite/commit/fdc3212474ff951e7e67810eca6cfb3ef1ed9ea2))\n* **plugin-legacy:** skip in SSR build ([#4536](https://github.com/vitejs/vite/issues/4536)) ([1f068fc](https://github.com/vitejs/vite/commit/1f068fcec38fc07c34e75a19821064386e460907))\n\n## <small>[1.5.2](https://github.com/vitejs/vite/compare/plugin-legacy@1.5.1...plugin-legacy@1.5.2) (2021-09-01)</small>\n### Bug Fixes\n\n* **plugin-legacy:** avoid executing blank dynamic import ([#4767](https://github.com/vitejs/vite/issues/4767)) ([de71408](https://github.com/vitejs/vite/commit/de7140853140029a3f48600b60e700464e7662b5)), closes [#4568](https://github.com/vitejs/vite/issues/4568)\n\n### Documentation\n\n* include algorithm in Content Security Policy hash ([#4690](https://github.com/vitejs/vite/issues/4690)) ([6815edd](https://github.com/vitejs/vite/commit/6815eddbb94f60bf0c08f91ee9404d93357eb602))\n\n## <small>[1.5.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.5.0...plugin-legacy@1.5.1) (2021-08-03)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#4468](https://github.com/vitejs/vite/issues/4468)) ([cd54a22](https://github.com/vitejs/vite/commit/cd54a22b8d5048f5d25a9954697f49b6d65dcc1f))\n* **plugin-legacy:** bake-in Promise polyfill, fix [#4414](https://github.com/vitejs/vite/issues/4414) ([#4440](https://github.com/vitejs/vite/issues/4440)) ([024a2de](https://github.com/vitejs/vite/commit/024a2de63df60a4037f9f7b13a0bc6e2b0d41fb6))\n\n## [1.5.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.4.4...plugin-legacy@1.5.0) (2021-07-27)\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#4387](https://github.com/vitejs/vite/issues/4387)) ([2f900ba](https://github.com/vitejs/vite/commit/2f900ba4d4ad8061e0046898e8d1de3129e7f784))\n* **plugin-legacy:** legacy fallback for dynamic import ([#3885](https://github.com/vitejs/vite/issues/3885)) ([fc6d8f1](https://github.com/vitejs/vite/commit/fc6d8f1d3efe836f17f3c45375dd3749128b8137))\n\n## <small>[1.4.4](https://github.com/vitejs/vite/compare/plugin-legacy@1.4.3...plugin-legacy@1.4.4) (2021-07-12)</small>\n### Features\n\n* allow entryFileNames, chunkFileNames functions for legacy ([#4122](https://github.com/vitejs/vite/issues/4122)) ([df29bff](https://github.com/vitejs/vite/commit/df29bfff44ad7f2e822f92935d0ca9c99f15b67e))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#4117](https://github.com/vitejs/vite/issues/4117)) ([e30ce56](https://github.com/vitejs/vite/commit/e30ce56861a154389a47e679c46a93680aae1325))\n* improve prettier config ([#4154](https://github.com/vitejs/vite/issues/4154)) ([98d95e3](https://github.com/vitejs/vite/commit/98d95e3e11bbc43e410b213b682e315b9344d2d7))\n\n## <small>[1.4.3](https://github.com/vitejs/vite/compare/plugin-legacy@1.4.2...plugin-legacy@1.4.3) (2021-06-27)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#3878](https://github.com/vitejs/vite/issues/3878)) ([a66a805](https://github.com/vitejs/vite/commit/a66a8053e9520d20bcf95fce870570c5195bcc91))\n* don't force polyfillDynamicImport if renderLegacyChunks is false ([#3695](https://github.com/vitejs/vite/issues/3695)) ([#3774](https://github.com/vitejs/vite/issues/3774)) ([d2a51ca](https://github.com/vitejs/vite/commit/d2a51ca4eda2ca9f99d9a066836d76d2253cfc24))\n* **plugin-legacy:** chunk may not exist ([#3886](https://github.com/vitejs/vite/issues/3886)) ([dd5931d](https://github.com/vitejs/vite/commit/dd5931d9c1cf382849047332b2c3409755ceebf5))\n\n## <small>[1.4.2](https://github.com/vitejs/vite/compare/plugin-legacy@1.4.1...plugin-legacy@1.4.2) (2021-06-22)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#3791](https://github.com/vitejs/vite/issues/3791)) ([74d409e](https://github.com/vitejs/vite/commit/74d409eafca8d74ec4a6ece621ea2895bc1f2a32))\n* **plugin-legacy:** wrap chunks in IIFE ([#3783](https://github.com/vitejs/vite/issues/3783)) ([9abdb81](https://github.com/vitejs/vite/commit/9abdb8137ef54dd095e7bc47ae6a1ccf490fd196))\n\n## <small>[1.4.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.4.0...plugin-legacy@1.4.1) (2021-06-01)</small>\n### Bug Fixes\n\n* **plugin-legacy:** respect custom filenames formats, fix [#2356](https://github.com/vitejs/vite/issues/2356) ([#2641](https://github.com/vitejs/vite/issues/2641)) ([d852731](https://github.com/vitejs/vite/commit/d852731622a1c009d15a5172343fc166c4bb5cb7))\n\n## [1.4.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.3.4...plugin-legacy@1.4.0) (2021-05-17)\n### Bug Fixes\n\n* **plugin-legacy:** turn off babel loose mode ([#3406](https://github.com/vitejs/vite/issues/3406)) ([5348c02](https://github.com/vitejs/vite/commit/5348c02f58bde36c412dbfe36c3ad37772bf83e5))\n* restore dynamic-import-polyfill ([#3434](https://github.com/vitejs/vite/issues/3434)) ([4112c5d](https://github.com/vitejs/vite/commit/4112c5d103673b83c50d446096086617dfaac5a3))\n\n### Documentation\n\n* **plugin-legacy:** add note about IE11, close [#3362](https://github.com/vitejs/vite/issues/3362) ([#3389](https://github.com/vitejs/vite/issues/3389)) ([b0b62f9](https://github.com/vitejs/vite/commit/b0b62f96d7d4b04d3bfea683feff84c8b31f1eca))\n\n## <small>[1.3.4](https://github.com/vitejs/vite/compare/plugin-legacy@1.3.3...plugin-legacy@1.3.4) (2021-05-11)</small>\n### Bug Fixes\n\n* **plugin-legacy:** move polyfills in plugin post, fixes [#2786](https://github.com/vitejs/vite/issues/2786) and [#2781](https://github.com/vitejs/vite/issues/2781) ([#3023](https://github.com/vitejs/vite/issues/3023)) ([43150e3](https://github.com/vitejs/vite/commit/43150e352d164744e2fda766927053439bdf7db9))\n* **plugin-legacy:** require Vite 2.0.0 final ([#3265](https://github.com/vitejs/vite/issues/3265)) ([e395dee](https://github.com/vitejs/vite/commit/e395deeb0f11ebb1bcebe69233adebaad10f77eb))\n\n## <small>[1.3.3](https://github.com/vitejs/vite/compare/plugin-legacy@1.3.2...plugin-legacy@1.3.3) (2021-05-03)</small>\n### Bug Fixes\n\n* ignore babelrc in legacy plugin ([#2801](https://github.com/vitejs/vite/issues/2801)) ([d466ad0](https://github.com/vitejs/vite/commit/d466ad0a095859a895fd4cb85f425ad4c4583e4e))\n* **plugin-legacy:** correct log level to error ([#3241](https://github.com/vitejs/vite/issues/3241)) ([474fe9a](https://github.com/vitejs/vite/commit/474fe9a3abbdf4845447eaab821d2ba51fda6207))\n\n### Miscellaneous Chores\n\n* Add `repository.directory` to `packages/**/package.json` ([#2687](https://github.com/vitejs/vite/issues/2687)) ([0ecff94](https://github.com/vitejs/vite/commit/0ecff9417ee0ccfea9132fb9df39eb4398c11eaf))\n\n### Tests\n\n* fix timeout hiding runtime build error ([#3185](https://github.com/vitejs/vite/issues/3185)) ([978d991](https://github.com/vitejs/vite/commit/978d991293f5b8e1a4197ac4e3aee4fa2e838a88))\n\n## <small>[1.3.2](https://github.com/vitejs/vite/compare/plugin-legacy@1.3.1...plugin-legacy@1.3.2) (2021-03-27)</small>\n### Bug Fixes\n\n* typo in plugin-legacy ([#2651](https://github.com/vitejs/vite/issues/2651)) ([9a2ce75](https://github.com/vitejs/vite/commit/9a2ce7580772cb783a9f8fda7e45e4a9adacbec2))\n\n### Miscellaneous Chores\n\n* **plugin-legacy:** upgrade @babel/standalone to 7.13.12 ([#2649](https://github.com/vitejs/vite/issues/2649)) ([4b89f5b](https://github.com/vitejs/vite/commit/4b89f5b97e715cff9078a528d06ef1255dfff293))\n* **plugin-legacy:** upgrade @babel/standalone to 7.13.6 ([#2198](https://github.com/vitejs/vite/issues/2198)) ([609f8aa](https://github.com/vitejs/vite/commit/609f8aa726d81a4094b60d3e0374c78238837a07))\n\n## <small>[1.3.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.3.0...plugin-legacy@1.3.1) (2021-02-15)</small>\n### Bug Fixes\n\n* **plugin-legacy:** prevent constant folding for import.meta.env.LEGACY ([bace724](https://github.com/vitejs/vite/commit/bace7244e776b3f4c9dd7e3ff1885df668cbcb87)), closes [#1999](https://github.com/vitejs/vite/issues/1999)\n* **plugin-legacy:** use correct string length in legacy env replacement ([#2015](https://github.com/vitejs/vite/issues/2015)) ([7f48086](https://github.com/vitejs/vite/commit/7f4808634f57ca8f4be3b455cc4fb8016acdc4fd))\n\n### Miscellaneous Chores\n\n* **plugin-legacy:** typo ([#2004](https://github.com/vitejs/vite/issues/2004)) [skip ci] ([5225253](https://github.com/vitejs/vite/commit/5225253bc9730b2db1a8b62642cd1496053fce6e))\n\n## [1.3.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.2.3...plugin-legacy@1.3.0) (2021-02-11)\n### Features\n\n* **plugin-legacy:** inject import.meta.env.LEGACY ([416f190](https://github.com/vitejs/vite/commit/416f190aa92f06a06f3ded403fb1e4cb8729256d))\n\n### Code Refactoring\n\n* remove unused ast, adjust logic ([859fed6](https://github.com/vitejs/vite/commit/859fed6780e2412e64e27aa841a7de0aa2986728))\n\n## <small>[1.2.3](https://github.com/vitejs/vite/compare/plugin-legacy@1.2.2...plugin-legacy@1.2.3) (2021-02-01)</small>\n### Features\n\n* **plugin-legacy:** use compact output when transpiling legacy chunks ([045e519](https://github.com/vitejs/vite/commit/045e519d51fbce94bddb60793e9e99311acc5aa2)), closes [#1828](https://github.com/vitejs/vite/issues/1828)\n\n### Code Refactoring\n\n* **plugin-legacy:** improve polyfill import removal strategy ([e40e6b2](https://github.com/vitejs/vite/commit/e40e6b29e62acf8300de5cca16e376bfeb27bc5e))\n\n## <small>[1.2.2](https://github.com/vitejs/vite/compare/plugin-legacy@1.2.1...plugin-legacy@1.2.2) (2021-01-25)</small>\n### Features\n\n* default vendor chunk splitting ([f6b58a0](https://github.com/vitejs/vite/commit/f6b58a0f535b1c26f9c1dfda74c28c685402c3c9))\n* support `base` option during dev, deprecate `build.base` ([#1556](https://github.com/vitejs/vite/issues/1556)) ([809d4bd](https://github.com/vitejs/vite/commit/809d4bd3bf62d3bc6b35f182178922d2ab2175f1))\n\n### Bug Fixes\n\n* **plugin-legacy:** throw error when using esbuild minify with legacy plugin ([8fb2511](https://github.com/vitejs/vite/commit/8fb2511a02c163d85f60dfab0bef104756768e35))\n\n## <small>[1.2.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.2.0...plugin-legacy@1.2.1) (2021-01-14)</small>\n### Bug Fixes\n\n* **plugin-legacy:** respect config.build.assetsDir ([#1532](https://github.com/vitejs/vite/issues/1532)) ([3e7ad3f](https://github.com/vitejs/vite/commit/3e7ad3fa26a6149b44b2e522648cbda1009e4888)), closes [#1530](https://github.com/vitejs/vite/issues/1530)\n\n## [1.2.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.1.1...plugin-legacy@1.2.0) (2021-01-11)\n### Features\n\n* **plugin-legacy:** support additionalLegacyPolyfills ([ca25896](https://github.com/vitejs/vite/commit/ca258962957c32df0196f30267c3d77b544aacbd)), closes [#1475](https://github.com/vitejs/vite/issues/1475)\n\n### Bug Fixes\n\n* **plugin-html:** typo in the Safari 10 nomodule snippet ([#1483](https://github.com/vitejs/vite/issues/1483)) ([e5576c3](https://github.com/vitejs/vite/commit/e5576c32c08214766c8bac5458dfcad8301d3a1a))\n\n## <small>[1.1.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.1.0...plugin-legacy@1.1.1) (2021-01-09)</small>\n### Bug Fixes\n\n* **plugin-legacy:** add `index.d.ts` at publish ([#1457](https://github.com/vitejs/vite/issues/1457)) ([dce2456](https://github.com/vitejs/vite/commit/dce245629651edab9719127deaf07ecfbcf20c5f))\n\n### Documentation\n\n* **plugin-legacy:** fix typos ([#1422](https://github.com/vitejs/vite/issues/1422)) [skip ci] ([16cf3d0](https://github.com/vitejs/vite/commit/16cf3d0cc758591c2a44abbf10b7f2fd21d5ef99))\n* Typo in plugin-legacy README ([#1455](https://github.com/vitejs/vite/issues/1455)) [skip ci] ([4647e07](https://github.com/vitejs/vite/commit/4647e072cb89d6eac648a66314f26cb6b65c68b4))\n\n### Miscellaneous Chores\n\n* add version badge for plugins [skip ci] ([62925eb](https://github.com/vitejs/vite/commit/62925eb4da2ce2053e3d28068db5423e2e66ae3d))\n\n## [1.1.0](https://github.com/vitejs/vite/compare/plugin-legacy@1.0.1...plugin-legacy@1.1.0) (2021-01-07)\n### Features\n\n* use constant inline script + provide CSP hashes ([72107cd](https://github.com/vitejs/vite/commit/72107cdcdb7241e9fadd67528abb14f54b1c901d))\n\n## <small>[1.0.1](https://github.com/vitejs/vite/compare/plugin-legacy@1.0.0...plugin-legacy@1.0.1) (2021-01-07)</small>\n### Features\n\n* **plugin-legacy:** @vitejs/plugin-legacy ([8c34870](https://github.com/vitejs/vite/commit/8c34870040f8c2f4be7d00245a3683f9e64d894e))\n\n### Bug Fixes\n\n* add promise polyfill if not used in bundle ([b72db4e](https://github.com/vitejs/vite/commit/b72db4e3ec5ca8974ea2f1913d5611f73c0978b5))\n* **plugin-legacy:** avoid esbuild transform on legacy chunks ([7734105](https://github.com/vitejs/vite/commit/7734105093c6dabf64da6bfc11486aa9ac62efea))\n\n### Performance Improvements\n\n* use @babel/standalone + lazy load ([b2f98fb](https://github.com/vitejs/vite/commit/b2f98fba0215ef171af2abc62e3aefc35f00d168))\n\n### Documentation\n\n* **plugin-legacy:** fix typo ([#1411](https://github.com/vitejs/vite/issues/1411)) ([3321111](https://github.com/vitejs/vite/commit/3321111c77f33ccb9bc06bfa84f6d3fc27902a6e))\n\n### Miscellaneous Chores\n\n* add plugin-legacy version requirement ([3b7a07a](https://github.com/vitejs/vite/commit/3b7a07ac5c7422b01577a26b2ca5b8e1e7001fa3))\n* changelog for plugin-legacy [skip ci] ([52ac81a](https://github.com/vitejs/vite/commit/52ac81a14298bf41e11f3bc0d2ae870d67b5ae9d))\n\n# 1.0.0 (2021-01-07)\n\n\n### Features\n\n* **plugin-legacy:** @vitejs/plugin-legacy ([8c34870](https://github.com/vitejs/vite/commit/8c34870040f8c2f4be7d00245a3683f9e64d894e))\n"
  },
  {
    "path": "packages/plugin-legacy/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019-present, VoidZero Inc. and Vite contributors\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": "packages/plugin-legacy/README.md",
    "content": "# @vitejs/plugin-legacy [![npm](https://img.shields.io/npm/v/@vitejs/plugin-legacy.svg)](https://npmjs.com/package/@vitejs/plugin-legacy)\n\nVite's minimum browser support target is [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta). This plugin provides support for legacy browsers that do not support those features when building for production.\n\nBy default, this plugin will:\n\n- Generate a corresponding legacy chunk for every chunk in the final bundle, transformed with [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env) and emitted as [SystemJS modules](https://github.com/systemjs/systemjs) (code splitting is still supported!).\n\n- Generate a polyfill chunk including SystemJS runtime, and any necessary polyfills determined by specified browser targets and **actual usage** in the bundle.\n\n- Inject `<script nomodule>` tags into generated HTML to conditionally load the polyfills and legacy bundle only in browsers without widely-available features support.\n\n- Inject the `import.meta.env.LEGACY` env variable, which will only be `true` in the legacy production build, and `false` in all other cases.\n\n## Usage\n\n```js\n// vite.config.js\nimport legacy from '@vitejs/plugin-legacy'\n\nexport default {\n  plugins: [\n    legacy({\n      targets: ['defaults', 'not IE 11'],\n    }),\n  ],\n}\n```\n\nTerser must be installed because plugin-legacy uses Terser for minification.\n\n```sh\nnpm add -D terser\n```\n\n## Options\n\n### `targets`\n\n- **Type:** `string | string[] | { [key: string]: string }`\n- **Default:** [`'last 2 versions and not dead, > 0.3%, Firefox ESR'`](https://browsersl.ist/#q=last+2+versions+and+not+dead%2C+%3E+0.3%25%2C+Firefox+ESR)\n\n  It's passed on to [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env#targets) when rendering **legacy chunks**.\n\n  The query is also [Browserslist compatible](https://github.com/browserslist/browserslist). See [Browserslist Best Practices](https://github.com/browserslist/browserslist#best-practices) for more details.\n\n  If it's not set, plugin-legacy will load [the browserslist config sources](https://github.com/browserslist/browserslist#queries) and then fallback to the default value.\n\n### `modernTargets`\n\n- **Type:** `string | string[]`\n- **Default:** [`'edge>=105, firefox>=106, chrome>=105, safari>=16.4, chromeAndroid>=105, iOS>=16.4'`](https://browsersl.ist/#q=edge%3E%3D105%2C+firefox%3E%3D106%2C+chrome%3E%3D105%2C+safari%3E%3D16.4%2C+chromeAndroid%3E%3D105%2C+iOS%3E%3D16.4)\n\n  It's passed on to [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env#targets) when collecting polyfills for **modern chunks**. The value set here will override the `build.target` option.\n\n  The query is also [Browserslist compatible](https://github.com/browserslist/browserslist). See [Browserslist Best Practices](https://github.com/browserslist/browserslist#best-practices) for more details.\n\n  If it's not set, plugin-legacy will fallback to the default value.\n\n  Note that this options should not be set unless `renderLegacyChunks` is set to `false`.\n\n### `polyfills`\n\n- **Type:** `boolean | string[]`\n- **Default:** `true`\n\n  By default, a polyfills chunk is generated based on the target browser ranges and actual usage in the final bundle (detected via `@babel/preset-env`'s `useBuiltIns: 'usage'`).\n\n  Set to a list of strings to explicitly control which polyfills to include. See [Polyfill Specifiers](#polyfill-specifiers) for details.\n\n  Set to `false` to avoid generating polyfills and handle it yourself (will still generate legacy chunks with syntax transformations).\n\n### `additionalLegacyPolyfills`\n\n- **Type:** `string[]`\n\n  Add custom imports to the legacy polyfills chunk. Since the usage-based polyfill detection only covers ES language features, it may be necessary to manually specify additional DOM API polyfills using this option.\n\n### `additionalModernPolyfills`\n\n- **Type:** `string[]`\n\n  Add custom imports to the modern polyfills chunk. Since the usage-based polyfill detection only covers ES language features, it may be necessary to manually specify additional DOM API polyfills using this option.\n\n### `modernPolyfills`\n\n- **Type:** `boolean | string[]`\n- **Default:** `false`\n\n  Defaults to `false`. Enabling this option will generate a separate polyfills chunk for the modern build (targeting [browsers that support widely-available features](#browsers-that-supports-esm-but-does-not-support-widely-available-features)).\n\n  Set to a list of strings to explicitly control which polyfills to include. See [Polyfill Specifiers](#polyfill-specifiers) for details.\n\n  If `modernTargets` is not set, it is **not recommended** to use the `true` value (which uses auto-detection) because `core-js@3` is very aggressive in polyfill inclusions due to all the bleeding edge features it supports. Even when targeting native ESM support, it injects 15kb of polyfills!\n\n  If you don't have hard reliance on bleeding edge runtime features, it is not that hard to avoid having to use polyfills in the modern build altogether. Alternatively, consider setting `modernTargets` or using an on-demand service like https://cdnjs.cloudflare.com/polyfill/ to only inject necessary polyfills based on actual browser user-agents (most modern browsers will need nothing!).\n\n### `renderLegacyChunks`\n\n- **Type:** `boolean`\n- **Default:** `true`\n\n  Set to `false` to disable legacy chunks. This is only useful if you are using `modernPolyfills`, which essentially allows you to use this plugin for injecting polyfills to the modern build only:\n\n  ```js\n  import legacy from '@vitejs/plugin-legacy'\n\n  export default {\n    plugins: [\n      legacy({\n        modernPolyfills: [\n          /* ... */\n        ],\n        renderLegacyChunks: false,\n      }),\n    ],\n  }\n  ```\n\n### `externalSystemJS`\n\n- **Type:** `boolean`\n- **Default:** `false`\n\n  Defaults to `false`. Enabling this option will exclude `systemjs/dist/s.min.js` inside polyfills-legacy chunk.\n\n### `renderModernChunks`\n\n- **Type:** `boolean`\n- **Default:** `true`\n\n  Set to `false` to only output the legacy bundles that support all target browsers.\n\n  This is also useful when running the project locally using `file:` protocol, as loading modern chunks with `type=\"module\"` may trigger CORS restrictions. To avoid this issue, simply set `renderModernChunks` to `false` to exclusively use legacy chunks instead.\n\n## Browsers that supports ESM but does not support widely-available features\n\nThe legacy plugin offers a way to use widely-available features natively in the modern build, while falling back to the legacy build in browsers with native ESM but without those features supported (e.g. Legacy Edge). This feature works by injecting a runtime check and loading the legacy bundle with SystemJS runtime if needed. There are the following drawbacks:\n\n- Modern bundle is downloaded in all ESM browsers\n- Modern bundle throws an error in browsers without those features support\n\nThe following features are considered as widely-available:\n\n- dynamic import\n- async generator\n- `import.meta.resolve`\n\n## Polyfill Specifiers\n\nPolyfill specifier strings for `polyfills` and `modernPolyfills` can be either of the following:\n\n- Any [`core-js` 3 sub import paths](https://unpkg.com/browse/core-js@latest/) - e.g. `es/map` will import `core-js/es/map`\n\n- Any [individual `core-js` 3 modules](https://unpkg.com/browse/core-js@latest/modules/) - e.g. `es.array.iterator` will import `core-js/modules/es.array.iterator.js`\n\n**Example**\n\n```js\nimport legacy from '@vitejs/plugin-legacy'\n\nexport default {\n  plugins: [\n    legacy({\n      polyfills: ['es.promise.finally', 'es/map', 'es/set'],\n      modernPolyfills: ['es.promise.finally'],\n    }),\n  ],\n}\n```\n\n## Content Security Policy\n\nThe legacy plugin requires inline scripts for [Safari 10.1 `nomodule` fix](https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc), SystemJS initialization, and dynamic import fallback. If you have a strict CSP policy requirement, you will need to [add the corresponding hashes to your `script-src` list](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_inline_script).\n\nThe hash values (without the `sha256-` prefix) can be retrieved via:\n\n```js\nimport { cspHashes } from '@vitejs/plugin-legacy'\n```\n\nThe current values are:\n\n- `sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=`\n- `sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=`\n- `sha256-w36slEqa9euNKxfvkw+LLGsDIr++3rsZXpZxtmRh8Aw=`\n- `sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc=`\n\n<!--\nRun `node --input-type=module -e \"import {cspHashes} from '@vitejs/plugin-legacy'; console.log(cspHashes.map(h => 'sha256-'+h))\"` to retrieve the value.\n-->\n\nNote that these values could change between minor versions. Thus, we recommend generating the CSP header from the exported `cspHashes` variable. If you copy the values manually, then you should pin the minor version using `~`.\n\nWhen using the `regenerator-runtime` polyfill, it will attempt to use the `globalThis` object to register itself. If `globalThis` is not available (it is [fairly new](https://caniuse.com/?search=globalThis) and not widely supported, including IE 11), it attempts to perform dynamic `Function(...)` call which violates the CSP. To avoid dynamic `eval` in the absence of `globalThis` consider adding `core-js/proposals/global-this` to `additionalLegacyPolyfills` to define it.\n\n## References\n\n- [Vue CLI modern mode](https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode)\n- [Using Native JavaScript Modules in Production Today](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/)\n- [rollup-native-modules-boilerplate](https://github.com/philipwalton/rollup-native-modules-boilerplate)\n"
  },
  {
    "path": "packages/plugin-legacy/package.json",
    "content": "{\n  \"name\": \"@vitejs/plugin-legacy\",\n  \"version\": \"8.0.0\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"author\": \"Evan You\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"keywords\": [\n    \"frontend\",\n    \"vite\",\n    \"vite-plugin\",\n    \"@vitejs/plugin-legacy\"\n  ],\n  \"exports\": \"./dist/index.js\",\n  \"scripts\": {\n    \"dev\": \"tsdown --watch\",\n    \"build\": \"tsdown\",\n    \"prepublishOnly\": \"npm run build\"\n  },\n  \"engines\": {\n    \"node\": \"^20.19.0 || >=22.12.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitejs/vite.git\",\n    \"directory\": \"packages/plugin-legacy\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitejs/vite/issues\"\n  },\n  \"homepage\": \"https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme\",\n  \"funding\": \"https://github.com/vitejs/vite?sponsor=1\",\n  \"dependencies\": {\n    \"@babel/core\": \"^7.29.0\",\n    \"@babel/plugin-transform-dynamic-import\": \"^7.27.1\",\n    \"@babel/plugin-transform-modules-systemjs\": \"^7.29.0\",\n    \"@babel/preset-env\": \"^7.29.0\",\n    \"babel-plugin-polyfill-corejs3\": \"^0.14.1\",\n    \"babel-plugin-polyfill-regenerator\": \"^0.6.7\",\n    \"browserslist\": \"^4.28.1\",\n    \"browserslist-to-esbuild\": \"^2.1.1\",\n    \"core-js\": \"^3.48.0\",\n    \"magic-string\": \"^0.30.21\",\n    \"regenerator-runtime\": \"^0.14.1\",\n    \"systemjs\": \"^6.15.1\"\n  },\n  \"peerDependencies\": {\n    \"terser\": \"^5.16.0\",\n    \"vite\": \"^8.0.0\"\n  },\n  \"devDependencies\": {\n    \"acorn\": \"^8.16.0\",\n    \"picocolors\": \"^1.1.1\",\n    \"tsdown\": \"^0.21.4\",\n    \"vite\": \"workspace:*\"\n  },\n  \"compatiblePackages\": {\n    \"schemaVersion\": 1,\n    \"rolldown\": {\n      \"type\": \"incompatible\",\n      \"reason\": \"Only supports Vite\"\n    },\n    \"rollup\": {\n      \"type\": \"incompatible\",\n      \"reason\": \"Only supports Vite\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/plugin-legacy/src/__tests__/readme.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { cspHashes } from '..'\n\ntest('CSP hashes in README.md should be correct', () => {\n  const readme = fs.readFileSync(\n    path.resolve(import.meta.dirname, '../../README.md'),\n    'utf-8',\n  )\n  const hashesInDoc = [...readme.matchAll(/`sha256-(.+)`/g)].map(\n    (match) => match[1],\n  )\n\n  expect(hashesInDoc).toStrictEqual(cspHashes)\n})\n"
  },
  {
    "path": "packages/plugin-legacy/src/__tests__/snippets.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport type { ecmaVersion } from 'acorn'\nimport { parse } from 'acorn'\nimport {\n  detectModernBrowserCode,\n  detectModernBrowserDetector,\n  dynamicFallbackInlineCode,\n  safari10NoModuleFix,\n  systemJSInlineCode,\n} from '../snippets'\n\nconst shouldFailVersions: ecmaVersion[] = []\nfor (let v = 2015; v <= 2019; v++) {\n  shouldFailVersions.push(v as ecmaVersion)\n}\n\nconst shouldPassVersions: ecmaVersion[] = []\nfor (let v = 2020; v <= 2024; v++) {\n  shouldPassVersions.push(v as ecmaVersion)\n}\n\nfor (const version of shouldFailVersions) {\n  test(`detect code should not be able to be parsed with ES${version}`, () => {\n    expect(() => {\n      parse(detectModernBrowserDetector, {\n        ecmaVersion: version,\n        sourceType: 'module',\n      })\n    }).toThrow()\n  })\n}\n\nfor (const version of shouldPassVersions) {\n  test(`detect code should be able to be parsed with ES${version}`, () => {\n    expect(() => {\n      parse(detectModernBrowserDetector, {\n        ecmaVersion: version,\n        sourceType: 'module',\n      })\n    }).not.toThrow()\n  })\n}\n\ndescribe('snippets are valid', () => {\n  const codes = {\n    safari10NoModuleFix,\n    systemJSInlineCode,\n    detectModernBrowserCode,\n    dynamicFallbackInlineCode,\n  }\n\n  for (const [name, value] of Object.entries(codes)) {\n    test(`${name} is valid JS`, () => {\n      expect(() => {\n        parse(value, {\n          ecmaVersion: 'latest',\n          sourceType: 'module',\n        })\n      }).not.toThrow()\n    })\n  }\n})\n"
  },
  {
    "path": "packages/plugin-legacy/src/index.ts",
    "content": "import path from 'node:path'\nimport crypto from 'node:crypto'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { build, normalizePath } from 'vite'\nimport MagicString from 'magic-string'\nimport type {\n  BuildOptions,\n  HtmlTagDescriptor,\n  Plugin,\n  ResolvedConfig,\n  Rollup,\n} from 'vite'\nimport type {\n  PluginItem as BabelPlugin,\n  types as BabelTypes,\n} from '@babel/core'\nimport colors from 'picocolors'\nimport browserslist from 'browserslist'\nimport type { Options } from './types'\nimport {\n  detectModernBrowserCode,\n  dynamicFallbackInlineCode,\n  legacyEntryId,\n  legacyPolyfillId,\n  modernChunkLegacyGuard,\n  safari10NoModuleFix,\n  systemJSInlineCode,\n} from './snippets'\n\n// lazy load babel since it's not used during dev\nlet babel: Promise<typeof import('@babel/core')> | undefined\nasync function loadBabel() {\n  return (babel ??= import('@babel/core'))\n}\n\n// The requested module 'browserslist' is a CommonJS module\n// which may not support all module.exports as named exports\nconst { loadConfig: browserslistLoadConfig } = browserslist\n\n// Duplicated from build.ts in Vite Core, at least while the feature is experimental\n// We should later expose this helper for other plugins to use\nfunction toOutputFilePathInHtml(\n  filename: string,\n  type: 'asset' | 'public',\n  hostId: string,\n  hostType: 'js' | 'css' | 'html',\n  config: ResolvedConfig,\n  toRelative: (filename: string, importer: string) => string,\n): string {\n  const { renderBuiltUrl } = config.experimental\n  let relative = config.base === '' || config.base === './'\n  if (renderBuiltUrl) {\n    const result = renderBuiltUrl(filename, {\n      hostId,\n      hostType,\n      type,\n      ssr: !!config.build.ssr,\n    })\n    if (typeof result === 'object') {\n      if (result.runtime) {\n        throw new Error(\n          `{ runtime: \"${result.runtime}\" } is not supported for assets in ${hostType} files: ${filename}`,\n        )\n      }\n      if (typeof result.relative === 'boolean') {\n        relative = result.relative\n      }\n    } else if (result) {\n      return result\n    }\n  }\n  if (relative && !config.build.ssr) {\n    return toRelative(filename, hostId)\n  } else {\n    return joinUrlSegments(config.decodedBase, filename)\n  }\n}\nfunction getBaseInHTML(urlRelativePath: string, config: ResolvedConfig) {\n  // Prefer explicit URL if defined for linking to assets and public files from HTML,\n  // even when base relative is specified\n  return config.base === './' || config.base === ''\n    ? path.posix.join(\n        path.posix.relative(urlRelativePath, '').slice(0, -2),\n        './',\n      )\n    : config.base\n}\nfunction joinUrlSegments(a: string, b: string): string {\n  if (!a || !b) {\n    return a || b || ''\n  }\n  if (a.endsWith('/')) {\n    a = a.substring(0, a.length - 1)\n  }\n  if (b[0] !== '/') {\n    b = '/' + b\n  }\n  return a + b\n}\n\nfunction toAssetPathFromHtml(\n  filename: string,\n  htmlPath: string,\n  config: ResolvedConfig,\n): string {\n  const relativeUrlPath = normalizePath(path.relative(config.root, htmlPath))\n  const toRelative = (filename: string, _hostId: string) =>\n    getBaseInHTML(relativeUrlPath, config) + filename\n  return toOutputFilePathInHtml(\n    filename,\n    'asset',\n    htmlPath,\n    'html',\n    config,\n    toRelative,\n  )\n}\n\nconst legacyEnvVarMarker = `__VITE_IS_LEGACY__`\nconst modernEnvVarMarker = `__VITE_IS_MODERN__`\n\nconst _require = createRequire(import.meta.url)\n\nconst nonLeadingHashInFileNameRE = /[^/]+\\[hash(?::\\d+)?\\]/\nconst prefixedHashInFileNameRE = /\\W?\\[hash(?::\\d+)?\\]/\n\n// browsers supporting dynamic import + import.meta.resolve + async generator\nconst modernTargetsEsbuild = [\n  'es2020',\n  'edge105',\n  'firefox106',\n  'chrome105',\n  'safari16.4',\n  'ios16.4',\n]\n// same with above but by browserslist syntax\n// es2020 = chrome 80+, safari 13.1+, firefox 72+, edge 80+\n// https://github.com/evanw/esbuild/issues/121#issuecomment-646956379\nconst modernTargetsBabel =\n  'edge>=105, firefox>=106, chrome>=105, safari>=16.4, chromeAndroid>=105, iOS>=16.4'\n\nconst outputOptionsForLegacyChunks =\n  new WeakSet<Rollup.NormalizedOutputOptions>()\n\nfunction viteLegacyPlugin(options: Options = {}): Plugin[] {\n  let config: ResolvedConfig\n  let targets: Options['targets']\n  const modernTargets: Options['modernTargets'] =\n    options.modernTargets || modernTargetsBabel\n\n  const genLegacy = options.renderLegacyChunks !== false\n  const genModern = options.renderModernChunks !== false\n  if (!genLegacy && !genModern) {\n    throw new Error(\n      '`renderLegacyChunks` and `renderModernChunks` cannot be both false',\n    )\n  }\n\n  const debugFlags = (process.env.DEBUG || '').split(',')\n  const isDebug =\n    debugFlags.includes('vite:*') || debugFlags.includes('vite:legacy')\n\n  const assumptions = options.assumptions || {}\n\n  const facadeToLegacyChunkMap = new Map()\n  const facadeToLegacyPolyfillMap = new Map()\n  const facadeToModernPolyfillMap = new Map()\n  const modernPolyfills = new Set<string>()\n  const legacyPolyfills = new Set<string>()\n  // When discovering polyfills in `renderChunk`, the hook may be non-deterministic, so we group the\n  // modern and legacy polyfills in a sorted chunks map for each rendered outputs before merging them.\n  const outputToChunkFileNameToPolyfills = new WeakMap<\n    Rollup.NormalizedOutputOptions,\n    Map<string, { modern: Set<string>; legacy: Set<string> }> | null\n  >()\n\n  if (Array.isArray(options.modernPolyfills) && genModern) {\n    options.modernPolyfills.forEach((i) => {\n      modernPolyfills.add(\n        i.includes('/') ? `core-js/${i}` : `core-js/modules/${i}.js`,\n      )\n    })\n  }\n  if (Array.isArray(options.additionalModernPolyfills)) {\n    options.additionalModernPolyfills.forEach((i) => {\n      modernPolyfills.add(i)\n    })\n  }\n  if (Array.isArray(options.polyfills)) {\n    options.polyfills.forEach((i) => {\n      if (i.startsWith(`regenerator`)) {\n        legacyPolyfills.add(`regenerator-runtime/runtime.js`)\n      } else {\n        legacyPolyfills.add(\n          i.includes('/') ? `core-js/${i}` : `core-js/modules/${i}.js`,\n        )\n      }\n    })\n  }\n  if (Array.isArray(options.additionalLegacyPolyfills)) {\n    options.additionalLegacyPolyfills.forEach((i) => {\n      legacyPolyfills.add(i)\n    })\n  }\n\n  let overriddenBuildTarget = false\n  let overriddenBuildTargetOnlyModern = false\n  let overriddenDefaultModernTargets = false\n  const legacyConfigPlugin: Plugin = {\n    name: 'vite:legacy-config',\n\n    async config(config, env) {\n      if (env.command === 'build' && !config.build?.ssr) {\n        if (!config.build) {\n          config.build = {}\n        }\n\n        if (genLegacy && !config.build.cssTarget) {\n          // Hint for esbuild that we are targeting legacy browsers when minifying CSS.\n          // Full CSS compat table available at https://github.com/evanw/esbuild/blob/78e04680228cf989bdd7d471e02bbc2c8d345dc9/internal/compat/css_table.go\n          // But note that only the `HexRGBA` feature affects the minify outcome.\n          // HSL & rebeccapurple values will be minified away regardless the target.\n          // So targeting `chrome61` suffices to fix the compatibility issue.\n          config.build.cssTarget = 'chrome61'\n        }\n\n        if (genLegacy) {\n          // Vite's default target browsers are **not** the same.\n          // See https://github.com/vitejs/vite/pull/10052#issuecomment-1242076461\n          overriddenBuildTarget = config.build.target !== undefined\n          overriddenDefaultModernTargets = options.modernTargets !== undefined\n        } else {\n          overriddenBuildTargetOnlyModern = config.build.target !== undefined\n        }\n\n        if (options.modernTargets) {\n          // Package is ESM only\n          const { default: browserslistToEsbuild } =\n            await import('browserslist-to-esbuild')\n          config.build.target = browserslistToEsbuild(options.modernTargets)\n        } else {\n          config.build.target = modernTargetsEsbuild\n        }\n      }\n\n      return {\n        define: {\n          'import.meta.env.LEGACY':\n            env.command === 'serve' || config.build?.ssr\n              ? false\n              : legacyEnvVarMarker,\n        },\n      }\n    },\n    configResolved(config) {\n      if (overriddenBuildTarget) {\n        config.logger.warn(\n          colors.yellow(\n            `plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers to support instead.`,\n          ),\n        )\n      }\n      if (overriddenBuildTargetOnlyModern) {\n        config.logger.warn(\n          colors.yellow(\n            `plugin-legacy overrode 'build.target'. You should pass 'modernTargets' as an option to this plugin with the list of browsers to support instead.`,\n          ),\n        )\n      }\n      if (overriddenDefaultModernTargets) {\n        config.logger.warn(\n          colors.yellow(\n            `plugin-legacy 'modernTargets' option overrode the builtin targets of modern chunks. Some versions of browsers between legacy and modern may not be supported.`,\n          ),\n        )\n      }\n      if (config.isWorker) {\n        config.logger.warn(\n          colors.yellow(\n            `plugin-legacy should not be passed to 'worker.plugins'. Pass to 'plugins' instead. Note that generating legacy chunks for workers are not supported by plugin-legacy.`,\n          ),\n        )\n      }\n    },\n  }\n\n  const legacyGenerateBundlePlugin: Plugin = {\n    name: 'vite:legacy-generate-polyfill-chunk',\n    apply: 'build',\n\n    async generateBundle(opts, bundle) {\n      if (config.build.ssr) {\n        return\n      }\n\n      const chunkFileNameToPolyfills =\n        outputToChunkFileNameToPolyfills.get(opts)\n      if (chunkFileNameToPolyfills == null) {\n        throw new Error(\n          'Internal @vitejs/plugin-legacy error: discovered polyfills should exist',\n        )\n      }\n\n      if (!isLegacyBundle(bundle)) {\n        // Merge discovered modern polyfills to `modernPolyfills`\n        for (const { modern } of chunkFileNameToPolyfills.values()) {\n          modern.forEach((p) => modernPolyfills.add(p))\n        }\n        if (!modernPolyfills.size) {\n          return\n        }\n        if (isDebug) {\n          console.log(\n            `[@vitejs/plugin-legacy] modern polyfills:`,\n            modernPolyfills,\n          )\n        }\n        await buildPolyfillChunk(\n          this,\n          config.mode,\n          modernPolyfills,\n          bundle,\n          facadeToModernPolyfillMap,\n          config.build,\n          'es',\n          opts,\n          true,\n          genLegacy,\n        )\n        return\n      }\n\n      if (!genLegacy) {\n        return\n      }\n\n      // Merge discovered legacy polyfills to `legacyPolyfills`\n      for (const { legacy } of chunkFileNameToPolyfills.values()) {\n        legacy.forEach((p) => legacyPolyfills.add(p))\n      }\n\n      // legacy bundle\n      if (options.polyfills !== false) {\n        // check if the target needs Promise polyfill because SystemJS relies on it\n        // https://github.com/systemjs/systemjs#ie11-support\n        await detectPolyfills(\n          `Promise.resolve(); Promise.all();`,\n          targets,\n          assumptions,\n          legacyPolyfills,\n        )\n      }\n\n      if (legacyPolyfills.size || !options.externalSystemJS) {\n        if (isDebug) {\n          console.log(\n            `[@vitejs/plugin-legacy] legacy polyfills:`,\n            legacyPolyfills,\n          )\n        }\n\n        await buildPolyfillChunk(\n          this,\n          config.mode,\n          legacyPolyfills,\n          bundle,\n          facadeToLegacyPolyfillMap,\n          // force using terser for legacy polyfill minification, since esbuild\n          // isn't legacy-safe\n          config.build,\n          'iife',\n          opts,\n          options.externalSystemJS,\n        )\n      }\n    },\n  }\n\n  const legacyPostPlugin: Plugin = {\n    name: 'vite:legacy-post-process',\n    enforce: 'post',\n    apply: 'build',\n\n    renderStart(opts) {\n      // Empty the nested map for this output\n      outputToChunkFileNameToPolyfills.set(opts, null)\n    },\n\n    configResolved(_config) {\n      if (_config.build.lib) {\n        throw new Error('@vitejs/plugin-legacy does not support library mode.')\n      }\n      config = _config\n\n      if (isDebug) {\n        console.log(`[@vitejs/plugin-legacy] modernTargets:`, modernTargets)\n      }\n\n      if (!genLegacy || config.build.ssr) {\n        return\n      }\n\n      targets =\n        options.targets ||\n        browserslistLoadConfig({ path: config.root }) ||\n        'last 2 versions and not dead, > 0.3%, Firefox ESR'\n      if (isDebug) {\n        console.log(`[@vitejs/plugin-legacy] targets:`, targets)\n      }\n\n      const getLegacyOutputFileName = (\n        fileNames:\n          | string\n          | ((chunkInfo: Rollup.PreRenderedChunk) => string)\n          | undefined,\n        defaultFileName = '[name]-legacy-[hash].js',\n      ): string | ((chunkInfo: Rollup.PreRenderedChunk) => string) => {\n        if (!fileNames) {\n          return path.posix.join(config.build.assetsDir, defaultFileName)\n        }\n\n        return (chunkInfo) => {\n          let fileName =\n            typeof fileNames === 'function' ? fileNames(chunkInfo) : fileNames\n\n          if (fileName.includes('[name]')) {\n            // [name]-[hash].[format] -> [name]-legacy-[hash].[format]\n            fileName = fileName.replace('[name]', '[name]-legacy')\n          } else if (nonLeadingHashInFileNameRE.test(fileName)) {\n            // custom[hash].[format] -> [name]-legacy[hash].[format]\n            // custom-[hash].[format] -> [name]-legacy-[hash].[format]\n            // custom.[hash].[format] -> [name]-legacy.[hash].[format]\n            // custom.[hash:10].[format] -> custom-legacy.[hash:10].[format]\n            fileName = fileName.replace(prefixedHashInFileNameRE, '-legacy$&')\n          } else {\n            // entry.js -> entry-legacy.js\n            // entry.min.js -> entry-legacy.min.js\n            fileName = fileName.replace(/(.+?)\\.(.+)/, '$1-legacy.$2')\n          }\n\n          return fileName\n        }\n      }\n\n      const createLegacyOutput = (\n        options: Rollup.OutputOptions = {},\n      ): Rollup.OutputOptions => {\n        return {\n          ...options,\n          format: 'esm',\n          entryFileNames: getLegacyOutputFileName(options.entryFileNames),\n          chunkFileNames: getLegacyOutputFileName(options.chunkFileNames),\n          minify: false, // minify with terser instead\n        }\n      }\n\n      const { rollupOptions } = config.build\n      const { output } = rollupOptions\n      if (Array.isArray(output)) {\n        rollupOptions.output = [\n          ...output.map(createLegacyOutput),\n          ...(genModern ? output : []),\n        ]\n      } else {\n        rollupOptions.output = [\n          createLegacyOutput(output),\n          ...(genModern ? [output || {}] : []),\n        ]\n      }\n\n      // @ts-expect-error is readonly but should be injected here\n      _config.isOutputOptionsForLegacyChunks = (\n        opts: Rollup.NormalizedOutputOptions,\n      ): boolean => outputOptionsForLegacyChunks.has(opts)\n    },\n\n    async renderChunk(raw, chunk, opts, { chunks }) {\n      if (config.build.ssr) {\n        return null\n      }\n\n      // On first run, initialize the map with sorted chunk file names\n      let chunkFileNameToPolyfills = outputToChunkFileNameToPolyfills.get(opts)\n      if (chunkFileNameToPolyfills == null) {\n        chunkFileNameToPolyfills = new Map()\n        for (const fileName in chunks) {\n          chunkFileNameToPolyfills.set(fileName, {\n            modern: new Set(),\n            legacy: new Set(),\n          })\n        }\n        outputToChunkFileNameToPolyfills.set(opts, chunkFileNameToPolyfills)\n      }\n      const polyfillsDiscovered = chunkFileNameToPolyfills.get(chunk.fileName)\n      if (polyfillsDiscovered == null) {\n        throw new Error(\n          `Internal @vitejs/plugin-legacy error: discovered polyfills for ${chunk.fileName} should exist`,\n        )\n      }\n\n      if (!isLegacyChunk(chunk)) {\n        if (\n          options.modernPolyfills &&\n          !Array.isArray(options.modernPolyfills) &&\n          genModern\n        ) {\n          // analyze and record modern polyfills\n          await detectPolyfills(\n            raw,\n            modernTargets,\n            assumptions,\n            polyfillsDiscovered.modern,\n          )\n        }\n\n        const ms = new MagicString(raw)\n\n        if (genLegacy && chunk.isEntry) {\n          // append this code to avoid modern chunks running on legacy targeted browsers\n          ms.prepend(modernChunkLegacyGuard)\n        }\n\n        if (raw.includes(legacyEnvVarMarker)) {\n          const re = new RegExp(legacyEnvVarMarker, 'g')\n          let match\n          while ((match = re.exec(raw))) {\n            ms.overwrite(\n              match.index,\n              match.index + legacyEnvVarMarker.length,\n              `false`,\n            )\n          }\n        }\n\n        if (config.build.sourcemap) {\n          return {\n            code: ms.toString(),\n            map: ms.generateMap({ hires: 'boundary' }),\n          }\n        }\n        return {\n          code: ms.toString(),\n        }\n      }\n\n      if (!genLegacy) {\n        return null\n      }\n\n      outputOptionsForLegacyChunks.add(opts)\n\n      // avoid emitting assets for legacy bundle\n      const needPolyfills =\n        options.polyfills !== false && !Array.isArray(options.polyfills)\n\n      // transform the legacy chunk with @babel/preset-env\n      const sourceMaps = !!config.build.sourcemap\n      const babel = await loadBabel()\n\n      // need to transform into systemjs separately from other plugins\n      // for preset-env polyfill detection and removal\n      const resultSystem = babel.transform(raw, {\n        babelrc: false,\n        configFile: false,\n        ast: true,\n        code: false,\n        sourceMaps,\n        plugins: [\n          // @ts-expect-error -- not typed\n          (await import('@babel/plugin-transform-dynamic-import')).default,\n          // @ts-expect-error -- not typed\n          (await import('@babel/plugin-transform-modules-systemjs')).default,\n        ],\n      })\n\n      const babelTransformOptions: babel.TransformOptions = {\n        babelrc: false,\n        configFile: false,\n        cloneInputAst: false,\n        compact: !!config.build.minify,\n        sourceMaps,\n        inputSourceMap: undefined,\n        targets,\n        assumptions,\n        browserslistConfigFile: false,\n        presets: [\n          // forcing our plugin to run before preset-env by wrapping it in a\n          // preset so we can catch the injected import statements...\n          [\n            () => ({\n              plugins: [\n                recordAndRemovePolyfillBabelPlugin(polyfillsDiscovered.legacy),\n                replaceLegacyEnvBabelPlugin(),\n                replaceModernEnvBabelPlugin(),\n                wrapIIFEBabelPlugin(),\n              ],\n            }),\n          ],\n          [\n            (await import('@babel/preset-env')).default,\n            {\n              bugfixes: true,\n              modules: false,\n              useBuiltIns: needPolyfills ? 'usage' : false,\n              corejs: needPolyfills\n                ? {\n                    version: _require('core-js/package.json').version,\n                    proposals: false,\n                  }\n                : undefined,\n              shippedProposals: true,\n            },\n          ],\n        ],\n      }\n      let result: babel.BabelFileResult | null\n      if (resultSystem) {\n        result = babel.transformFromAstSync(\n          resultSystem.ast!,\n          undefined,\n          babelTransformOptions,\n        )\n      } else {\n        result = babel.transform(raw, babelTransformOptions)\n      }\n      if (result) return { code: result.code!, map: result.map }\n      return null\n    },\n\n    transformIndexHtml(html, { chunk }) {\n      if (config.build.ssr) return\n      if (!chunk) return\n      if (chunk.fileName.includes('-legacy')) {\n        // The legacy bundle is built first, and its index.html isn't actually emitted if\n        // modern bundle will be generated. Here we simply record its corresponding legacy chunk.\n        facadeToLegacyChunkMap.set(chunk.facadeModuleId, chunk.fileName)\n        if (genModern) {\n          return\n        }\n      }\n      if (!genModern) {\n        html = html.replace(/<script type=\"module\".*?<\\/script>/g, '')\n      }\n\n      const tags: HtmlTagDescriptor[] = []\n      const htmlFilename = chunk.facadeModuleId?.replace(/\\?.*$/, '')\n\n      // 1. inject modern polyfills\n      if (genModern) {\n        const modernPolyfillFilename = facadeToModernPolyfillMap.get(\n          chunk.facadeModuleId,\n        )\n\n        if (modernPolyfillFilename) {\n          tags.push({\n            tag: 'script',\n            attrs: {\n              type: 'module',\n              crossorigin: true,\n              src: toAssetPathFromHtml(\n                modernPolyfillFilename,\n                chunk.facadeModuleId!,\n                config,\n              ),\n            },\n          })\n        } else if (modernPolyfills.size) {\n          throw new Error(\n            `No corresponding modern polyfill chunk found for ${htmlFilename}`,\n          )\n        }\n      }\n\n      if (!genLegacy) {\n        return { html, tags }\n      }\n\n      // 2. inject Safari 10 nomodule fix\n      if (genModern) {\n        tags.push({\n          tag: 'script',\n          attrs: { nomodule: genModern },\n          children: safari10NoModuleFix,\n          injectTo: 'body',\n        })\n      }\n\n      // 3. inject legacy polyfills\n      const legacyPolyfillFilename = facadeToLegacyPolyfillMap.get(\n        chunk.facadeModuleId,\n      )\n      if (legacyPolyfillFilename) {\n        tags.push({\n          tag: 'script',\n          attrs: {\n            nomodule: genModern,\n            crossorigin: true,\n            id: legacyPolyfillId,\n            src: toAssetPathFromHtml(\n              legacyPolyfillFilename,\n              chunk.facadeModuleId!,\n              config,\n            ),\n          },\n          injectTo: 'body',\n        })\n      } else if (legacyPolyfills.size) {\n        throw new Error(\n          `No corresponding legacy polyfill chunk found for ${htmlFilename}`,\n        )\n      }\n\n      // 4. inject legacy entry\n      const legacyEntryFilename = facadeToLegacyChunkMap.get(\n        chunk.facadeModuleId,\n      )\n      if (legacyEntryFilename) {\n        // `assets/foo.js` means importing \"named register\" in SystemJS\n        tags.push({\n          tag: 'script',\n          attrs: {\n            nomodule: genModern,\n            crossorigin: true,\n            // we set the entry path on the element as an attribute so that the\n            // script content will stay consistent - which allows using a constant\n            // hash value for CSP.\n            id: legacyEntryId,\n            'data-src': toAssetPathFromHtml(\n              legacyEntryFilename,\n              chunk.facadeModuleId!,\n              config,\n            ),\n          },\n          children: systemJSInlineCode,\n          injectTo: 'body',\n        })\n      } else {\n        throw new Error(\n          `No corresponding legacy entry chunk found for ${htmlFilename}`,\n        )\n      }\n\n      // 5. inject dynamic import fallback entry\n      if (legacyPolyfillFilename && legacyEntryFilename && genModern) {\n        tags.push({\n          tag: 'script',\n          attrs: { type: 'module' },\n          children: detectModernBrowserCode,\n          injectTo: 'head',\n        })\n        tags.push({\n          tag: 'script',\n          attrs: { type: 'module' },\n          children: dynamicFallbackInlineCode,\n          injectTo: 'head',\n        })\n      }\n\n      return {\n        html,\n        tags,\n      }\n    },\n\n    generateBundle(_opts, bundle) {\n      if (config.build.ssr) {\n        return\n      }\n\n      if (isLegacyBundle(bundle) && genModern) {\n        // avoid emitting duplicate assets\n        for (const name in bundle) {\n          if (\n            bundle[name].type === 'asset' &&\n            !name.endsWith('.map') &&\n            !name.includes('-legacy') // legacy chunks\n          ) {\n            delete bundle[name]\n          }\n        }\n      }\n    },\n  }\n\n  return [legacyConfigPlugin, legacyGenerateBundlePlugin, legacyPostPlugin]\n}\n\nexport async function detectPolyfills(\n  code: string,\n  targets: any,\n  assumptions: Record<string, boolean>,\n  list: Set<string>,\n): Promise<void> {\n  const babel = await loadBabel()\n  const result = babel.transform(code, {\n    ast: true,\n    code: false,\n    babelrc: false,\n    configFile: false,\n    compact: false,\n    targets,\n    assumptions,\n    browserslistConfigFile: false,\n    plugins: [\n      [\n        (await import('babel-plugin-polyfill-corejs3')).default,\n        {\n          method: 'usage-global',\n          version: _require('core-js/package.json').version,\n          shippedProposals: true,\n        },\n      ],\n      [\n        (await import('babel-plugin-polyfill-regenerator')).default,\n        {\n          method: 'usage-global',\n        },\n      ],\n    ],\n  })\n  for (const node of result!.ast!.program.body) {\n    if (node.type === 'ImportDeclaration') {\n      const source = node.source.value\n      if (\n        source.startsWith('core-js/') ||\n        source.startsWith('regenerator-runtime/')\n      ) {\n        list.add(source)\n      }\n    }\n  }\n}\n\nasync function buildPolyfillChunk(\n  ctx: Rollup.PluginContext,\n  mode: string,\n  imports: Set<string>,\n  bundle: Rollup.OutputBundle,\n  facadeToChunkMap: Map<string, string>,\n  buildOptions: BuildOptions,\n  format: 'iife' | 'es',\n  rollupOutputOptions: Rollup.NormalizedOutputOptions,\n  excludeSystemJS?: boolean,\n  prependModenChunkLegacyGuard?: boolean,\n) {\n  let { minify, assetsDir, sourcemap } = buildOptions\n  minify = minify ? 'terser' : false\n  const res = await build({\n    mode,\n    // so that everything is resolved from here\n    root: path.dirname(fileURLToPath(import.meta.url)),\n    configFile: false,\n    logLevel: 'error',\n    plugins: [\n      polyfillsPlugin(imports, excludeSystemJS),\n      prependModenChunkLegacyGuard && prependModenChunkLegacyGuardPlugin(),\n    ],\n    build: {\n      write: false,\n      minify,\n      assetsDir,\n      sourcemap,\n      rollupOptions: {\n        input: {\n          polyfills: polyfillId,\n        },\n        output: {\n          format,\n          hashCharacters: rollupOutputOptions.hashCharacters,\n          entryFileNames: rollupOutputOptions.entryFileNames,\n          sourcemapBaseUrl: rollupOutputOptions.sourcemapBaseUrl,\n        },\n      },\n    },\n    // Don't run esbuild for transpilation or minification\n    // because we don't want to transpile code.\n    esbuild: false,\n    optimizeDeps: {\n      esbuildOptions: {\n        // If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.\n        // This limits the input code not to include es2015+ codes.\n        // But core-js is the only dependency which includes commonjs code\n        // and core-js doesn't include es2015+ codes.\n        target: 'es5',\n      },\n    },\n  })\n  const _polyfillChunk = Array.isArray(res) ? res[0] : res\n  if (!('output' in _polyfillChunk)) return\n  const polyfillChunk = _polyfillChunk.output.find(\n    (chunk) => chunk.type === 'chunk' && chunk.isEntry,\n  ) as Rollup.OutputChunk\n\n  // associate the polyfill chunk to every entry chunk so that we can retrieve\n  // the polyfill filename in index html transform\n  for (const key in bundle) {\n    const chunk = bundle[key]\n    if (chunk.type === 'chunk' && chunk.facadeModuleId) {\n      facadeToChunkMap.set(chunk.facadeModuleId, polyfillChunk.fileName)\n    }\n  }\n\n  // add the chunk to the bundle\n  ctx.emitFile({\n    type: 'prebuilt-chunk',\n    name: polyfillChunk.name,\n    fileName: polyfillChunk.fileName,\n    code: polyfillChunk.code,\n    facadeModuleId: polyfillChunk.facadeModuleId ?? undefined,\n    isEntry: polyfillChunk.isEntry,\n    isDynamicEntry: polyfillChunk.isDynamicEntry,\n    exports: [],\n    map: polyfillChunk.map ?? undefined,\n    sourcemapFileName: polyfillChunk.sourcemapFileName ?? undefined,\n  })\n  if (polyfillChunk.sourcemapFileName) {\n    const polyfillChunkMapAsset = _polyfillChunk.output.find(\n      (chunk) =>\n        chunk.type === 'asset' &&\n        chunk.fileName === polyfillChunk.sourcemapFileName,\n    ) as Rollup.OutputAsset | undefined\n    if (polyfillChunkMapAsset) {\n      ctx.emitFile({\n        type: 'asset',\n        fileName: polyfillChunkMapAsset.fileName,\n        source: polyfillChunkMapAsset.source,\n      })\n    }\n  }\n}\n\nconst polyfillId = '\\0vite/legacy-polyfills'\n\nfunction polyfillsPlugin(\n  imports: Set<string>,\n  excludeSystemJS?: boolean,\n): Plugin {\n  return {\n    name: 'vite:legacy-polyfills',\n    resolveId(id) {\n      if (id === polyfillId) {\n        return id\n      }\n    },\n    load(id) {\n      if (id === polyfillId) {\n        return (\n          [...imports].map((i) => `import ${JSON.stringify(i)};`).join('') +\n          (excludeSystemJS ? '' : `import \"systemjs/dist/s.min.js\";`)\n        )\n      }\n    },\n  }\n}\n\nfunction prependModenChunkLegacyGuardPlugin(): Plugin {\n  let sourceMapEnabled!: boolean\n  return {\n    name: 'vite:legacy-prepend-moden-chunk-legacy-guard',\n    configResolved(config) {\n      sourceMapEnabled = !!config.build.sourcemap\n    },\n    renderChunk(code) {\n      if (!sourceMapEnabled) {\n        return modernChunkLegacyGuard + code\n      }\n\n      const ms = new MagicString(code)\n      ms.prepend(modernChunkLegacyGuard)\n      return {\n        code: ms.toString(),\n        map: ms.generateMap({ hires: 'boundary' }),\n      }\n    },\n  }\n}\n\nfunction isLegacyChunk(chunk: Rollup.RenderedChunk) {\n  return chunk.fileName.includes('-legacy')\n}\n\nfunction isLegacyBundle(bundle: Rollup.OutputBundle) {\n  const entryChunk = Object.values(bundle).find(\n    (output) => output.type === 'chunk' && output.isEntry,\n  )\n\n  return !!entryChunk && entryChunk.fileName.includes('-legacy')\n}\n\nfunction recordAndRemovePolyfillBabelPlugin(\n  polyfills: Set<string>,\n): BabelPlugin {\n  return ({ types: t }: { types: typeof BabelTypes }): BabelPlugin => ({\n    name: 'vite-remove-polyfill-import',\n    post({ path }) {\n      path.get('body').forEach((p) => {\n        if (t.isImportDeclaration(p.node)) {\n          polyfills.add(p.node.source.value)\n          p.remove()\n        }\n      })\n    },\n  })\n}\n\nfunction replaceLegacyEnvBabelPlugin(): BabelPlugin {\n  return ({ types: t }): BabelPlugin => ({\n    name: 'vite-replace-env-legacy',\n    visitor: {\n      Identifier(path) {\n        if (path.node.name === legacyEnvVarMarker) {\n          path.replaceWith(t.booleanLiteral(true))\n        }\n      },\n    },\n  })\n}\n\nfunction replaceModernEnvBabelPlugin(): BabelPlugin {\n  return ({ types: t }): BabelPlugin => ({\n    name: 'vite-replace-env-modern',\n    visitor: {\n      Identifier(path) {\n        if (path.node.name === modernEnvVarMarker) {\n          path.replaceWith(t.booleanLiteral(false))\n        }\n      },\n    },\n  })\n}\n\nfunction wrapIIFEBabelPlugin(): BabelPlugin {\n  return ({ types: t, template }): BabelPlugin => {\n    const buildIIFE = template(';(function(){%%body%%})();')\n\n    return {\n      name: 'vite-wrap-iife',\n      post({ path }) {\n        if (!this.isWrapped) {\n          this.isWrapped = true\n          path.replaceWith(t.program(buildIIFE({ body: path.node.body })))\n        }\n      },\n    }\n  }\n}\n\nexport const cspHashes: string[] = [\n  safari10NoModuleFix,\n  systemJSInlineCode,\n  detectModernBrowserCode,\n  dynamicFallbackInlineCode,\n].map((i) => crypto.hash('sha256', i, 'base64'))\n\nexport type { Options }\n\nexport default viteLegacyPlugin\n\n// Compat for require\nfunction viteLegacyPluginCjs(this: unknown, options: Options): Plugin[] {\n  return viteLegacyPlugin.call(this, options)\n}\nObject.assign(viteLegacyPluginCjs, {\n  cspHashes,\n  default: viteLegacyPluginCjs,\n  detectPolyfills,\n})\n\nexport { viteLegacyPluginCjs as 'module.exports' }\n"
  },
  {
    "path": "packages/plugin-legacy/src/shims.d.ts",
    "content": "declare module 'babel-plugin-polyfill-corejs3'\n\ndeclare module 'babel-plugin-polyfill-regenerator'\n"
  },
  {
    "path": "packages/plugin-legacy/src/snippets.ts",
    "content": "// https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc\n// DO NOT ALTER THIS CONTENT\nexport const safari10NoModuleFix: string = `!function(){var e=document,t=e.createElement(\"script\");if(!(\"noModule\"in t)&&\"onbeforeload\"in t){var n=!1;e.addEventListener(\"beforeload\",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute(\"nomodule\")||!n)return;e.preventDefault()}),!0),t.type=\"module\",t.src=\".\",e.head.appendChild(t),t.remove()}}();`\n\nexport const legacyPolyfillId: string = 'vite-legacy-polyfill'\nexport const legacyEntryId: string = 'vite-legacy-entry'\nexport const systemJSInlineCode: string = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`\n\nconst detectModernBrowserVarName = '__vite_is_modern_browser'\n// inline module to execute the code before other imports\nconst detectImportMetaResolveSupportModule: string =\n  'data:text/javascript,if(!import.meta.resolve)throw Error(\"import.meta.resolve not supported\")'\nexport const detectModernBrowserDetector: string = `import.meta.url;import(\"_\").catch(()=>1);(async function*(){})().next()`\nexport const detectModernBrowserCode: string = `import'${detectImportMetaResolveSupportModule}';${detectModernBrowserDetector};window.${detectModernBrowserVarName}=true`\nexport const dynamicFallbackInlineCode: string = `!function(){if(window.${detectModernBrowserVarName})return;console.warn(\"vite: loading legacy chunks, syntax error above and the same error below should be ignored\");var e=document.getElementById(\"${legacyPolyfillId}\"),n=document.createElement(\"script\");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`\n\nexport const modernChunkLegacyGuard: string = `import'${detectImportMetaResolveSupportModule}';export function __vite_legacy_guard(){${detectModernBrowserDetector}};`\n"
  },
  {
    "path": "packages/plugin-legacy/src/types.ts",
    "content": "export interface Options {\n  /**\n   * default: 'defaults'\n   */\n  targets?: string | string[] | Record<string, string>\n  /**\n   * default: 'edge>=79, firefox>=67, chrome>=64, safari>=12, chromeAndroid>=64, iOS>=12'\n   */\n  modernTargets?: string | string[]\n  /**\n   * default: true\n   */\n  polyfills?: boolean | string[]\n  additionalLegacyPolyfills?: string[]\n  additionalModernPolyfills?: string[]\n  /**\n   * default: false\n   */\n  modernPolyfills?: boolean | string[]\n  /**\n   * default: true\n   */\n  renderLegacyChunks?: boolean\n  /**\n   * default: false\n   */\n  externalSystemJS?: boolean\n  /**\n   * default: true\n   */\n  renderModernChunks?: boolean\n  /**\n   * @see https://babeljs.io/docs/assumptions\n   *\n   * default: {}\n   */\n  assumptions?: Record<string, boolean>\n}\n"
  },
  {
    "path": "packages/plugin-legacy/tsconfig.json",
    "content": "{\n  \"include\": [\"src\"],\n  \"exclude\": [\"**/*.spec.ts\"],\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"target\": \"ES2023\",\n    \"module\": \"Preserve\",\n    \"moduleResolution\": \"bundler\",\n    \"isolatedDeclarations\": true,\n    \"declaration\": true,\n    \"strict\": true,\n    \"sourceMap\": true,\n    \"noUnusedLocals\": true,\n    \"esModuleInterop\": true,\n    \"paths\": {\n      \"vite\": [\"../vite/src/node/index.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/plugin-legacy/tsdown.config.ts",
    "content": "import { defineConfig } from 'tsdown'\n\nexport default defineConfig({\n  entry: ['src/index.ts'],\n  target: 'node20',\n  inlineOnly: ['picocolors'],\n  tsconfig: false, // disable tsconfig `paths` when bundling\n  dts: true,\n  fixedExtension: false,\n})\n"
  },
  {
    "path": "packages/vite/CHANGELOG.md",
    "content": "## <small>[8.0.1](https://github.com/vitejs/vite/compare/v8.0.0...v8.0.1) (2026-03-19)</small>\n### Features\n\n* update rolldown to 1.0.0-rc.10 ([#21932](https://github.com/vitejs/vite/issues/21932)) ([b3c067d](https://github.com/vitejs/vite/commit/b3c067d71a781ca72899d08d095c9acd119361ee))\n\n### Bug Fixes\n\n* **bundled-dev:** properly disable `inlineConst` optimization ([#21865](https://github.com/vitejs/vite/issues/21865)) ([6d97142](https://github.com/vitejs/vite/commit/6d97142abc4805ad53cc732826bb502d6d5dd6ce))\n* **css:** lightningcss minify failed when `build.target: 'es6'` ([#21933](https://github.com/vitejs/vite/issues/21933)) ([5fcce46](https://github.com/vitejs/vite/commit/5fcce46a609bc3e3c600810918626b5fc8f16448))\n* **deps:** update all non-major dependencies ([#21878](https://github.com/vitejs/vite/issues/21878)) ([6dbbd7f](https://github.com/vitejs/vite/commit/6dbbd7f072b1e13abd96489b0016b3d93d937999))\n* **dev:** always use ESM Oxc runtime ([#21829](https://github.com/vitejs/vite/issues/21829)) ([d323ed7](https://github.com/vitejs/vite/commit/d323ed7a824c232597c2b4ef2a4f3494e5231c3d))\n* **dev:** handle concurrent restarts in `_createServer` ([#21810](https://github.com/vitejs/vite/issues/21810)) ([40bc729](https://github.com/vitejs/vite/commit/40bc7293ef574103171f72cc8618f9ef22cc5fa0))\n* handle `+` symbol in package subpath exports during dep optimization ([#21886](https://github.com/vitejs/vite/issues/21886)) ([86db93d](https://github.com/vitejs/vite/commit/86db93d8b1d511e9a56a4ea576741a5350eac99f))\n* improve `no-cors` request block error ([#21902](https://github.com/vitejs/vite/issues/21902)) ([5ba688b](https://github.com/vitejs/vite/commit/5ba688bc422c54944bc6fc563bfe1ba2616a0911))\n* use precise regexes for transform filter to avoid backtracking ([#21800](https://github.com/vitejs/vite/issues/21800)) ([dbe41bd](https://github.com/vitejs/vite/commit/dbe41bddb9db3563c21ae9ce0ebc310e8b8878c9))\n* **worker:** `require(json)` result should not be wrapped ([#21847](https://github.com/vitejs/vite/issues/21847)) ([0672fd2](https://github.com/vitejs/vite/commit/0672fd20aac00e4f78fe8fe886978a9b64f63ba7))\n* **worker:** make worker output consistent with client and SSR ([#21871](https://github.com/vitejs/vite/issues/21871)) ([69454d7](https://github.com/vitejs/vite/commit/69454d7136f18334e9a58862741ec14a5edf6f98))\n\n### Miscellaneous Chores\n\n* add changelog rearrange script ([#21835](https://github.com/vitejs/vite/issues/21835)) ([efef073](https://github.com/vitejs/vite/commit/efef073a6f71be0330bd72784654ed8b8dd60cbf))\n* **deps:** bump required `@vitejs/devtools` version to 0.1+ ([#21925](https://github.com/vitejs/vite/issues/21925)) ([12932f5](https://github.com/vitejs/vite/commit/12932f5a5a36b7b3f55ce5e3b867a08154ba1547))\n* **deps:** update rolldown-related dependencies ([#21787](https://github.com/vitejs/vite/issues/21787)) ([1af1d3a](https://github.com/vitejs/vite/commit/1af1d3a3a4fd62fa581392b2dec9052efe8485b3))\n* rearrange 8.0 changelog ([8e05b61](https://github.com/vitejs/vite/commit/8e05b61d3f2271adb16713835b943e5e13d20499))\n* rearrange 8.0 changelog ([#21834](https://github.com/vitejs/vite/issues/21834)) ([86edeee](https://github.com/vitejs/vite/commit/86edeee31eeacdbfb93c112df088fbd606f9917e))\n\n## [8.0.0](https://github.com/vitejs/vite/compare/v8.0.0-beta.18...v8.0.0) (2026-03-12)\n\n![Vite 8 is here!](../../docs/public/og-image-announcing-vite8.webp)\n\nToday, we're thrilled to announce the release of the next Vite major:\n\n- **[Vite 8.0 announcement blog post](https://vite.dev/blog/announcing-vite8.html)**\n- [Docs](https://vite.dev/) (translations: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/), [فارسی](https://fa.vite.dev/))\n- [Migration Guide](https://vite.dev/guide/migration.html)\n\n### ⚠ BREAKING CHANGES\n\n- remove `import.meta.hot.accept` resolution fallback (#21382)\n- update default browser target (#21193)\n- the epic `rolldown-vite` merge (#21189)\n\n### Features\n\n- update rolldown to 1.0.0-rc.9 ([#21813](https://github.com/vitejs/vite/issues/21813)) ([f05be0e](https://github.com/vitejs/vite/commit/f05be0eabf5c045b8892d463081da3c8fbf5a5ae))\n- warn when `vite-tsconfig-paths` plugin is detected ([#21781](https://github.com/vitejs/vite/issues/21781)) ([ada493e](https://github.com/vitejs/vite/commit/ada493e4214ef2028b96583550443a386be2e2ae))\n- **css:** support es2025 build target for lightningcss ([#21769](https://github.com/vitejs/vite/issues/21769)) ([08906e7](https://github.com/vitejs/vite/commit/08906e76f2fc0e55c8aea6243f6203ce0c78f106))\n- forward browser console logs and errors to dev server terminal ([#20916](https://github.com/vitejs/vite/issues/20916)) ([2540ed0](https://github.com/vitejs/vite/commit/2540ed06d0b6f93829d2d764b6a02f7dbfd14923))\n- update rolldown to 1.0.0-rc.8 ([#21790](https://github.com/vitejs/vite/issues/21790)) ([a0c950e](https://github.com/vitejs/vite/commit/a0c950e30945cc97fb2381a2affac086730fa31e))\n- export `Visitor` and `ESTree` from `rolldown/utils` ([#21664](https://github.com/vitejs/vite/issues/21664)) ([45de31e](https://github.com/vitejs/vite/commit/45de31e5ffcc514832aec96fa6e09a189c26d684))\n- update rolldown to 1.0.0-rc.6 ([#21714](https://github.com/vitejs/vite/issues/21714)) ([37a65f8](https://github.com/vitejs/vite/commit/37a65f8c31b5baeb4dadecfd4da98f81bae4202e))\n- use util.inspect for CLI error display ([#21668](https://github.com/vitejs/vite/issues/21668)) ([5f425a9](https://github.com/vitejs/vite/commit/5f425a9126ad1a483f482970bef8c29a0e721a3c))\n- update rolldown to 1.0.0-rc.5 ([#21660](https://github.com/vitejs/vite/issues/21660)) ([b3ddbc5](https://github.com/vitejs/vite/commit/b3ddbc54ee5b836852b09811c8e920b2b2cde7cb))\n- update rolldown to 1.0.0-rc.4 ([#21617](https://github.com/vitejs/vite/issues/21617)) ([1ee5c7f](https://github.com/vitejs/vite/commit/1ee5c7f796c24d7319fbd5258bbdce4968859efe))\n- **wasm:** add SSR support for `.wasm?init` ([#21102](https://github.com/vitejs/vite/issues/21102)) ([216a3b5](https://github.com/vitejs/vite/commit/216a3b53c610918027a7713a0d5495628f77d306))\n- integrate devtools ([#21331](https://github.com/vitejs/vite/issues/21331)) ([acbf507](https://github.com/vitejs/vite/commit/acbf507bcb05f9cd9525c765431b3e0ed97328e4))\n- update rolldown to 1.0.0-rc.3 ([#21554](https://github.com/vitejs/vite/issues/21554)) ([43358e9](https://github.com/vitejs/vite/commit/43358e97cd6485513f25ee11133333cba05841e3))\n- **manifest:** add `assets` field for standalone CSS entry points ([#21015](https://github.com/vitejs/vite/issues/21015)) ([f289b9b](https://github.com/vitejs/vite/commit/f289b9b0ce7821b1554b878d083c426e7a695b59))\n- update rolldown to 1.0.0-rc.2 ([#21512](https://github.com/vitejs/vite/issues/21512)) ([fa136a9](https://github.com/vitejs/vite/commit/fa136a9e68921f3ca396e0870193fe805fbfb7b4))\n- **bundled-dev:** support worker in initial bundle ([#21415](https://github.com/vitejs/vite/issues/21415)) ([f3d3149](https://github.com/vitejs/vite/commit/f3d31499c714fe5c5acf8355520624c662f9d79f))\n- **dev:** detect port conflicts on wildcard hosts ([#21381](https://github.com/vitejs/vite/issues/21381)) ([b0dd5a9](https://github.com/vitejs/vite/commit/b0dd5a993fd2f95c8cb2190a3ca4296bc9e06359))\n- shortcuts case insensitive ([#21224](https://github.com/vitejs/vite/issues/21224)) ([7796ade](https://github.com/vitejs/vite/commit/7796aded764bca987abfec8ab0ad0438c5a5e7eb))\n- update rolldown to 1.0.0-rc.1 ([#21463](https://github.com/vitejs/vite/issues/21463)) ([ff9dd7f](https://github.com/vitejs/vite/commit/ff9dd7fef0d3c898e317fca84a629828f3e28936))\n- warn if `envPrefix` contains spaces ([#21292](https://github.com/vitejs/vite/issues/21292)) ([9fcde3c](https://github.com/vitejs/vite/commit/9fcde3c870896a62fbca19be8ee14efab9393f4a))\n- update rolldown to 1.0.0-beta.60 ([#21408](https://github.com/vitejs/vite/issues/21408)) ([c33aa7c](https://github.com/vitejs/vite/commit/c33aa7cfd142a0dd38ed89589fc7b04cf8866791))\n- update rolldown to 1.0.0-beta.59 ([#21374](https://github.com/vitejs/vite/issues/21374)) ([0037943](https://github.com/vitejs/vite/commit/00379439fa62383460b056d587d0366597c19ab4))\n- add `ignoreOutdatedRequests` option to `optimizeDeps` ([#21364](https://github.com/vitejs/vite/issues/21364)) ([b2e75aa](https://github.com/vitejs/vite/commit/b2e75aabe93e3219f40fa5ad8755d53cdd2439b5))\n- add ios to default esbuild targets ([#21342](https://github.com/vitejs/vite/issues/21342)) ([daae6e9](https://github.com/vitejs/vite/commit/daae6e9f5dd223258a9e7a9a7fa22c8a4564902f))\n- update rolldown to 1.0.0-beta.58 ([#21354](https://github.com/vitejs/vite/issues/21354)) ([ba40cef](https://github.com/vitejs/vite/commit/ba40cef16d20590f7115d4d628d9b79fa0783473))\n- update rolldown to 1.0.0-beta.57 ([#21335](https://github.com/vitejs/vite/issues/21335)) ([d5412ef](https://github.com/vitejs/vite/commit/d5412ef4c472bc5fef4ed69cfee4ef4a929c6be9))\n- **css:** support es2024 build target for lightningcss ([#21294](https://github.com/vitejs/vite/issues/21294)) ([bd33b8e](https://github.com/vitejs/vite/commit/bd33b8e08768fdcef0b09e3eefa649fdcafdd397))\n- update rolldown to 1.0.0-beta.56 ([#21323](https://github.com/vitejs/vite/issues/21323)) ([9847a63](https://github.com/vitejs/vite/commit/9847a634cf36de2e6ac0043ffd22cefb1b5951bd))\n- introduce v2 native plugins and enable it by default ([#21268](https://github.com/vitejs/vite/issues/21268)) ([42f2ab3](https://github.com/vitejs/vite/commit/42f2ab3aec7cd0e03e195611b1e1ddabbedc9d61))\n- **ssr:** avoid errors when rewriting already rewritten stacktrace ([#21269](https://github.com/vitejs/vite/issues/21269)) ([98d9a33](https://github.com/vitejs/vite/commit/98d9a33274d9ac90780786afa612d916feddf2e3))\n- update rolldown to 1.0.0-beta.55 ([#21300](https://github.com/vitejs/vite/issues/21300)) ([2c8db85](https://github.com/vitejs/vite/commit/2c8db858d7081e898f63ce9569c3f19a91a10956))\n- update rolldown to 1.0.0-beta.54 ([#21267](https://github.com/vitejs/vite/issues/21267)) ([c751172](https://github.com/vitejs/vite/commit/c75117213cb1d2d13554fbc26a75e8df191c27eb))\n- add a warning that is output when a plugin sets esbuild related options ([#21218](https://github.com/vitejs/vite/issues/21218)) ([200646b](https://github.com/vitejs/vite/commit/200646b14397bfb80e9b29d2e4b33fcfc72d6b2c))\n- highly experimental full bundle mode ([#21235](https://github.com/vitejs/vite/issues/21235)) ([83d8c99](https://github.com/vitejs/vite/commit/83d8c99753d8bd5c1ea9b7a00e6998c865dad4e2))\n- print esbuild options when both esbuild and oxc options are set ([#21216](https://github.com/vitejs/vite/issues/21216)) ([08ae87b](https://github.com/vitejs/vite/commit/08ae87b14a3ce5f7cb3f1a382f497d36d0c2e01b))\n- update default browser target ([#21193](https://github.com/vitejs/vite/issues/21193)) ([8c3dd06](https://github.com/vitejs/vite/commit/8c3dd06bd9903bf0e6bc51f3554eea8cb6b26903))\n- the epic `rolldown-vite` merge ([#21189](https://github.com/vitejs/vite/issues/21189)) ([4a7f8d4](https://github.com/vitejs/vite/commit/4a7f8d43e6b14b89fef278c3ea86f9e3f64b7fc2))\n\n### Bug Fixes\n\n- **deps:** update all non-major dependencies ([#21786](https://github.com/vitejs/vite/issues/21786)) ([eaa4352](https://github.com/vitejs/vite/commit/eaa4352af8f8658e3a10a9945ad9c227fcb2f28a))\n- use `watch.watcher` instead of `watch.notify` ([#21793](https://github.com/vitejs/vite/issues/21793)) ([88953b3](https://github.com/vitejs/vite/commit/88953b331d6b6acf20dc1731745f27712b091fd9))\n- **css:** apply `server.origin` to public file URLs in CSS (fix [#18457](https://github.com/vitejs/vite/issues/18457)) ([#21697](https://github.com/vitejs/vite/issues/21697)) ([c967f48](https://github.com/vitejs/vite/commit/c967f48b2e888585e977c3a8d829f7370eb40922))\n- **deps:** update all non-major dependencies ([#21732](https://github.com/vitejs/vite/issues/21732)) ([5c921ca](https://github.com/vitejs/vite/commit/5c921ca9bfe64327df82b04ae34ccfe0a7cfa297))\n- **dev:** disable extglobs for consistency ([#21745](https://github.com/vitejs/vite/issues/21745)) ([1958eeb](https://github.com/vitejs/vite/commit/1958eeb34f9eab93f106b785c1c2ddf97b5c3b3a))\n- **lib:** keep annotation comments for es output ([#21740](https://github.com/vitejs/vite/issues/21740)) ([dd3c4f4](https://github.com/vitejs/vite/commit/dd3c4f4cf0f9e665e56e6d9a9cb7007fc3ac0dc3))\n- **optimizer:** avoid error happening with a package with asset entrypoint ([#21766](https://github.com/vitejs/vite/issues/21766)) ([f7e1d07](https://github.com/vitejs/vite/commit/f7e1d0720e6b9f2ce5d358b6a23ebdb72c51be70))\n- **ssr:** throw friendly error when calling `ssrLoadModule` with non-runnable ssr env ([#21739](https://github.com/vitejs/vite/issues/21739)) ([1fa736e](https://github.com/vitejs/vite/commit/1fa736e802c3f0fa0eacdda1d5d1c976794459bd))\n- **types:** remove extends ImportMeta from ModuleRunnerImportMeta ([#21710](https://github.com/vitejs/vite/issues/21710)) ([0176d45](https://github.com/vitejs/vite/commit/0176d45deb29f5db1f551d20d828598c2130be36))\n- **wasm:** reset assetUrlRE.lastIndex before .test() in SSR builds ([#21780](https://github.com/vitejs/vite/issues/21780)) ([3a0d8d9](https://github.com/vitejs/vite/commit/3a0d8d94a8868f5e118c81bc35a657ef19ff7d82))\n- **deps:** update all non-major dependencies ([#21691](https://github.com/vitejs/vite/issues/21691)) ([521fdc0](https://github.com/vitejs/vite/commit/521fdc0ced51ddee7f728e6f891f36ebc6c0e1ce))\n- **optimizer:** avoid duplicate modules when `preserveSymlinks` is enabled ([#21720](https://github.com/vitejs/vite/issues/21720)) ([72165e0](https://github.com/vitejs/vite/commit/72165e0f58d49b894a366af25993cbffbd0ee986))\n- **dev:** only treat EADDRINUSE as port conflict in wildcard pre-check ([#21642](https://github.com/vitejs/vite/issues/21642)) ([e54e25f](https://github.com/vitejs/vite/commit/e54e25fbb9b721b2c655d17e35706e070c92ff70))\n- **dev:** prevent concurrent server restarts ([#21636](https://github.com/vitejs/vite/issues/21636)) ([8ce23a3](https://github.com/vitejs/vite/commit/8ce23a3b6e1eb86eef2b50c1bfbad072bbf9a03a))\n- **dev:** return \"502 Bad Gateway\" on proxy failures instead of 500 ([#21652](https://github.com/vitejs/vite/issues/21652)) ([e240df2](https://github.com/vitejs/vite/commit/e240df2ea4accd11631aac0f361e846a2e3140b0))\n- clear tsconfig cache only when tsconfig.json is cached ([#21622](https://github.com/vitejs/vite/issues/21622)) ([50c9675](https://github.com/vitejs/vite/commit/50c9675aa6c488b9887b7849a3397b7b29d1bd74))\n- **deps:** update all non-major dependencies ([#21594](https://github.com/vitejs/vite/issues/21594)) ([becdc5d](https://github.com/vitejs/vite/commit/becdc5dcc49efa3769c92e9929fb2280fd776206))\n- **lib:** CSS injection point error with nested name IIFE output ([#21606](https://github.com/vitejs/vite/issues/21606)) ([5003de6](https://github.com/vitejs/vite/commit/5003de6253ffdb23d1a52b1b5e06281d34f3a6ec))\n- **module-runner:** incorrect column with `sourcemapInterceptor: \"prepareStackTrace\"` ([#21562](https://github.com/vitejs/vite/issues/21562)) ([416c095](https://github.com/vitejs/vite/commit/416c0959ebd63db622c6579b53065e95f09c63f8))\n- **module-runner:** prevent crash on negative column in stacktrace ([#21585](https://github.com/vitejs/vite/issues/21585)) ([a075590](https://github.com/vitejs/vite/commit/a075590c4091240a6f0caca6b052500fd122f041))\n- rolldownOptions/rollupOptions merging at environment level ([#21612](https://github.com/vitejs/vite/issues/21612)) ([db2ecc7](https://github.com/vitejs/vite/commit/db2ecc7675c3932fc9e127b726ab8b0cab25f75c))\n- **scanner:** respect tsconfig.json ([#21547](https://github.com/vitejs/vite/issues/21547)) ([c6c04db](https://github.com/vitejs/vite/commit/c6c04db9c67d1b390d40fd1fd026d49204957f8d))\n- avoid registering customization hook for import meta resolver multiple times ([#21518](https://github.com/vitejs/vite/issues/21518)) ([8bb3203](https://github.com/vitejs/vite/commit/8bb32036792a6f522f5c947112f3d688add755a0))\n- **config:** avoid watching rolldown runtime virtual module ([#21545](https://github.com/vitejs/vite/issues/21545)) ([d18b139](https://github.com/vitejs/vite/commit/d18b13957b3bec08eae5a9ff80340488c8150d46))\n- **deps:** update all non-major dependencies ([#21540](https://github.com/vitejs/vite/issues/21540)) ([9ebaeaa](https://github.com/vitejs/vite/commit/9ebaeaac094db996b1d12665052633c20ac8a9cf))\n- populate originalFileNames when resolving CSS asset paths ([#21542](https://github.com/vitejs/vite/issues/21542)) ([8b47ff7](https://github.com/vitejs/vite/commit/8b47ff76d28630b4dc39c77fbd2762b4c36ad23d))\n- **deps:** update all non-major dependencies ([#21488](https://github.com/vitejs/vite/issues/21488)) ([2b32ca2](https://github.com/vitejs/vite/commit/2b32ca24fe9d742901c2cb5c88e6b1fd734f8c73))\n- disable `tsconfig` option when loading config ([#21517](https://github.com/vitejs/vite/issues/21517)) ([5025c35](https://github.com/vitejs/vite/commit/5025c358d119aa0b60d0505f9dd705950ad897f6))\n- **optimizer:** map relative `new URL` paths to correct relative file location ([#21434](https://github.com/vitejs/vite/issues/21434)) ([ca96cbc](https://github.com/vitejs/vite/commit/ca96cbc8eff23091c288f9eaf1944af2de3c564f))\n- avoid using deprecated `output.inlineDynamicImport` option ([#21464](https://github.com/vitejs/vite/issues/21464)) ([471ce62](https://github.com/vitejs/vite/commit/471ce6275663f068afa241a55711fd646d482385))\n- use separate hook object for each environment ([#21472](https://github.com/vitejs/vite/issues/21472)) ([66347f6](https://github.com/vitejs/vite/commit/66347f6df0e723d9d03ea31ab41ab5b767ad15ba))\n- **deps:** update all non-major dependencies ([#21440](https://github.com/vitejs/vite/issues/21440)) ([1835995](https://github.com/vitejs/vite/commit/18359959cb2960a2fb2b9a340e5ae27d122a1501))\n- **dev:** avoid event emitter leak caused by `server.listen` callback ([#21451](https://github.com/vitejs/vite/issues/21451)) ([602d786](https://github.com/vitejs/vite/commit/602d7865db2b12835c8225f3e87076bef4e247b9))\n- lazy hook filter should work ([#21443](https://github.com/vitejs/vite/issues/21443)) ([bc0c207](https://github.com/vitejs/vite/commit/bc0c207f537789d10d55caa4ee3697aa923b8426))\n- **optimizer:** skip `rolldownCjsExternalPlugin` for `platform: neutral` ([#21452](https://github.com/vitejs/vite/issues/21452)) ([d2fc4be](https://github.com/vitejs/vite/commit/d2fc4be0447e384e18e557b70f7c345d5bcea941))\n- **deps:** update all non-major dependencies ([#21389](https://github.com/vitejs/vite/issues/21389)) ([30f48df](https://github.com/vitejs/vite/commit/30f48df33ec9e9bd0b8164461eede5574398370b))\n- **deps:** update esbuild peerDependency version ([#21398](https://github.com/vitejs/vite/issues/21398)) ([4266c97](https://github.com/vitejs/vite/commit/4266c978083b3afa8d09ac3d3a110ee79f8efde2))\n- **hmr:** trigger prune event when last import is removed ([#20781](https://github.com/vitejs/vite/issues/20781)) ([#21093](https://github.com/vitejs/vite/issues/21093)) ([7576735](https://github.com/vitejs/vite/commit/757673528c64945b77aee4a8e01669ccd0644973))\n- **module-runner:** use `process.getBuiltinModule` instead of `import('node:module')` ([#21402](https://github.com/vitejs/vite/issues/21402)) ([6633bcb](https://github.com/vitejs/vite/commit/6633bcb94149a2923cb6419aa481c5384bcf9310))\n- support .env file mounts (FIFOs) ([#21365](https://github.com/vitejs/vite/issues/21365)) ([6e6f82a](https://github.com/vitejs/vite/commit/6e6f82a067acc6e158be3b82edb3d7d2888f9af2))\n- **css:** stylus Evaluator support ([#21376](https://github.com/vitejs/vite/issues/21376)) ([cf9ace1](https://github.com/vitejs/vite/commit/cf9ace1b40b2767b9b9cbbabb084fe2e32afc535))\n- **deps:** update all non-major dependencies ([#21321](https://github.com/vitejs/vite/issues/21321)) ([9bc7c2e](https://github.com/vitejs/vite/commit/9bc7c2ed4f387fb982b84d1988a26af8990096f7))\n- **import-analysis:** avoid cjs interop for built browser external module ([#21333](https://github.com/vitejs/vite/issues/21333)) ([dc5a2fb](https://github.com/vitejs/vite/commit/dc5a2fb86f10c69b0ba6bc1831d9a29c79754ba2))\n- **worker:** handle `new Worker(..., new URL(import.meta.url))` with trailing comma ([#21325](https://github.com/vitejs/vite/issues/21325)) ([4a47241](https://github.com/vitejs/vite/commit/4a472418c02a0821900678778752c2d361bae3bd))\n- detect `import.meta.resolve` when formatted across multiple lines ([#21312](https://github.com/vitejs/vite/issues/21312)) ([130e718](https://github.com/vitejs/vite/commit/130e7181a55c524383c63bbfb1749d0ff7185cad))\n- allow no-cors requests for non-script tag requests ([#21299](https://github.com/vitejs/vite/issues/21299)) ([ef3d596](https://github.com/vitejs/vite/commit/ef3d59648fd9dd3f9b3118d09d216dc0afcb8c33))\n- **deps:** update all non-major dependencies ([#21285](https://github.com/vitejs/vite/issues/21285)) ([4635b2e](https://github.com/vitejs/vite/commit/4635b2e90f833d1048d76381e20208c0e0841e97))\n- unreachable error when building with `experimental.bundledDev` is enabled ([#21296](https://github.com/vitejs/vite/issues/21296)) ([e81c183](https://github.com/vitejs/vite/commit/e81c183f8c8ccaf7774ef0d0ee125bf63dbf30b4))\n- **deps:** update all non-major dependencies ([#21231](https://github.com/vitejs/vite/issues/21231)) ([859789c](https://github.com/vitejs/vite/commit/859789c856412dfa67969232ddda1df754febf40))\n- don't strip base from imports ([#21221](https://github.com/vitejs/vite/issues/21221)) ([7da742b](https://github.com/vitejs/vite/commit/7da742b478d2309c7d8de4cb55614a6476f350b4))\n- allow exiting process before optimizer cleanup is done ([#21170](https://github.com/vitejs/vite/issues/21170)) ([55ceffc](https://github.com/vitejs/vite/commit/55ceffc8976b8bb8c819f5b47419f8499ba3f843))\n- plugin shortcut support ([#21211](https://github.com/vitejs/vite/issues/21211)) ([6a3aca0](https://github.com/vitejs/vite/commit/6a3aca084356316811ff62cbedb5a410a249e789))\n\n### Performance Improvements\n\n- **ssr:** skip circular import check for already-evaluated modules ([#21632](https://github.com/vitejs/vite/issues/21632)) ([235140b](https://github.com/vitejs/vite/commit/235140b2d519e866fc28f88fe8155a5091630daf))\n- use tsconfig cache for oxc transform in dev ([#21643](https://github.com/vitejs/vite/issues/21643)) ([57ff177](https://github.com/vitejs/vite/commit/57ff177575bef6bee81a250e853d2c99affa0015))\n\n### Documentation\n\n- bulk of typo fixes ([#21507](https://github.com/vitejs/vite/issues/21507)) ([80755da](https://github.com/vitejs/vite/commit/80755dacab296cd2083fef29e09280ceb810a943))\n- update `build.dynamicImportVarsOptions` ([#21477](https://github.com/vitejs/vite/issues/21477)) ([54ce2ed](https://github.com/vitejs/vite/commit/54ce2ed15a95619bd18ac6609b7d7b5f42b4965d))\n- clarify the pronunciation of `vite` in IPA symbols ([#21238](https://github.com/vitejs/vite/issues/21238)) ([9b1d4d6](https://github.com/vitejs/vite/commit/9b1d4d6f348c8899bd7651bd802f583e99b901ee))\n- ensure https links ([#21266](https://github.com/vitejs/vite/issues/21266)) ([2eb259a](https://github.com/vitejs/vite/commit/2eb259a84859c7656718258afed08eb80670f530))\n\n### Miscellaneous Chores\n\n- **deps-dev:** bump rollup from 4.57.1 to 4.59.0 ([#21717](https://github.com/vitejs/vite/issues/21717)) ([25227bb](https://github.com/vitejs/vite/commit/25227bbdc7de0ed07cf7bdc9a1a733e3a9a132bc))\n- **deps:** update dependency cac to v7 ([#21788](https://github.com/vitejs/vite/issues/21788)) ([44e33ae](https://github.com/vitejs/vite/commit/44e33ae6a7b64130831f08b2a20d04cbd106898d))\n- **deps:** update dependency rolldown-plugin-dts to ^0.22.2 ([#21731](https://github.com/vitejs/vite/issues/21731)) ([d8ea652](https://github.com/vitejs/vite/commit/d8ea652a8b295d9e012ac7ea607d813c69f77791))\n- **deps:** remove `fdir` and `@rollup/plugin-commonjs` ([#21639](https://github.com/vitejs/vite/issues/21639)) ([5abffd5](https://github.com/vitejs/vite/commit/5abffd5d04bf586a60970588a14d7e3b79445093))\n- **deps:** update dependency @rollup/plugin-alias to v6 ([#21097](https://github.com/vitejs/vite/issues/21097)) ([44b5bdf](https://github.com/vitejs/vite/commit/44b5bdfcf2b2c1b73563ed0526c48584b756360f))\n- fix broken link for future deprecations ([#21603](https://github.com/vitejs/vite/issues/21603)) ([25f4501](https://github.com/vitejs/vite/commit/25f45013b94e50acc5c3e476691aa2210b33cae4))\n- update `customResolver` deprecation message to mention `enforce: 'pre'` ([#21576](https://github.com/vitejs/vite/issues/21576)) ([2ce34d5](https://github.com/vitejs/vite/commit/2ce34d5580ed118db6361696e6283c1fea74e685))\n- update rolldown-plugin-dts to 0.22.1 ([#21559](https://github.com/vitejs/vite/issues/21559)) ([77aab4b](https://github.com/vitejs/vite/commit/77aab4b7f1e3a2131477659c909a3fbe02faa0a0))\n- **deps:** update dependency rolldown-plugin-dts to ^0.21.8 ([#21539](https://github.com/vitejs/vite/issues/21539)) ([33881cb](https://github.com/vitejs/vite/commit/33881cb34f4587919713975d13ce255ef744472d))\n- add missing versions to changelog ([#21515](https://github.com/vitejs/vite/issues/21515)) ([4bfb239](https://github.com/vitejs/vite/commit/4bfb239686a17343bc46c0d7c968e28b0d64041f))\n- **deps:** update rolldown-related dependencies ([#21487](https://github.com/vitejs/vite/issues/21487)) ([5863e51](https://github.com/vitejs/vite/commit/5863e513fab6b481cfb42da86202f9db728c077d))\n- **deps:** update rolldown-related dependencies ([#21390](https://github.com/vitejs/vite/issues/21390)) ([be9dd4e](https://github.com/vitejs/vite/commit/be9dd4e08d899f9ed27f2bdcb81bf27d018377a6))\n- fix typo in plugin.ts comment ([#21435](https://github.com/vitejs/vite/issues/21435)) ([d31fc66](https://github.com/vitejs/vite/commit/d31fc6685b4dde33062bf4dfe46e0502de4e1449))\n- replace caniuse link for ES2024 ([#21355](https://github.com/vitejs/vite/issues/21355)) ([2ba4e99](https://github.com/vitejs/vite/commit/2ba4e990192845e01c733aa186c9599cdb5bb8fe))\n- cleanup changelog ([#21202](https://github.com/vitejs/vite/issues/21202)) ([8c8c56e](https://github.com/vitejs/vite/commit/8c8c56e1eb465e6dcd0c1b40f187228edc0e2be4))\n- **deps:** update rolldown-related dependencies ([#21230](https://github.com/vitejs/vite/issues/21230)) ([9349446](https://github.com/vitejs/vite/commit/9349446e9344bd81ccfb37af482f479cd1b59bbc))\n- fix spelling error ([#21223](https://github.com/vitejs/vite/issues/21223)) ([cc10e20](https://github.com/vitejs/vite/commit/cc10e207ae87ac122fc1efbb5ab01b516eb9cce8))\n\n### Code Refactoring\n\n- don't add `optimization.inlineConst: { mode: 'smart' }` as it's enabled by default ([#21794](https://github.com/vitejs/vite/issues/21794)) ([22b3d11](https://github.com/vitejs/vite/commit/22b3d111c38deb76d3c07010bf9903e3ee1befc1))\n- enable some native plugins even with enable native plugin false ([#21744](https://github.com/vitejs/vite/issues/21744)) ([fc46c79](https://github.com/vitejs/vite/commit/fc46c79797e9ec22a5a4fb1999f6268f72d586f8))\n- avoid deprecated `legalComments` option ([#21721](https://github.com/vitejs/vite/issues/21721)) ([e06496e](https://github.com/vitejs/vite/commit/e06496ef259015b5a89f33a9965be25f8bea0624))\n- use `ESTree` types from `rolldown/utils` ([#21719](https://github.com/vitejs/vite/issues/21719)) ([9239750](https://github.com/vitejs/vite/commit/9239750e619afba03243d6d583eaca55b510ddfe))\n- deprecate `customResolver` in `resolve.alias` ([#21476](https://github.com/vitejs/vite/issues/21476)) ([81275c9](https://github.com/vitejs/vite/commit/81275c907211ac766013e6232c2cdf559534bed1))\n- remove unnecessary `@rolldown/pluginutils` ([#21560](https://github.com/vitejs/vite/issues/21560)) ([c367b62](https://github.com/vitejs/vite/commit/c367b62693f19040e64d14915877f0b05b8ac7ae))\n- enable some native plugins even with enable native plugin false ([#21608](https://github.com/vitejs/vite/issues/21608)) ([5a4f692](https://github.com/vitejs/vite/commit/5a4f6924260ef0f2683177a99935160badea3f3b))\n- use `rolldown/utils` ([#21577](https://github.com/vitejs/vite/issues/21577)) ([e56103f](https://github.com/vitejs/vite/commit/e56103f180216306de738769303f31ad4c078b26))\n- use internal devtools config ([#21609](https://github.com/vitejs/vite/issues/21609)) ([9aea20f](https://github.com/vitejs/vite/commit/9aea20f4a190e0e1c7edc656361d636cd6ce642f))\n- use parseEnv ([#21586](https://github.com/vitejs/vite/issues/21586)) ([f859d2c](https://github.com/vitejs/vite/commit/f859d2cdfcc18f139775c208be068461a91602e5))\n- **wasm:** remove native wasm helper plugin usage ([#21566](https://github.com/vitejs/vite/issues/21566)) ([71a86be](https://github.com/vitejs/vite/commit/71a86be6d9b9ea0329e92f20671f4db1f020874d))\n- enable some native plugins even with enable native plugin false ([#21511](https://github.com/vitejs/vite/issues/21511)) ([b40292c](https://github.com/vitejs/vite/commit/b40292ce6a7dbbbbac9c6dae5f126b7f44c3e1b7))\n- remove `experimental.enableNativePlugin: 'resolver'` ([#21510](https://github.com/vitejs/vite/issues/21510)) ([f9d9213](https://github.com/vitejs/vite/commit/f9d92130fa79c638f77a3a8e6e55506f185d5a49))\n- use `import.meta.dirname` everywhere ([#21509](https://github.com/vitejs/vite/issues/21509)) ([7becf5f](https://github.com/vitejs/vite/commit/7becf5f8fe9041cff60f495ef975faaba68f9eb2))\n- **optimizer:** simplify `rolldownCjsExternalPlugin` ([#21450](https://github.com/vitejs/vite/issues/21450)) ([ebda8fd](https://github.com/vitejs/vite/commit/ebda8fd3c14f60e63d13d22102cb3d79a12f47a9))\n- remove `import.meta.hot.accept` resolution fallback ([#21382](https://github.com/vitejs/vite/issues/21382)) ([71d0797](https://github.com/vitejs/vite/commit/71d0797a719440f2a09b3364bfcf18576c2b67fb))\n- **optimizer:** remove dead code ([#21334](https://github.com/vitejs/vite/issues/21334)) ([e9a2cdb](https://github.com/vitejs/vite/commit/e9a2cdbb7d96a3f8e15d25774708d4f4ab626bb9))\n\n### Tests\n\n- **ssr:** incorrect `handleInvoke` was called in server-worker-runner.invoke test ([#21751](https://github.com/vitejs/vite/issues/21751)) ([b95ca22](https://github.com/vitejs/vite/commit/b95ca22460fe39fc862444f8c642fd6a0794c87c))\n- add more type tests for `defineConfig` ([#21698](https://github.com/vitejs/vite/issues/21698)) ([4fedbbd](https://github.com/vitejs/vite/commit/4fedbbdd9178a3f92e491233f44d49b3ac095c69))\n- test case for catching invalid package resolution error ([#21601](https://github.com/vitejs/vite/issues/21601)) ([c9b9359](https://github.com/vitejs/vite/commit/c9b9359fe88fc4b8a69a0d5c5a7eed8961fb6e57))\n- **bundled-dev:** add worker test cases ([#21557](https://github.com/vitejs/vite/issues/21557)) ([569bc98](https://github.com/vitejs/vite/commit/569bc98d6bc42fbd1835c1c24a493776030b6cb4))\n\n### Beta Changelogs\n\n#### [8.0.0-beta.18](https://github.com/vitejs/vite/compare/v8.0.0-beta.17...v8.0.0-beta.18) (2026-03-09)\n\nSee [8.0.0-beta.18 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.18/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.17](https://github.com/vitejs/vite/compare/v8.0.0-beta.16...v8.0.0-beta.17) (2026-03-09)\n\nSee [8.0.0-beta.17 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.17/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.16](https://github.com/vitejs/vite/compare/v8.0.0-beta.15...v8.0.0-beta.16) (2026-02-27)\n\nSee [8.0.0-beta.16 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.16/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.15](https://github.com/vitejs/vite/compare/v8.0.0-beta.14...v8.0.0-beta.15) (2026-02-19)\n\nSee [8.0.0-beta.15 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.15/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.14](https://github.com/vitejs/vite/compare/v8.0.0-beta.13...v8.0.0-beta.14) (2026-02-12)\n\nSee [8.0.0-beta.14 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.14/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.13](https://github.com/vitejs/vite/compare/v8.0.0-beta.12...v8.0.0-beta.13) (2026-02-05)\n\nSee [8.0.0-beta.13 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.13/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.12](https://github.com/vitejs/vite/compare/v8.0.0-beta.11...v8.0.0-beta.12) (2026-02-03)\n\nSee [8.0.0-beta.12 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.12/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.11](https://github.com/vitejs/vite/compare/v8.0.0-beta.10...v8.0.0-beta.11) (2026-01-29)\n\nSee [8.0.0-beta.11 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.11/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.10](https://github.com/vitejs/vite/compare/v8.0.0-beta.9...v8.0.0-beta.10) (2026-01-24)\n\nSee [8.0.0-beta.10 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.10/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.9](https://github.com/vitejs/vite/compare/v8.0.0-beta.8...v8.0.0-beta.9) (2026-01-22)\n\nSee [8.0.0-beta.9 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.9/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.8](https://github.com/vitejs/vite/compare/v8.0.0-beta.7...v8.0.0-beta.8) (2026-01-15)\n\nSee [8.0.0-beta.8 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.8/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.7](https://github.com/vitejs/vite/compare/v8.0.0-beta.6...v8.0.0-beta.7) (2026-01-08)\n\nSee [8.0.0-beta.7 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.7/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.6](https://github.com/vitejs/vite/compare/v8.0.0-beta.5...v8.0.0-beta.6) (2026-01-07)\n\nSee [8.0.0-beta.6 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.6/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.5](https://github.com/vitejs/vite/compare/v8.0.0-beta.4...v8.0.0-beta.5) (2025-12-25)\n\nSee [8.0.0-beta.5 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.5/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.4](https://github.com/vitejs/vite/compare/v8.0.0-beta.3...v8.0.0-beta.4) (2025-12-22)\n\nSee [8.0.0-beta.4 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.4/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.3](https://github.com/vitejs/vite/compare/v8.0.0-beta.2...v8.0.0-beta.3) (2025-12-18)\n\nSee [8.0.0-beta.3 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.3/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.2](https://github.com/vitejs/vite/compare/v8.0.0-beta.1...v8.0.0-beta.2) (2025-12-12)\n\nSee [8.0.0-beta.2 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.2/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.1](https://github.com/vitejs/vite/compare/v8.0.0-beta.0...v8.0.0-beta.1) (2025-12-08)\n\nSee [8.0.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.1/packages/vite/CHANGELOG.md)\n\n#### [8.0.0-beta.0](https://github.com/vitejs/vite/compare/v7.2.4...v8.0.0-beta.0) (2025-12-03)\n\nSee [8.0.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v8.0.0-beta.0/packages/vite/CHANGELOG.md)\n\n### Rolldown-Vite changelogs\n\nSee [rolldown-vite changelog](https://github.com/vitejs/rolldown-vite/blob/v7.2.10/packages/vite/CHANGELOG.md)\n\n## <small>[7.3.1](https://github.com/vitejs/vite/compare/v7.3.0...v7.3.1) (2026-01-07)</small>\n### Features\n\n* add `ignoreOutdatedRequests` option to `optimizeDeps` ([#21364](https://github.com/vitejs/vite/issues/21364)) ([9d39d37](https://github.com/vitejs/vite/commit/9d39d373a7b4e0a93322b70b9dbeb202af06af3e))\n\n## [7.3.0](https://github.com/vitejs/vite/compare/v7.2.7...v7.3.0) (2025-12-15)\n### Features\n\n* **deps:** update esbuild from ^0.25.0 to ^0.27.0 ([#21183](https://github.com/vitejs/vite/issues/21183)) ([cff26ec](https://github.com/vitejs/vite/commit/cff26ec0fc13373d7125a5eac6cb01fe63fee4b1))\n\n## <small>[7.2.7](https://github.com/vitejs/vite/compare/v7.2.6...v7.2.7) (2025-12-08)</small>\n### Bug Fixes\n\n* plugin shortcut support ([#21211](https://github.com/vitejs/vite/issues/21211)) ([721f163](https://github.com/vitejs/vite/commit/721f16343d9555ae8fc71a2e5354b22e12ff0dc3))\n\n## <small>[7.2.6](https://github.com/vitejs/vite/compare/v7.2.5...v7.2.6) (2025-12-01)</small>\n## <small>[7.2.5](https://github.com/vitejs/vite/compare/v7.2.4...v7.2.5) (2025-12-01)</small>\n### Bug Fixes\n\n* **config:** handle shebang properly ([#21158](https://github.com/vitejs/vite/issues/21158)) ([df5a30d](https://github.com/vitejs/vite/commit/df5a30d2690a2ebc4824a79becdcef30538dc602))\n* **deps:** update all non-major dependencies ([#21146](https://github.com/vitejs/vite/issues/21146)) ([a3cd262](https://github.com/vitejs/vite/commit/a3cd262f37228967e455617e982b35fccc49ffe9))\n* **deps:** update all non-major dependencies ([#21175](https://github.com/vitejs/vite/issues/21175)) ([72e398a](https://github.com/vitejs/vite/commit/72e398a46d8d2f54fbcbeb9ff0dceab346aeb642))\n* fix `external: true` merging ([#21164](https://github.com/vitejs/vite/issues/21164)) ([5ef557a](https://github.com/vitejs/vite/commit/5ef557a96c4a1f2b3a3aa25c12df3ee87b4a03f5))\n* shortcuts not rebound after server restart ([#21166](https://github.com/vitejs/vite/issues/21166)) ([3765f7b](https://github.com/vitejs/vite/commit/3765f7baea36234bf3816eeed38776d27bfd3649))\n\n### Performance Improvements\n\n* **deps:** replace debug with obug ([#21137](https://github.com/vitejs/vite/issues/21137)) ([203a551](https://github.com/vitejs/vite/commit/203a5512a42a1031f685993f5d9cbae5f328354f))\n\n### Documentation\n\n* clarify manifest.json `imports` field is JS chunks only ([#21136](https://github.com/vitejs/vite/issues/21136)) ([46d3077](https://github.com/vitejs/vite/commit/46d3077f2b63771cc50230bc907c48f5773c00fb))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#21174](https://github.com/vitejs/vite/issues/21174)) ([74559c9](https://github.com/vitejs/vite/commit/74559c947483a8ee24da052ac2d9568f7cb3546a))\n\n## <small>[7.2.4](https://github.com/vitejs/vite/compare/v7.2.3...v7.2.4) (2025-11-20)</small>\n### Bug Fixes\n\n* revert \"perf(deps): replace debug with obug ([#21107](https://github.com/vitejs/vite/issues/21107))\" ([2d66b7b](https://github.com/vitejs/vite/commit/2d66b7b14aa6dfd62f3d6a59ee8382ed5ca6fd32))\n\n## <small>[7.2.3](https://github.com/vitejs/vite/compare/v7.2.2...v7.2.3) (2025-11-20)</small>\n### Bug Fixes\n\n* allow multiple `bindCLIShortcuts` calls with shortcut merging ([#21103](https://github.com/vitejs/vite/issues/21103)) ([5909efd](https://github.com/vitejs/vite/commit/5909efd8fbfd1bf1eab65427aea0613124b2797a))\n* **deps:** update all non-major dependencies ([#21096](https://github.com/vitejs/vite/issues/21096)) ([6a34ac3](https://github.com/vitejs/vite/commit/6a34ac3422686e7cf7cc9a25d299cb8e5a8d92a0))\n* **deps:** update all non-major dependencies ([#21128](https://github.com/vitejs/vite/issues/21128)) ([4f8171e](https://github.com/vitejs/vite/commit/4f8171eb3046bd70c83964689897dab4c6b58bc0))\n\n### Performance Improvements\n\n* **deps:** replace debug with obug ([#21107](https://github.com/vitejs/vite/issues/21107)) ([acfe939](https://github.com/vitejs/vite/commit/acfe939e1f7c303c34b0b39b883cc302da767fa2))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency @rollup/plugin-commonjs to v29 ([#21099](https://github.com/vitejs/vite/issues/21099)) ([02ceaec](https://github.com/vitejs/vite/commit/02ceaec45e17bef19159188a28d9196fed1761be))\n* **deps:** update rolldown-related dependencies ([#21095](https://github.com/vitejs/vite/issues/21095)) ([39a0a15](https://github.com/vitejs/vite/commit/39a0a15fd24ed37257c48b795097a3794e54d255))\n* **deps:** update rolldown-related dependencies ([#21127](https://github.com/vitejs/vite/issues/21127)) ([5029720](https://github.com/vitejs/vite/commit/50297208452241061cb44d09a4bbdf77a11ac01e))\n\n## <small>[7.2.2](https://github.com/vitejs/vite/compare/v7.2.1...v7.2.2) (2025-11-07)</small>\n### Bug Fixes\n\n* revert \"refactor: use fs.cpSync ([#21019](https://github.com/vitejs/vite/issues/21019))\" ([#21081](https://github.com/vitejs/vite/issues/21081)) ([728c8ee](https://github.com/vitejs/vite/commit/728c8eeebc0ad7ba48e680f46bbdb55020b2e152))\n\n## <small>[7.2.1](https://github.com/vitejs/vite/compare/v7.2.0...v7.2.1) (2025-11-06)</small>\n### Bug Fixes\n\n* **worker:** some worker asset was missing ([#21074](https://github.com/vitejs/vite/issues/21074)) ([82d2d6c](https://github.com/vitejs/vite/commit/82d2d6ccf5a69c3d67e44e3704a0c3eb34db2236))\n\n### Code Refactoring\n\n* **build:** rename `indexOfMatchInSlice` to `findPreloadMarker` ([#21054](https://github.com/vitejs/vite/issues/21054)) ([f83264f](https://github.com/vitejs/vite/commit/f83264f5d97caa8ba80276a9ee9e82cb0e69c4ca))\n\n## [7.2.0](https://github.com/vitejs/vite/compare/v7.2.0-beta.1...v7.2.0) (2025-11-05)\n### Bug Fixes\n\n* **css:** fallback to sass when sass-embedded platform binary is missing ([#21002](https://github.com/vitejs/vite/issues/21002)) ([b1fd616](https://github.com/vitejs/vite/commit/b1fd6161886caeb31ac646d6544116d37efe46d0))\n* **module-runner:** make `getBuiltins` response JSON serializable ([#21029](https://github.com/vitejs/vite/issues/21029)) ([ad5b3bf](https://github.com/vitejs/vite/commit/ad5b3bf6f3ad7b24886718c5f5de32eee923ae11))\n* **types:** add undefined to optional properties for exactOptionalProperties type compatibility ([#21040](https://github.com/vitejs/vite/issues/21040)) ([2833c55](https://github.com/vitejs/vite/commit/2833c5576a87be2db450c195ccf64dfc8925a15b))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#21047](https://github.com/vitejs/vite/issues/21047)) ([e3a6a83](https://github.com/vitejs/vite/commit/e3a6a83406943bc59a9916cae3f25ab33c2b5802))\n\n## [7.2.0-beta.1](https://github.com/vitejs/vite/compare/v7.2.0-beta.0...v7.2.0-beta.1) (2025-10-29)\n### Bug Fixes\n\n* increase stream reset rate limit for HTTP2 ([#21024](https://github.com/vitejs/vite/issues/21024)) ([4f44f22](https://github.com/vitejs/vite/commit/4f44f22f7f4595d74c76778bd522387138775055))\n* **optimizer:** externalize virtual modules for html like files ([#21001](https://github.com/vitejs/vite/issues/21001)) ([e5af352](https://github.com/vitejs/vite/commit/e5af352d8e1a9f187159137f836db5bedbd68a66))\n\n### Documentation\n\n* clarify the values are escaped automatically ([#21017](https://github.com/vitejs/vite/issues/21017)) ([246df13](https://github.com/vitejs/vite/commit/246df134dd58441e1e40dd361cf42419d05ea7a5))\n\n### Code Refactoring\n\n* use `fs.cpSync` ([#21019](https://github.com/vitejs/vite/issues/21019)) ([a2df778](https://github.com/vitejs/vite/commit/a2df77812814b927880bc4d68aafa8c8fa47daf0))\n\n## [7.2.0-beta.0](https://github.com/vitejs/vite/compare/v7.1.11...v7.2.0-beta.0) (2025-10-28)\n### Features\n\n* add `import.meta.resolve` support for ESM config (bundle config loader) ([#20962](https://github.com/vitejs/vite/issues/20962)) ([f86789a](https://github.com/vitejs/vite/commit/f86789a6e237bd0e31cde3a3f09bdef45bfa7d1c))\n* add `perEnvironmentWatchChangeDuringDev` ([#20996](https://github.com/vitejs/vite/issues/20996)) ([a5e98e6](https://github.com/vitejs/vite/commit/a5e98e695ee4152127977abb506029dc8f7544fb))\n* add vite client connect events ([#20978](https://github.com/vitejs/vite/issues/20978)) ([543d87c](https://github.com/vitejs/vite/commit/543d87c2cd1ec629f19de56a903a15185f20db1f))\n* **build:** emit license ([#18546](https://github.com/vitejs/vite/issues/18546)) ([b42c3fb](https://github.com/vitejs/vite/commit/b42c3fb2cb75bb4fdf7557cb35946564d6dc4384))\n* **dev:** support HTTP2 even if proxy feature is used ([#20869](https://github.com/vitejs/vite/issues/20869)) ([fc21af7](https://github.com/vitejs/vite/commit/fc21af7a42dd559a95f54b6165d34f36883eaa7f))\n* **lib:** enable minification but keep pure annotations for es output with terser ([#20522](https://github.com/vitejs/vite/issues/20522)) ([df997d0](https://github.com/vitejs/vite/commit/df997d0cfca8e1dad04ac1bf8119caa2d2e4c1fc))\n* **optimizer:** add rush lockfile support ([#20833](https://github.com/vitejs/vite/issues/20833)) ([718ca2d](https://github.com/vitejs/vite/commit/718ca2d708dbeb393839932437a6b161851ca24c))\n* **utils:** support multiple certificates in resolveServerUrls ([#20707](https://github.com/vitejs/vite/issues/20707)) ([24513e5](https://github.com/vitejs/vite/commit/24513e567c643d5f6fb61af6298aa3fc2b166b90))\n\n### Bug Fixes\n\n* **build:** ensure amd bundles request `require` to be injected ([#20861](https://github.com/vitejs/vite/issues/20861)) ([bb85bd7](https://github.com/vitejs/vite/commit/bb85bd751e4568c707612b708deaba67f8af4ca3))\n* **build:** replace `names` in the manifest with unmangled `name` for CSS assets ([#20585](https://github.com/vitejs/vite/issues/20585)) ([4abf056](https://github.com/vitejs/vite/commit/4abf0566024a70c38a0eb5bf614f72189038247d))\n* **deps:** downgrade commonjs plugin to 28.0.6 to avoid rollup/plugins[#1909](https://github.com/vitejs/vite/issues/1909) ([#20988](https://github.com/vitejs/vite/issues/20988)) ([856e683](https://github.com/vitejs/vite/commit/856e683885ed53ec6044897451608bc6518baef6))\n* **deps:** update all non-major dependencies ([#21008](https://github.com/vitejs/vite/issues/21008)) ([185641e](https://github.com/vitejs/vite/commit/185641e3cdae29277c41eb8028f6eac542215f01))\n* disable optional peer dep handling for `nodeResolveWithVite` ([#20989](https://github.com/vitejs/vite/issues/20989)) ([ca18b23](https://github.com/vitejs/vite/commit/ca18b233d43a8f31883726ca565940ad1dc85f38))\n* handle query parameters for `/@vite/*` modules ([#20998](https://github.com/vitejs/vite/issues/20998)) ([6843a6a](https://github.com/vitejs/vite/commit/6843a6ae49df8ca523104a8ccfb9a8f9602b3881))\n* **module-runner:** resolve `resolvedSources` correctly ([#20959](https://github.com/vitejs/vite/issues/20959)) ([c4f6039](https://github.com/vitejs/vite/commit/c4f6039436657db50c610aa17eaf821dbd4ad57d))\n* **resolve:** match resolved subpath import path's relative prefix with regex (fix [#20972](https://github.com/vitejs/vite/issues/20972)) ([#20973](https://github.com/vitejs/vite/issues/20973)) ([ff2d83e](https://github.com/vitejs/vite/commit/ff2d83e2e7a3f7eba72f41b40686912f1e4b6843))\n* update build log to include environment name ([#20987](https://github.com/vitejs/vite/issues/20987)) ([77c25c1](https://github.com/vitejs/vite/commit/77c25c16ba9f3568e55fd4135f57c70f984d3fdd))\n* use esm entrypoint for css preprocessors and terser ([#20918](https://github.com/vitejs/vite/issues/20918)) ([1460824](https://github.com/vitejs/vite/commit/14608241cc4c821e7a392f6d92ef291a926bd94d))\n\n### Performance Improvements\n\n* **module-runner:** add client-side builtin module check ([#20924](https://github.com/vitejs/vite/issues/20924)) ([ccffead](https://github.com/vitejs/vite/commit/ccffead5f8340bf9e7d88fed4b3c0ac5a74f5926))\n* **module-runner:** use `module.registerHooks` when available ([#20980](https://github.com/vitejs/vite/issues/20980)) ([9c8a780](https://github.com/vitejs/vite/commit/9c8a7801c5ad29da4c3822c414223593c526e855))\n* run `dev.createEnvironment` and `build.createEnvironment` concurrently ([#20699](https://github.com/vitejs/vite/issues/20699)) ([d636220](https://github.com/vitejs/vite/commit/d6362207ba817a210cbcea1253a174542a6c8c68))\n* **worker:** rebuild only when affected ([#20559](https://github.com/vitejs/vite/issues/20559)) ([5cd3890](https://github.com/vitejs/vite/commit/5cd38906afe1fab4ec967b18b21c05a80ac49c92))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20965](https://github.com/vitejs/vite/issues/20965)) ([6ad5424](https://github.com/vitejs/vite/commit/6ad5424f0bcabd8943c34d341cf9ed2e64b3d53c))\n* **deps:** update rolldown-related dependencies ([#21009](https://github.com/vitejs/vite/issues/21009)) ([7cec1ad](https://github.com/vitejs/vite/commit/7cec1addc257eb5bd0856adbe1e4306f0bb83e22))\n* fix merge error ([075caa0](https://github.com/vitejs/vite/commit/075caa065bab659f45411cfe9b3b02e23ebe5406))\n\n### Code Refactoring\n\n* remove `listenersForEvents` variable ([#20977](https://github.com/vitejs/vite/issues/20977)) ([4d01112](https://github.com/vitejs/vite/commit/4d01112415a9c3d06f2fe143a9987e50c4d47f36))\n* remove unused `invoke` parameter ([#20991](https://github.com/vitejs/vite/issues/20991)) ([29cdb39](https://github.com/vitejs/vite/commit/29cdb390374689e4dec9017b21fefe88b6ce4203))\n\n### Build System\n\n* normalize license repo url ([#21010](https://github.com/vitejs/vite/issues/21010)) ([bb65468](https://github.com/vitejs/vite/commit/bb65468f3c6213fdd870c085610ec575af66b03c))\n* use isolated declarations ([#20928](https://github.com/vitejs/vite/issues/20928)) ([dad7643](https://github.com/vitejs/vite/commit/dad76436e96e1bac2baa805a0a3c1861e88e050c))\n\n## <small>[7.1.11](https://github.com/vitejs/vite/compare/v7.1.10...v7.1.11) (2025-10-20)</small>\n### Bug Fixes\n\n* **dev:** trim trailing slash before `server.fs.deny` check ([#20968](https://github.com/vitejs/vite/issues/20968)) ([f479cc5](https://github.com/vitejs/vite/commit/f479cc57c425ed41ceb434fecebd63931b1ed4ed))\n\n### Miscellaneous Chores\n\n* **deps:** update all non-major dependencies ([#20966](https://github.com/vitejs/vite/issues/20966)) ([6fb41a2](https://github.com/vitejs/vite/commit/6fb41a260bda443685e719ea4765d3faca3db944))\n\n### Code Refactoring\n\n* use subpath imports for types module reference ([#20921](https://github.com/vitejs/vite/issues/20921)) ([d0094af](https://github.com/vitejs/vite/commit/d0094af639d9ebbb51d4e00910b74f23eb8fe131))\n\n### Build System\n\n* remove cjs reference in files field ([#20945](https://github.com/vitejs/vite/issues/20945)) ([ef411ce](https://github.com/vitejs/vite/commit/ef411cee2696af3ba791879fdae9aad165f178b2))\n* remove hash from built filenames ([#20946](https://github.com/vitejs/vite/issues/20946)) ([a817307](https://github.com/vitejs/vite/commit/a81730754d655d1371ce0f4354af1c84e12f9f2d))\n\n## <small>[7.1.10](https://github.com/vitejs/vite/compare/v7.1.9...v7.1.10) (2025-10-14)</small>\n### Bug Fixes\n\n* **css:** avoid duplicate style for server rendered stylesheet link and client inline style during dev ([#20767](https://github.com/vitejs/vite/issues/20767)) ([3a92bc7](https://github.com/vitejs/vite/commit/3a92bc79b306a01b8aaf37f80b2239eaf6e488e7))\n* **css:** respect emitAssets when cssCodeSplit=false ([#20883](https://github.com/vitejs/vite/issues/20883)) ([d3e7eee](https://github.com/vitejs/vite/commit/d3e7eeefa91e1992f47694d16fe4dbe708c4d80e))\n* **deps:** update all non-major dependencies ([879de86](https://github.com/vitejs/vite/commit/879de86935a31b4e47ab907ddd859366518ce268))\n* **deps:** update all non-major dependencies ([#20894](https://github.com/vitejs/vite/issues/20894)) ([3213f90](https://github.com/vitejs/vite/commit/3213f90ff0d8f274bcec65f40aac6dfcff1ac244))\n* **dev:** allow aliases starting with `//` ([#20760](https://github.com/vitejs/vite/issues/20760)) ([b95fa2a](https://github.com/vitejs/vite/commit/b95fa2aa7564eda4c9f05ee7616a2dbada35e463))\n* **dev:** remove timestamp query consistently ([#20887](https://github.com/vitejs/vite/issues/20887)) ([6537d15](https://github.com/vitejs/vite/commit/6537d15591619d7e1cfc1e50599bec16cd88340f))\n* **esbuild:** inject esbuild helpers correctly for esbuild 0.25.9+ ([#20906](https://github.com/vitejs/vite/issues/20906)) ([446eb38](https://github.com/vitejs/vite/commit/446eb386329ef682d614c77958a542f2dc222880))\n* normalize path before calling `fileToBuiltUrl` ([#20898](https://github.com/vitejs/vite/issues/20898)) ([73b6d24](https://github.com/vitejs/vite/commit/73b6d243e0398ee5d8d44c7d24162f4a0f4b1cf1))\n* preserve original sourcemap file field when combining sourcemaps ([#20926](https://github.com/vitejs/vite/issues/20926)) ([c714776](https://github.com/vitejs/vite/commit/c714776aa1dcc24299a81c1495cbcbb1b1ef1dd3))\n\n### Documentation\n\n* correct `WebSocket` spelling ([#20890](https://github.com/vitejs/vite/issues/20890)) ([29e98dc](https://github.com/vitejs/vite/commit/29e98dc3efe35efbd978523367c05db7d2e7a278))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20923](https://github.com/vitejs/vite/issues/20923)) ([a5e3b06](https://github.com/vitejs/vite/commit/a5e3b064fa7ca981cb6f15f8e88806b36a99b8bf))\n\n## <small>[7.1.9](https://github.com/vitejs/vite/compare/v7.1.8...v7.1.9) (2025-10-03)</small>\n### Reverts\n\n* **server:** drain stdin when not interactive ([#20885](https://github.com/vitejs/vite/issues/20885)) ([12d72b0](https://github.com/vitejs/vite/commit/12d72b0538ef1540bfb0f1dd8a44b75deaa3464e))\n\n## <small>[7.1.8](https://github.com/vitejs/vite/compare/v7.1.7...v7.1.8) (2025-10-02)</small>\n### Bug Fixes\n\n* **css:** improve url escape characters handling ([#20847](https://github.com/vitejs/vite/issues/20847)) ([24a61a3](https://github.com/vitejs/vite/commit/24a61a3f5404279e91f7ceebf7449a5e874f9d56))\n* **deps:** update all non-major dependencies ([#20855](https://github.com/vitejs/vite/issues/20855)) ([788a183](https://github.com/vitejs/vite/commit/788a183afce57de13f5656f0cf42cdf6fdc3ebaa))\n* **deps:** update artichokie to 0.4.2 ([#20864](https://github.com/vitejs/vite/issues/20864)) ([e670799](https://github.com/vitejs/vite/commit/e670799e123dca78e1a63aeb06dbadade3d5ab51))\n* **dev:** skip JS responses for document requests ([#20866](https://github.com/vitejs/vite/issues/20866)) ([6bc6c4d](https://github.com/vitejs/vite/commit/6bc6c4dbc23501577d3919dc841454eb2eb14a54))\n* **glob:** fix HMR for array patterns with exclusions ([#20872](https://github.com/vitejs/vite/issues/20872)) ([63e040f](https://github.com/vitejs/vite/commit/63e040f1ca6b635a007eb40aa7c8b891e8cc5799))\n* keep ids for virtual modules as-is ([#20808](https://github.com/vitejs/vite/issues/20808)) ([d4eca98](https://github.com/vitejs/vite/commit/d4eca986d679c77bd449db20fd99d8255985b550))\n* **server:** drain stdin when not interactive ([#20837](https://github.com/vitejs/vite/issues/20837)) ([bb950e9](https://github.com/vitejs/vite/commit/bb950e92b372f9a52245e9542cf9d9700d23ef8c))\n* **server:** improve malformed URL handling in middlewares ([#20830](https://github.com/vitejs/vite/issues/20830)) ([d65a983](https://github.com/vitejs/vite/commit/d65a9831c984e562c5bf2b5f427de16f6e1bd931))\n\n### Documentation\n\n* **create-vite:** provide deno example ([#20747](https://github.com/vitejs/vite/issues/20747)) ([fdb758a](https://github.com/vitejs/vite/commit/fdb758a51796b1ab605437b2eee778a84e87e169))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20810](https://github.com/vitejs/vite/issues/20810)) ([ea68a88](https://github.com/vitejs/vite/commit/ea68a8868c7ee249213057f8a81c3f92a9839dde))\n* **deps:** update rolldown-related dependencies ([#20854](https://github.com/vitejs/vite/issues/20854)) ([4dd06fd](https://github.com/vitejs/vite/commit/4dd06fdc8d643059c2abf88188eae7c4877aab6e))\n* update url of `create-react-app` license ([#20865](https://github.com/vitejs/vite/issues/20865)) ([166a178](https://github.com/vitejs/vite/commit/166a178f45b6e48db27b5626559f5ec3358c2fb4))\n\n## <small>[7.1.7](https://github.com/vitejs/vite/compare/v7.1.6...v7.1.7) (2025-09-22)</small>\n### Bug Fixes\n\n* **build:** fix ssr environment `emitAssets: true` when `sharedConfigBuild: true` ([#20787](https://github.com/vitejs/vite/issues/20787)) ([4c4583c](https://github.com/vitejs/vite/commit/4c4583ce7a13306e0853901570c5d95517fe81da))\n* **client:** use CSP nonce when rendering error overlay ([#20791](https://github.com/vitejs/vite/issues/20791)) ([9bc9d12](https://github.com/vitejs/vite/commit/9bc9d1258f550e9d8f5e530cd27aecb1bee32bdb))\n* **deps:** update all non-major dependencies ([#20811](https://github.com/vitejs/vite/issues/20811)) ([9f2247c](https://github.com/vitejs/vite/commit/9f2247c066cac75746356c9391845235445a154b))\n* **glob:** handle glob imports from folders starting with dot ([#20800](https://github.com/vitejs/vite/issues/20800)) ([105abe8](https://github.com/vitejs/vite/commit/105abe87c412cf0f83859ba41fed869221cbb3e0))\n* **hmr:** trigger prune event when import is removed from non hmr module ([#20768](https://github.com/vitejs/vite/issues/20768)) ([9f32b1d](https://github.com/vitejs/vite/commit/9f32b1dc710991c53a9f665c8d0d6945f342bf92))\n* **hmr:** wait for `import.meta.hot.prune` callbacks to complete before running other HMRs ([#20698](https://github.com/vitejs/vite/issues/20698)) ([98a3484](https://github.com/vitejs/vite/commit/98a3484733443ee529870477a6ab6a03572e3cbc))\n\n## <small>[7.1.6](https://github.com/vitejs/vite/compare/v7.1.5...v7.1.6) (2025-09-18)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20773](https://github.com/vitejs/vite/issues/20773)) ([88af2ae](https://github.com/vitejs/vite/commit/88af2ae7df77160e7d11a9fa147a4967c8499f13))\n* **esbuild:** inject esbuild helper functions with minified `$` variables correctly ([#20761](https://github.com/vitejs/vite/issues/20761)) ([7e8e004](https://github.com/vitejs/vite/commit/7e8e0043d60379e11da481d9cc3c3556c9756ac0))\n* fallback terser to main thread when nameCache is provided ([#20750](https://github.com/vitejs/vite/issues/20750)) ([a679a64](https://github.com/vitejs/vite/commit/a679a643404c95556dda2670643e14eca9c585bd))\n* **types:** strict env typings fail when `skipLibCheck` is `false` ([#20755](https://github.com/vitejs/vite/issues/20755)) ([cc54e29](https://github.com/vitejs/vite/commit/cc54e294746d3eac868de96f85d98dd0fa0cda11))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20675](https://github.com/vitejs/vite/issues/20675)) ([a67bb5f](https://github.com/vitejs/vite/commit/a67bb5fbec5f3e42151dc7e3166858d0d33533de))\n* **deps:** update rolldown-related dependencies ([#20772](https://github.com/vitejs/vite/issues/20772)) ([d785e72](https://github.com/vitejs/vite/commit/d785e72f2ead705e8b2416c0a5097878fced3435))\n\n## <small>[7.1.5](https://github.com/vitejs/vite/compare/v7.1.4...v7.1.5) (2025-09-08)</small>\n### Bug Fixes\n\n* apply `fs.strict` check to HTML files ([#20736](https://github.com/vitejs/vite/issues/20736)) ([14015d7](https://github.com/vitejs/vite/commit/14015d794f69accba68798bd0e15135bc51c9c1e))\n* **deps:** update all non-major dependencies ([#20732](https://github.com/vitejs/vite/issues/20732)) ([122bfba](https://github.com/vitejs/vite/commit/122bfbabeb1f095ce7cabd30893e5531e9a007c4))\n* upgrade sirv to 3.0.2 ([#20735](https://github.com/vitejs/vite/issues/20735)) ([09f2b52](https://github.com/vitejs/vite/commit/09f2b52e8d5907f26602653caf41b3a56692600d))\n\n## <small>[7.1.4](https://github.com/vitejs/vite/compare/v7.1.3...v7.1.4) (2025-09-01)</small>\n### Bug Fixes\n\n* add missing awaits ([#20697](https://github.com/vitejs/vite/issues/20697)) ([79d10ed](https://github.com/vitejs/vite/commit/79d10ed6341ba7a751d007b7ad113a9b8be9c853))\n* **deps:** update all non-major dependencies ([#20676](https://github.com/vitejs/vite/issues/20676)) ([5a274b2](https://github.com/vitejs/vite/commit/5a274b29df83744cf0ce4dafd94029d2a9e01135))\n* **deps:** update all non-major dependencies ([#20709](https://github.com/vitejs/vite/issues/20709)) ([0401feb](https://github.com/vitejs/vite/commit/0401feba17e60bd7e976c5643128a0da49670a83))\n* pass rollup watch options when building in watch mode ([#20674](https://github.com/vitejs/vite/issues/20674)) ([f367453](https://github.com/vitejs/vite/commit/f367453ca2825bc8a390d41c5d13b161756f2b41))\n\n### Miscellaneous Chores\n\n* remove unused constants entry from rolldown.config.ts ([#20710](https://github.com/vitejs/vite/issues/20710)) ([537fcf9](https://github.com/vitejs/vite/commit/537fcf91862a1bf51e70ce6fe9b414319dd3a675))\n\n### Code Refactoring\n\n* remove unnecessary `minify` parameter from `finalizeCss` ([#20701](https://github.com/vitejs/vite/issues/20701)) ([8099582](https://github.com/vitejs/vite/commit/8099582e5364f907f2bc6cb8e2d52ae0c4d937e4))\n\n## <small>[7.1.3](https://github.com/vitejs/vite/compare/v7.1.2...v7.1.3) (2025-08-19)</small>\n### Features\n\n* **cli:** add Node.js version warning for unsupported versions ([#20638](https://github.com/vitejs/vite/issues/20638)) ([a1be1bf](https://github.com/vitejs/vite/commit/a1be1bf0905b9086e5f1370c63d76a7fa4a195ec))\n* generate code frame for parse errors thrown by terser ([#20642](https://github.com/vitejs/vite/issues/20642)) ([a9ba017](https://github.com/vitejs/vite/commit/a9ba0174a58b949373d6b4240bc69180dff0b780))\n* support long lines in `generateCodeFrame` ([#20640](https://github.com/vitejs/vite/issues/20640)) ([1559577](https://github.com/vitejs/vite/commit/15595773170c2a07f2efdccee05964fb87c19ae6))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20634](https://github.com/vitejs/vite/issues/20634)) ([4851cab](https://github.com/vitejs/vite/commit/4851cab3ba818b5f0f82eef3796b61d4b12768f1))\n* **optimizer:** incorrect incompatible error ([#20439](https://github.com/vitejs/vite/issues/20439)) ([446fe83](https://github.com/vitejs/vite/commit/446fe83033686dd38d13b786a217b8277b5c5f09))\n* support multiline new URL(..., import.meta.url) expressions ([#20644](https://github.com/vitejs/vite/issues/20644)) ([9ccf142](https://github.com/vitejs/vite/commit/9ccf142764d48292aa33e5ca6f020a7d55b97f61))\n\n### Performance Improvements\n\n* **cli:** dynamically import `resolveConfig` ([#20646](https://github.com/vitejs/vite/issues/20646)) ([f691f57](https://github.com/vitejs/vite/commit/f691f57e46118328e00174160ceab2101b7256ca))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20633](https://github.com/vitejs/vite/issues/20633)) ([98b92e8](https://github.com/vitejs/vite/commit/98b92e8c4b10ae87c48292a8ac09b01ca81a02cf))\n\n### Code Refactoring\n\n* replace startsWith with strict equality ([#20603](https://github.com/vitejs/vite/issues/20603)) ([42816de](https://github.com/vitejs/vite/commit/42816dee0e177dded1c9de4d9099089ec4acef96))\n* use `import` in worker threads ([#20641](https://github.com/vitejs/vite/issues/20641)) ([530687a](https://github.com/vitejs/vite/commit/530687a344c51daf3115d1c134586bbde58356e0))\n\n### Tests\n\n* remove `checkNodeVersion` test ([#20647](https://github.com/vitejs/vite/issues/20647)) ([731d3e6](https://github.com/vitejs/vite/commit/731d3e61f444f6c5e611f67b531416ed6450f90f))\n\n## <small>[7.1.2](https://github.com/vitejs/vite/compare/v7.1.1...v7.1.2) (2025-08-12)</small>\n### Bug Fixes\n\n* **client:** add `[vite]` prefixes to debug logs ([#20595](https://github.com/vitejs/vite/issues/20595)) ([7cdef61](https://github.com/vitejs/vite/commit/7cdef612a65da5363905723f77516b6745ac9a94))\n* **config:** make debugger work with bundle loader ([#20573](https://github.com/vitejs/vite/issues/20573)) ([c583927](https://github.com/vitejs/vite/commit/c583927bee657f15f63fdf80468fbe6a74eacdec))\n* **deps:** update all non-major dependencies ([#20587](https://github.com/vitejs/vite/issues/20587)) ([20d4817](https://github.com/vitejs/vite/commit/20d48172a0352d32f766b3c878d52a8944fdbf6e))\n* don't consider ids with `npm:` prefix as a built-in module ([#20558](https://github.com/vitejs/vite/issues/20558)) ([ab33803](https://github.com/vitejs/vite/commit/ab33803f2c831a82ddee637ad62e0c4ceeb663f1))\n* **hmr:** watch non-inlined assets referenced by CSS ([#20581](https://github.com/vitejs/vite/issues/20581)) ([b7d494b](https://github.com/vitejs/vite/commit/b7d494bf60af3ef7316d87266bb3ebf56617d5fd))\n* **module-runner:** prevent crash when sourceMappingURL pattern appears in string literals ([#20554](https://github.com/vitejs/vite/issues/20554)) ([2770478](https://github.com/vitejs/vite/commit/2770478d1c190d3e3de34ef9a3d2c493c06e9933))\n\n### Miscellaneous Chores\n\n* **deps:** migrate to `@jridgewell/remapping` from `@ampproject/remapping` ([#20577](https://github.com/vitejs/vite/issues/20577)) ([0a6048a](https://github.com/vitejs/vite/commit/0a6048aba4523f451edf29ae4037d252cc963815))\n* **deps:** update rolldown-related dependencies ([#20586](https://github.com/vitejs/vite/issues/20586)) ([77632c5](https://github.com/vitejs/vite/commit/77632c55db51cd6d03bcf24a1cef8d21058100a3))\n\n## <small>[7.1.1](https://github.com/vitejs/vite/compare/v7.1.0...v7.1.1) (2025-08-08)</small>\n### Bug Fixes\n\n* **deps:** update `launch-editor-middleware` ([#20569](https://github.com/vitejs/vite/issues/20569)) ([826b394](https://github.com/vitejs/vite/commit/826b394e0efd033d2fe88126fe9a28da9573bd8f))\n\n### Miscellaneous Chores\n\n* fix changelog beta links ([#20561](https://github.com/vitejs/vite/issues/20561)) ([2e0c21a](https://github.com/vitejs/vite/commit/2e0c21a07ec5ca7ed5eaa1b6a7d44682fa467a06))\n* update 7.1 changelog ([#20560](https://github.com/vitejs/vite/issues/20560)) ([d8869b8](https://github.com/vitejs/vite/commit/d8869b84208879c7aa6a0268ec073a34760c0d80))\n\n## [7.1.0](https://github.com/vitejs/vite/compare/v7.1.0-beta.1...v7.1.0) (2025-08-07)\n### Features\n\n* support files with more than 1000 lines by `generateCodeFrame` ([#20508](https://github.com/vitejs/vite/issues/20508)) ([e7d0b2a](https://github.com/vitejs/vite/commit/e7d0b2afa56840dabbbad10015dc04083caaf248))\n* add `import.meta.main` support in config (bundle config loader) ([#20516](https://github.com/vitejs/vite/issues/20516)) ([5d3e3c2](https://github.com/vitejs/vite/commit/5d3e3c2ae5a2174941fd09fd7842794a287c3ab7))\n* **optimizer:** improve dependency optimization error messages with esbuild formatMessages ([#20525](https://github.com/vitejs/vite/issues/20525)) ([d17cfed](https://github.com/vitejs/vite/commit/d17cfeda0741e4476570700a00b7b37917c97700))\n* **ssr:** add `import.meta.main` support for Node.js module runner ([#20517](https://github.com/vitejs/vite/issues/20517)) ([794a8f2](https://github.com/vitejs/vite/commit/794a8f230218a3b1e148defc5a2d7a67409177ff))\n* add `future: 'warn'` ([#20473](https://github.com/vitejs/vite/issues/20473)) ([e6aaf17](https://github.com/vitejs/vite/commit/e6aaf17ca21544572941957ce71bd8dbdc94e402))\n* add `removeServerPluginContainer` future deprecation ([#20437](https://github.com/vitejs/vite/issues/20437)) ([c1279e7](https://github.com/vitejs/vite/commit/c1279e75401ac6ea1d0678da88414a76ff36b6fe))\n* add `removeServerReloadModule` future deprecation ([#20436](https://github.com/vitejs/vite/issues/20436)) ([6970d17](https://github.com/vitejs/vite/commit/6970d1740cebd56af696abf60f30adb0c060f578))\n* add `server.warmupRequest` to future deprecation ([#20431](https://github.com/vitejs/vite/issues/20431)) ([8ad388a](https://github.com/vitejs/vite/commit/8ad388aeab0dc79e4bc14859b91174427805a46b))\n* add `ssrFixStacktrace` / `ssrRewriteStacktrace` to `removeSsrLoadModule` future deprecation ([#20435](https://github.com/vitejs/vite/issues/20435)) ([8c8f587](https://github.com/vitejs/vite/commit/8c8f5879ead251705c2c363f5b8b94f618fbf374))\n* **client:** ping from SharedWorker ([#19057](https://github.com/vitejs/vite/issues/19057)) ([5c97c22](https://github.com/vitejs/vite/commit/5c97c22548476e5f80856ece1d80b9234a7e6ecb))\n* **dev:** add `this.fs` support ([#20301](https://github.com/vitejs/vite/issues/20301)) ([0fe3f2f](https://github.com/vitejs/vite/commit/0fe3f2f7c325c5990f1059c28b66b24e1b8fd5d3))\n* export `defaultExternalConditions` ([#20279](https://github.com/vitejs/vite/issues/20279)) ([344d302](https://github.com/vitejs/vite/commit/344d30243b107852b133175e947a0410ea703f00))\n* implement `removePluginHookSsrArgument` future deprecation ([#20433](https://github.com/vitejs/vite/issues/20433)) ([95927d9](https://github.com/vitejs/vite/commit/95927d9c0ba1cb0b3bd8c900f039c099f8e29f90))\n* implement `removeServerHot` future deprecation ([#20434](https://github.com/vitejs/vite/issues/20434)) ([259f45d](https://github.com/vitejs/vite/commit/259f45d0698a184d6ecc352b610001fa1acdcee1))\n* resolve server URLs before calling other listeners ([#19981](https://github.com/vitejs/vite/issues/19981)) ([45f6443](https://github.com/vitejs/vite/commit/45f6443a935258d8eee62874f0695b8c1c60a481))\n* **ssr:** resolve externalized packages with `resolve.externalConditions` and add `module-sync` to default external condition ([#20409](https://github.com/vitejs/vite/issues/20409)) ([c669c52](https://github.com/vitejs/vite/commit/c669c524e6008a4902169f4b2f865e892297acf3))\n* **ssr:** support `import.meta.resolve` in module runner ([#20260](https://github.com/vitejs/vite/issues/20260)) ([62835f7](https://github.com/vitejs/vite/commit/62835f7c06d37802f0bc2abbf58bbaeaa8c73ce5))\n\n### Bug Fixes\n\n* **css:** avoid warnings for `image-set` containing `__VITE_ASSET__` ([#20520](https://github.com/vitejs/vite/issues/20520)) ([f1a2635](https://github.com/vitejs/vite/commit/f1a2635e6977a3eda681bec036f64f07686dad0d))\n* **css:** empty CSS entry points should generate CSS files, not JS files ([#20518](https://github.com/vitejs/vite/issues/20518)) ([bac9f3e](https://github.com/vitejs/vite/commit/bac9f3ecf84ae5c5add6ef224ae057508247f89e))\n* **dev:** denied request stalled when requested concurrently ([#20503](https://github.com/vitejs/vite/issues/20503)) ([64a52e7](https://github.com/vitejs/vite/commit/64a52e70d9250b16aa81ce2df27c23fe56907257))\n* **manifest:** initialize `entryCssAssetFileNames` as an empty Set ([#20542](https://github.com/vitejs/vite/issues/20542)) ([6a46cda](https://github.com/vitejs/vite/commit/6a46cdac5dece70296d1179640958deeeb2e6c19))\n* skip prepareOutDirPlugin in workers ([#20556](https://github.com/vitejs/vite/issues/20556)) ([97d5111](https://github.com/vitejs/vite/commit/97d5111645a395dae48b16b110bc76c1ee8956c8))\n* **asset:** only watch existing files for `new URL(, import.meta.url)` ([#20507](https://github.com/vitejs/vite/issues/20507)) ([1b211fd](https://github.com/vitejs/vite/commit/1b211fd1beccd0fc13bec700815abaa9f54147e8))\n* **client:** keep ping on WS constructor error ([#20512](https://github.com/vitejs/vite/issues/20512)) ([3676da5](https://github.com/vitejs/vite/commit/3676da5bc5b2b69b28619b8521fca94d30468fe5))\n* **deps:** update all non-major dependencies ([#20537](https://github.com/vitejs/vite/issues/20537)) ([fc9a9d3](https://github.com/vitejs/vite/commit/fc9a9d3f1493caa3d614f64e0a61fd5684f0928b))\n* don't resolve as relative for specifiers starting with a dot ([#20528](https://github.com/vitejs/vite/issues/20528)) ([c5a10ec](https://github.com/vitejs/vite/commit/c5a10ec004130bec17cf42760b76d1d404008fa3))\n* **html:** allow control character in input stream ([#20483](https://github.com/vitejs/vite/issues/20483)) ([c12a4a7](https://github.com/vitejs/vite/commit/c12a4a76a299237a0a13b885c72fdda6e4a3c9b7))\n* merge old and new `noExternal: true` correctly ([#20502](https://github.com/vitejs/vite/issues/20502)) ([9ebe4a5](https://github.com/vitejs/vite/commit/9ebe4a514a2e48e3fe194f16b0556a45ff38077a))\n* **deps:** update all non-major dependencies ([#20489](https://github.com/vitejs/vite/issues/20489)) ([f6aa04a](https://github.com/vitejs/vite/commit/f6aa04a52d486c8881f666c450caa3dab3c6bba1))\n* **dev:** denied requests overly ([#20410](https://github.com/vitejs/vite/issues/20410)) ([4be5270](https://github.com/vitejs/vite/commit/4be5270b27f7e6323f1771974b4b3520d86600e4))\n* **hmr:** register css deps as `type: asset` ([#20391](https://github.com/vitejs/vite/issues/20391)) ([7eac8dd](https://github.com/vitejs/vite/commit/7eac8ddb65033b8c001d6c6bc46aaeeefb79680a))\n* **optimizer:** discover correct jsx runtime during scan ([#20495](https://github.com/vitejs/vite/issues/20495)) ([10d48bb](https://github.com/vitejs/vite/commit/10d48bb2e30824d217e415a58cea9e69c2820c2a))\n* **preview:** set correct host for `resolvedUrls` ([#20496](https://github.com/vitejs/vite/issues/20496)) ([62b3e0d](https://github.com/vitejs/vite/commit/62b3e0d95c143e2f8b4e88d99c381d23663025ee))\n* **worker:** resolve WebKit compat with inline workers by deferring blob URL revocation ([#20460](https://github.com/vitejs/vite/issues/20460)) ([8033e5b](https://github.com/vitejs/vite/commit/8033e5bf8d3ff43995d0620490ed8739c59171dd))\n\n### Performance Improvements\n\n* **client:** reduce reload debounce ([#20429](https://github.com/vitejs/vite/issues/20429)) ([22ad43b](https://github.com/vitejs/vite/commit/22ad43b4bf2435efe78a65b84e8469b23521900a))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20536](https://github.com/vitejs/vite/issues/20536)) ([8be2787](https://github.com/vitejs/vite/commit/8be278748a92b128c49a24619d8d537dd2b08ceb))\n* **deps:** update dependency parse5 to v8 ([#20490](https://github.com/vitejs/vite/issues/20490)) ([744582d](https://github.com/vitejs/vite/commit/744582d0187c50045fb6cf229e3fab13093af08e))\n* format ([f20addc](https://github.com/vitejs/vite/commit/f20addc5363058f5fd797e5bc71fab3877ed0a76))\n* stablize `cssScopeTo` ([#19592](https://github.com/vitejs/vite/issues/19592)) ([ced1343](https://github.com/vitejs/vite/commit/ced13433fb71e2101850a4da1b0ef70cbc38b804))\n\n### Code Refactoring\n\n* use hook filters in the worker plugin ([#20527](https://github.com/vitejs/vite/issues/20527)) ([958cdf2](https://github.com/vitejs/vite/commit/958cdf24f882be6953ca20912dd30c84213b069b))\n* extract prepareOutDir as a plugin ([#20373](https://github.com/vitejs/vite/issues/20373)) ([2c4af1f](https://github.com/vitejs/vite/commit/2c4af1f90b3ac98df6f4585a329528e6bd850462))\n* extract resolve rollup options ([#20375](https://github.com/vitejs/vite/issues/20375)) ([61a9778](https://github.com/vitejs/vite/commit/61a97780e6c54adb87345cb8c1f5f0d8e9ca5c05))\n* rewrite openchrome.applescript to JXA ([#20424](https://github.com/vitejs/vite/issues/20424)) ([7979f9d](https://github.com/vitejs/vite/commit/7979f9da555aa16bd221b32ea78ce8cb5292fac4))\n* use `http-proxy-3` ([#20402](https://github.com/vitejs/vite/issues/20402)) ([26d9872](https://github.com/vitejs/vite/commit/26d987232aad389733a7635b92122bb1d78dfcad))\n* use hook filters in internal plugins ([#20358](https://github.com/vitejs/vite/issues/20358)) ([f19c4d7](https://github.com/vitejs/vite/commit/f19c4d72de142814994e30120aa4ad57552cb874))\n* use hook filters in internal resolve plugin ([#20480](https://github.com/vitejs/vite/issues/20480)) ([acd2a13](https://github.com/vitejs/vite/commit/acd2a13c2d80e8c5c721bcf9738dfc03346cbfe1))\n\n### Tests\n\n* detect ts support via `process.features` ([#20544](https://github.com/vitejs/vite/issues/20544)) ([856d3f0](https://github.com/vitejs/vite/commit/856d3f06e6889979f630c8453fa385f01d8adaba))\n* fix unimportant errors in test-unit ([#20545](https://github.com/vitejs/vite/issues/20545)) ([1f23554](https://github.com/vitejs/vite/commit/1f235545b14a51d41b19a49da4a7e3a8e8eb5d10))\n\n### Beta Changelogs\n\n#### [7.1.0-beta.1](https://github.com/vitejs/vite/compare/v7.1.0-beta.0...v7.1.0-beta.1) (2025-08-05)\n\nSee [7.1.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v7.1.0-beta.1/packages/vite/CHANGELOG.md)\n\n#### [7.1.0-beta.0](https://github.com/vitejs/vite/compare/v7.0.6...v7.1.0-beta.0) (2025-07-30)\n\nSee [7.1.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v7.1.0-beta.0/packages/vite/CHANGELOG.md)\n\n\n## <small>[7.0.6](https://github.com/vitejs/vite/compare/v7.0.5...v7.0.6) (2025-07-24)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20442](https://github.com/vitejs/vite/issues/20442)) ([e49f505](https://github.com/vitejs/vite/commit/e49f50599d852eec644e79b074b4648e2dff1e5d))\n* **dev:** incorrect sourcemap when optimized CJS is imported ([#20458](https://github.com/vitejs/vite/issues/20458)) ([ead2dec](https://github.com/vitejs/vite/commit/ead2dec74170ad26db8a18bbd68f075efaceb0e3))\n* **module-runner:** normalize file:// on windows ([#20449](https://github.com/vitejs/vite/issues/20449)) ([1c9cb49](https://github.com/vitejs/vite/commit/1c9cb493f0467c463113d301b00ce07cbe4b6f58))\n* respond with correct headers and status code for HEAD requests ([#20421](https://github.com/vitejs/vite/issues/20421)) ([23d04fc](https://github.com/vitejs/vite/commit/23d04fc2d8a4fcf7c2011418693d6000748aa655))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20441](https://github.com/vitejs/vite/issues/20441)) ([f689d61](https://github.com/vitejs/vite/commit/f689d613429ae9452c74f8bc482d8cc2584ea6b8))\n* remove some files from prettier ignore ([#20459](https://github.com/vitejs/vite/issues/20459)) ([8403f69](https://github.com/vitejs/vite/commit/8403f69551131b5c39bfaf242ffac2e5efcd1dd6))\n\n### Code Refactoring\n\n* use environment transform request ([#20430](https://github.com/vitejs/vite/issues/20430)) ([24e6a0c](https://github.com/vitejs/vite/commit/24e6a0c3165557396db6ab59d3001e037c76ce32))\n\n## <small>[7.0.5](https://github.com/vitejs/vite/compare/v7.0.4...v7.0.5) (2025-07-17)</small>\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20406](https://github.com/vitejs/vite/issues/20406)) ([1a1cc8a](https://github.com/vitejs/vite/commit/1a1cc8a435a21996255b3e5cc75ed4680de2a7f3))\n* remove special handling for `Accept: text/html` ([#20376](https://github.com/vitejs/vite/issues/20376)) ([c9614b9](https://github.com/vitejs/vite/commit/c9614b9c378be4a32e84f37be71a8becce52af7b))\n* watch assets referenced by `new URL(, import.meta.url)` ([#20382](https://github.com/vitejs/vite/issues/20382)) ([6bc8bf6](https://github.com/vitejs/vite/commit/6bc8bf634d4a2c9915da9813963dd80a4186daeb))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency rolldown to ^1.0.0-beta.27 ([#20405](https://github.com/vitejs/vite/issues/20405)) ([1165667](https://github.com/vitejs/vite/commit/1165667b271fb1fb76584278e72a85d564c9bb09))\n\n### Code Refactoring\n\n* use `foo.endsWith(\"bar\")` instead of `/bar$/.test(foo)` ([#20413](https://github.com/vitejs/vite/issues/20413)) ([862e192](https://github.com/vitejs/vite/commit/862e192d21f66039635a998724bdc6b94fd293a0))\n\n## <small>[7.0.4](https://github.com/vitejs/vite/compare/v7.0.3...v7.0.4) (2025-07-10)</small>\n### Bug Fixes\n\n* allow resolving bare specifiers to relative paths for entries ([#20379](https://github.com/vitejs/vite/issues/20379)) ([324669c](https://github.com/vitejs/vite/commit/324669c2d84966a822b1b2c134c9830a90bed271))\n\n### Build System\n\n* remove `@oxc-project/runtime` devDep ([#20389](https://github.com/vitejs/vite/issues/20389)) ([5e29602](https://github.com/vitejs/vite/commit/5e29602f6fe4bf28f6e7c869a214dee6957f855c))\n\n## <small>[7.0.3](https://github.com/vitejs/vite/compare/v7.0.2...v7.0.3) (2025-07-08)</small>\n### Bug Fixes\n\n* **client:** protect against window being defined but addEv undefined ([#20359](https://github.com/vitejs/vite/issues/20359)) ([31d1467](https://github.com/vitejs/vite/commit/31d1467cf0da1e1dca623e6df0d345b30fae0c3d))\n* **define:** replace optional values ([#20338](https://github.com/vitejs/vite/issues/20338)) ([9465ae1](https://github.com/vitejs/vite/commit/9465ae1378b456e08659a22286bee6bce8edeedc))\n* **deps:** update all non-major dependencies ([#20366](https://github.com/vitejs/vite/issues/20366)) ([43ac73d](https://github.com/vitejs/vite/commit/43ac73da27b3907c701e95e6a7d28fde659729ec))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency dotenv to v17 ([#20325](https://github.com/vitejs/vite/issues/20325)) ([45040d4](https://github.com/vitejs/vite/commit/45040d48076302eeb101f8d07bbcd04758fde8a4))\n* **deps:** update dependency rolldown to ^1.0.0-beta.24 ([#20365](https://github.com/vitejs/vite/issues/20365)) ([5ab25e7](https://github.com/vitejs/vite/commit/5ab25e73a2ea2a2e2c0469350288a183dfb57030))\n* use `n/prefer-node-protocol` rule ([#20368](https://github.com/vitejs/vite/issues/20368)) ([38bb268](https://github.com/vitejs/vite/commit/38bb268cde15541321f36016e77d61eecb707298))\n\n### Code Refactoring\n\n* minor changes to reduce diff between normal Vite and rolldown-vite ([#20354](https://github.com/vitejs/vite/issues/20354)) ([2e8050e](https://github.com/vitejs/vite/commit/2e8050e4cd8835673baf07375b7db35128144222))\n\n## <small>[7.0.2](https://github.com/vitejs/vite/compare/v7.0.1...v7.0.2) (2025-07-04)</small>\n### Bug Fixes\n\n* **css:** resolve relative paths in sass, revert [#20300](https://github.com/vitejs/vite/issues/20300) ([#20349](https://github.com/vitejs/vite/issues/20349)) ([db8bd41](https://github.com/vitejs/vite/commit/db8bd412a8b783fe8e9f82d1a822b0534abbf5a3))\n\n## <small>[7.0.1](https://github.com/vitejs/vite/compare/v7.0.0...v7.0.1) (2025-07-03)</small>\n### Bug Fixes\n\n* **css:** skip resolving resolved paths in sass ([#20300](https://github.com/vitejs/vite/issues/20300)) ([ac528a4](https://github.com/vitejs/vite/commit/ac528a44c384fefb6f10c3f531df93b5ac39324c))\n* **deps:** update all non-major dependencies ([#20324](https://github.com/vitejs/vite/issues/20324)) ([3e81af3](https://github.com/vitejs/vite/commit/3e81af38a80c7617aba6bf3300d8b4267570f9cf))\n* **types:** add a global interface for Worker ([#20243](https://github.com/vitejs/vite/issues/20243)) ([37bdfc1](https://github.com/vitejs/vite/commit/37bdfc18f4c5bed053a38c5d717df33036acdd62))\n\n### Miscellaneous Chores\n\n* **deps:** update rolldown-related dependencies ([#20323](https://github.com/vitejs/vite/issues/20323)) ([30d2f1b](https://github.com/vitejs/vite/commit/30d2f1b38c72387ffdca3ee4746730959a020b59))\n* fix typos and grammatical errors across documentation and comments ([#20337](https://github.com/vitejs/vite/issues/20337)) ([c1c951d](https://github.com/vitejs/vite/commit/c1c951dcc32ec9f133b03ebbceddd749fc14f1e9))\n* group commits by category in changelog ([#20310](https://github.com/vitejs/vite/issues/20310)) ([41e83f6](https://github.com/vitejs/vite/commit/41e83f62b1adb65f5af4c1ec006de1c845437edc))\n* rearrange 7.0 changelog ([#20280](https://github.com/vitejs/vite/issues/20280)) ([eafd28a](https://github.com/vitejs/vite/commit/eafd28ac88d5908cbc3e0a047ed7a12094386436))\n\n## [7.0.0](https://github.com/vitejs/vite/compare/v7.0.0-beta.2...v7.0.0) (2025-06-24)\n\n![Vite 7 is out!](../../docs/public/og-image-announcing-vite7.png)\n\nToday, we're excited to announce the release of the next Vite major:\n\n- **[Vite 7.0 announcement blog post](https://vite.dev/blog/announcing-vite7.html)**\n- [Docs](https://vite.dev/) (translations: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/), [فارسی](https://fa.vite.dev/))\n- [Migration Guide](https://vite.dev/guide/migration.html)\n\n### ⚠ BREAKING CHANGES\n\n* **ssr:** don't access `Object` variable in ssr transformed code (#19996)\n* remove `experimental.skipSsrTransform` option (#20038)\n* remove `HotBroadcaster` (#19988)\n* **css:** always use sass compiler API (#19978)\n* bump `build.target` and name it `baseline-widely-available` (#20007)\n* bump required node version to 20.19+, 22.12+ and remove cjs build (#20032)\n* **css:** remove sass legacy API support (#19977)\n* remove deprecated `HotBroadcaster` related types (#19987)\n* remove deprecated no-op type only properties (#19985)\n* remove node 18 support (#19972)\n* remove deprecated hook-level `enforce`/`transform` from `transformIndexHtml` hook (#19349)\n* remove deprecated splitVendorChunkPlugin (#19255)\n\n### Features\n\n* **types:** use terser types from terser package ([#20274](https://github.com/vitejs/vite/issues/20274)) ([a5799fa](https://github.com/vitejs/vite/commit/a5799fa74c6190ecbb2da3d280136ff32463afc6))\n* apply some middlewares before `configurePreviewServer` hook ([#20224](https://github.com/vitejs/vite/issues/20224)) ([b989c42](https://github.com/vitejs/vite/commit/b989c42cf84378e6cb93970de739941f0d56d6f6))\n* apply some middlewares before `configureServer` hook ([#20222](https://github.com/vitejs/vite/issues/20222)) ([f5cc4c0](https://github.com/vitejs/vite/commit/f5cc4c0ded337670b439e51bc95f173e2b5cf9ad))\n* add base option to import.meta.glob ([#20163](https://github.com/vitejs/vite/issues/20163)) ([253d6c6](https://github.com/vitejs/vite/commit/253d6c6df2ebe3c4a88dabb6cec000128681561f))\n* add `this.meta.viteVersion` ([#20088](https://github.com/vitejs/vite/issues/20088)) ([f55bf41](https://github.com/vitejs/vite/commit/f55bf41e91f8dfe829a46e58f0035b19c8ab6a25))\n* allow passing down resolved config to vite's `createServer` ([#19894](https://github.com/vitejs/vite/issues/19894)) ([c1ae9bd](https://github.com/vitejs/vite/commit/c1ae9bd4a0542b4703ae7766ad61d072e8b833bd))\n* buildApp hook ([#19971](https://github.com/vitejs/vite/issues/19971)) ([5da659d](https://github.com/vitejs/vite/commit/5da659de902f0a2d6d8beefbf269128383b63887))\n* **build:** provide names for asset entrypoints ([#19912](https://github.com/vitejs/vite/issues/19912)) ([c4e01dc](https://github.com/vitejs/vite/commit/c4e01dc5ab0f1708383c39d28ce62e12b8f374fc))\n* bump `build.target` and name it `baseline-widely-available` ([#20007](https://github.com/vitejs/vite/issues/20007)) ([4a8aa82](https://github.com/vitejs/vite/commit/4a8aa82556eb2b9e54673a6aac77873e0eb27fa9))\n* **client:** support opening fileURL in editor ([#20040](https://github.com/vitejs/vite/issues/20040)) ([1bde4d2](https://github.com/vitejs/vite/commit/1bde4d25243cd9beaadb01413e896fef562626ef))\n* make PluginContext available for Vite-specific hooks ([#19936](https://github.com/vitejs/vite/issues/19936)) ([7063839](https://github.com/vitejs/vite/commit/7063839d47dfd4ac6be1247ba68e414ffe287b00))\n* resolve environments plugins at config time ([#20120](https://github.com/vitejs/vite/issues/20120)) ([f6a28d5](https://github.com/vitejs/vite/commit/f6a28d5f792ba5cc4dc236e3e6edd05199cabcc8))\n* stabilize `css.preprocessorMaxWorkers` and default to `true` ([#19992](https://github.com/vitejs/vite/issues/19992)) ([70aee13](https://github.com/vitejs/vite/commit/70aee139ea802478bad56e5e441f187140bcf0cc))\n* stabilize `optimizeDeps.noDiscovery` ([#19984](https://github.com/vitejs/vite/issues/19984)) ([6d2dcb4](https://github.com/vitejs/vite/commit/6d2dcb494db9f40565f11b50bdbb8c1b7245697d))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#20271](https://github.com/vitejs/vite/issues/20271)) ([6b64d63](https://github.com/vitejs/vite/commit/6b64d63d700154de2c00270300b671cef8863708))\n* keep `import.meta.url` in bundled Vite ([#20235](https://github.com/vitejs/vite/issues/20235)) ([3bf3a8a](https://github.com/vitejs/vite/commit/3bf3a8ab00e5a0dfab0bb5741cb871ea30b72651))\n* **module-runner:** export `ssrExportNameKey` ([#20266](https://github.com/vitejs/vite/issues/20266)) ([ac302a7](https://github.com/vitejs/vite/commit/ac302a729062dbfc67f762b3c4af46b7893c214f))\n* **module-runner:** expose `normalizeModuleId` ([#20277](https://github.com/vitejs/vite/issues/20277)) ([9b98dcb](https://github.com/vitejs/vite/commit/9b98dcbf75546240e1609185828e18a77bac8c8d))\n* **deps:** update all non-major dependencies ([#20181](https://github.com/vitejs/vite/issues/20181)) ([d91d4f7](https://github.com/vitejs/vite/commit/d91d4f7ad55edbcb4a51fc23376cbff89f776d30))\n* **deps:** update all non-major dependencies ([#20212](https://github.com/vitejs/vite/issues/20212)) ([a80339b](https://github.com/vitejs/vite/commit/a80339b1798607dd7389f42964272181cf9eb453))\n* align dynamic import detection ([#20115](https://github.com/vitejs/vite/issues/20115)) ([1ea2222](https://github.com/vitejs/vite/commit/1ea2222302f128c4000289683480d8311ea34223))\n* applyToEnvironment after configResolved ([#20170](https://github.com/vitejs/vite/issues/20170)) ([a330b80](https://github.com/vitejs/vite/commit/a330b805b0733fadd1f7d586218c2aafcbb41a7f))\n* **deps:** update all non-major dependencies ([#20141](https://github.com/vitejs/vite/issues/20141)) ([89ca65b](https://github.com/vitejs/vite/commit/89ca65ba1d849046dccdea52e9eca980f331be26))\n* handle dynamic import with `.then(m => m.a)` ([#20117](https://github.com/vitejs/vite/issues/20117)) ([7b7410a](https://github.com/vitejs/vite/commit/7b7410abab7c95880d943e46bd1a16dcb1a893fc))\n* **hmr:** use monotonicDateNow for timestamp ([#20158](https://github.com/vitejs/vite/issues/20158)) ([8d26785](https://github.com/vitejs/vite/commit/8d26785b8c3f5295ca0c1519dda1ddae9096fc73))\n* **optimizer:** align relative `build.rollupOptions.input` resolution with rollup ([#20080](https://github.com/vitejs/vite/issues/20080)) ([9759c29](https://github.com/vitejs/vite/commit/9759c29a8985da1a51de452d741850f0bf2ef7ef))\n* **ssr:** don't access `Object` variable in ssr transformed code ([#19996](https://github.com/vitejs/vite/issues/19996)) ([fceff60](https://github.com/vitejs/vite/commit/fceff60dc81730f7768b57f14e7a112facff387d))\n* **types:** prefer sass-embedded types over sass types for `preprocessorOptions.sass` (fix [#20150](https://github.com/vitejs/vite/issues/20150)) ([#20166](https://github.com/vitejs/vite/issues/20166)) ([7db56be](https://github.com/vitejs/vite/commit/7db56be237dd1e1e875518475421d5c90cf950da))\n* virtual svg module ([#20144](https://github.com/vitejs/vite/issues/20144)) ([7dfcb31](https://github.com/vitejs/vite/commit/7dfcb316ee64aca0a98a1d2905deb1dfd113ae6d))\n* **client:** render the last part of the stacktrace ([#20039](https://github.com/vitejs/vite/issues/20039)) ([c7c1743](https://github.com/vitejs/vite/commit/c7c17434968848f1471179c10a5fc9d2804add8b))\n* **cli:** make `cleanGlobalCLIOptions()` clean `--force` ([#19999](https://github.com/vitejs/vite/issues/19999)) ([d4a171a](https://github.com/vitejs/vite/commit/d4a171afd387000789172a94c94a1c33c0856f85))\n* **css:** remove alias exclude logic from rebaseUrl ([#20100](https://github.com/vitejs/vite/issues/20100)) ([44c6d01](https://github.com/vitejs/vite/commit/44c6d0111f95c8aa44d6a09a768e8cf02232ed29))\n* **css:** sass rebase url in relative imported modules ([#20067](https://github.com/vitejs/vite/issues/20067)) ([261fad9](https://github.com/vitejs/vite/commit/261fad9b8e6380c84b8692b3fbe18d6f37d367bd))\n* **css:** should not wrap with double quote when the url rebase feature bailed out ([#20068](https://github.com/vitejs/vite/issues/20068)) ([a33d0c7](https://github.com/vitejs/vite/commit/a33d0c7d65d9fff9acd5de0cf3c4d371297b3990))\n* **deps:** update all non-major dependencies ([#19953](https://github.com/vitejs/vite/issues/19953)) ([ac8e1fb](https://github.com/vitejs/vite/commit/ac8e1fb289a06fc0671dab1f4ef68e508e34360e))\n* **deps:** update all non-major dependencies ([#20061](https://github.com/vitejs/vite/issues/20061)) ([7b58856](https://github.com/vitejs/vite/commit/7b588563636a6f735a6e25832f33fc08572b25d9))\n* importing an optional peer dep should throw an runtime error ([#20029](https://github.com/vitejs/vite/issues/20029)) ([d0221cd](https://github.com/vitejs/vite/commit/d0221cd7383c18d67a5ef594da52e6aa5fc4d87b))\n* merge `environments.*.resolve.noExternal` properly ([#20077](https://github.com/vitejs/vite/issues/20077)) ([daf4a25](https://github.com/vitejs/vite/commit/daf4a25a1c0a37c992606e6ae159e13190c2e101))\n* merge `server.allowedHosts: true` correctly ([#20138](https://github.com/vitejs/vite/issues/20138)) ([2ade756](https://github.com/vitejs/vite/commit/2ade756c9549a52d804797d45da37c8429a51fd3))\n* **optimizer:** non object module.exports for Node builtin modules in CJS external facade ([#20048](https://github.com/vitejs/vite/issues/20048)) ([00ac6e4](https://github.com/vitejs/vite/commit/00ac6e410eeb15719fe020fd497f0336e7fd1aa8))\n* **optimizer:** show error when `computeEntries` failed ([#20079](https://github.com/vitejs/vite/issues/20079)) ([b742b46](https://github.com/vitejs/vite/commit/b742b46f8308a71c1d2aa426eade0c50cbf1480f))\n* treat all `optimizeDeps.entries` values as globs ([#20045](https://github.com/vitejs/vite/issues/20045)) ([1422395](https://github.com/vitejs/vite/commit/142239588d6752c5b91d435aee9b4a6c00b7f924))\n* **types:** expose additional PluginContext types ([#20129](https://github.com/vitejs/vite/issues/20129)) ([b6df9aa](https://github.com/vitejs/vite/commit/b6df9aac3320cd953f6d45ad9245a7b564f67cc1))\n\n### Performance Improvements\n\n* **utils:** improve performance of `numberToPos` ([#20244](https://github.com/vitejs/vite/issues/20244)) ([3f46901](https://github.com/vitejs/vite/commit/3f469012ad38e3cb330adc74a8b3ec88561c822e))\n\n### Documentation\n\n* tiny typo ([#20110](https://github.com/vitejs/vite/issues/20110)) ([d20fc2c](https://github.com/vitejs/vite/commit/d20fc2cdc9700513425b18b625e01224f61e4eab))\n\n### Miscellaneous Chores\n\n* \"indentity\" → \"identity\" in test description ([#20225](https://github.com/vitejs/vite/issues/20225)) ([ea9aed7](https://github.com/vitejs/vite/commit/ea9aed7ebcb7f4be542bd2a384cbcb5a1e7b31bd))\n* **deps:** update rolldown-related dependencies ([#20270](https://github.com/vitejs/vite/issues/20270)) ([f7377c3](https://github.com/vitejs/vite/commit/f7377c3eae6323bd3237ff5de5ae55c879fe7325))\n* typos in comments ([#20259](https://github.com/vitejs/vite/issues/20259)) ([b135918](https://github.com/vitejs/vite/commit/b135918b91e8381c50bd2d076d40e9a65fe68bfe))\n* **deps:** update rolldown-related dependencies ([#20182](https://github.com/vitejs/vite/issues/20182)) ([6172f41](https://github.com/vitejs/vite/commit/6172f410b44cbae8d052997bb1819a6197a4d397))\n* **deps:** update rolldown-related dependencies ([#20211](https://github.com/vitejs/vite/issues/20211)) ([b13b7f5](https://github.com/vitejs/vite/commit/b13b7f5e21fe05c3214766b3de584a026fbfe144))\n* add a way to disable source maps when developing Vite ([#20168](https://github.com/vitejs/vite/issues/20168)) ([3a30c0a](https://github.com/vitejs/vite/commit/3a30c0a084a1b92a6265f8900df89e5102418e5e))\n* **deps:** update rolldown-related dependencies ([#20140](https://github.com/vitejs/vite/issues/20140)) ([0387447](https://github.com/vitejs/vite/commit/03874471e3de14e7d2f474ecb354499e7f5eb418))\n* fix source map support when developing Vite ([#20167](https://github.com/vitejs/vite/issues/20167)) ([279ab0d](https://github.com/vitejs/vite/commit/279ab0dc954c5e986810b78efa7fe898945f8f21))\n* use destructuring alias in buildEnvironment function ([#19472](https://github.com/vitejs/vite/issues/19472)) ([501572a](https://github.com/vitejs/vite/commit/501572a9a3e1e22ab7e19afb5b13d3f54da67c37))\n* declare version range for peer dependencies ([#19979](https://github.com/vitejs/vite/issues/19979)) ([c9bfd57](https://github.com/vitejs/vite/commit/c9bfd578f4c56314c6c6d6f34e49fe494ae11072))\n* deprecate `ResolvedConfig.createResolver` and recommend `createIdResolver` ([#20031](https://github.com/vitejs/vite/issues/20031)) ([d101d64](https://github.com/vitejs/vite/commit/d101d64722f82ed681b833bfd3fb394eeb496e21))\n* fix comment for `devEnvironmentOptions.moduleRunnerTransform` ([#20035](https://github.com/vitejs/vite/issues/20035)) ([338081d](https://github.com/vitejs/vite/commit/338081df9649f68484416d199113fc67abbb6cd5))\n* generate dts internally by rolldown-plugin-dts ([#20093](https://github.com/vitejs/vite/issues/20093)) ([a66afa3](https://github.com/vitejs/vite/commit/a66afa33bd92e2be6ee1d52b8fffa49da266adab))\n* remove deprecated splitVendorChunkPlugin ([#19255](https://github.com/vitejs/vite/issues/19255)) ([91a92c7](https://github.com/vitejs/vite/commit/91a92c7e1eaf55cd5d5cfa49c546e130045e7dee))\n* remove node 18 support ([#19972](https://github.com/vitejs/vite/issues/19972)) ([00b8a98](https://github.com/vitejs/vite/commit/00b8a98f36376804437e1342265453915ae613de))\n* remove redundant word in comment ([#20139](https://github.com/vitejs/vite/issues/20139)) ([9b2964d](https://github.com/vitejs/vite/commit/9b2964df79d31b17e6b387e7fc082753f8ee5774))\n* remove unused deps ([#20097](https://github.com/vitejs/vite/issues/20097)) ([d11ae6b](https://github.com/vitejs/vite/commit/d11ae6bca808407a9f0fb4f9c1cb8496a705c2d7))\n* rename rollup to rolldown where appropriate ([#20096](https://github.com/vitejs/vite/issues/20096)) ([306e250](https://github.com/vitejs/vite/commit/306e250a94e12584b4182db8ec531750b3d9e3ba))\n* speed up typechecking ([#20131](https://github.com/vitejs/vite/issues/20131)) ([a357c19](https://github.com/vitejs/vite/commit/a357c1987f332519d7bacafebc5620c7ab534d8f))\n* use plugin hooks filter for `patch-types` plugin for bundling vite ([#20089](https://github.com/vitejs/vite/issues/20089)) ([c127955](https://github.com/vitejs/vite/commit/c12795522fd95d3535100293f4cf53c53c3f301f))\n* use rolldown to bundle Vite itself ([#19925](https://github.com/vitejs/vite/issues/19925)) ([7753b02](https://github.com/vitejs/vite/commit/7753b028848d9e23bcea5f00565207f2d1de8291))\n* use rolldown-plugin-dts for dts bundling ([#19990](https://github.com/vitejs/vite/issues/19990)) ([449d7f3](https://github.com/vitejs/vite/commit/449d7f30a85ae70eb0037fdab0b1ebf2e4927a24))\n\n### Code Refactoring\n\n* **worker:** set virtual file content in load hook ([#20160](https://github.com/vitejs/vite/issues/20160)) ([0d60667](https://github.com/vitejs/vite/commit/0d60667e03d91cc0d48dd2cdbd8154d94e0aba74))\n* bump required node version to 20.19+, 22.12+ and remove cjs build ([#20032](https://github.com/vitejs/vite/issues/20032)) ([2b80243](https://github.com/vitejs/vite/commit/2b80243fada75378e80475028fdcc78f4432bd6f))\n* **css:** always use sass compiler API ([#19978](https://github.com/vitejs/vite/issues/19978)) ([3bfe5c5](https://github.com/vitejs/vite/commit/3bfe5c5ff96af0a0624c8f14503ef87a0c0850ed))\n* **css:** remove sass legacy API support ([#19977](https://github.com/vitejs/vite/issues/19977)) ([6eaccc9](https://github.com/vitejs/vite/commit/6eaccc9009d718a1afcff2af587e81eb959f5b60))\n* merge `src/node/publicUtils.ts` to `src/node/index.ts` ([#20086](https://github.com/vitejs/vite/issues/20086)) ([999a1ed](https://github.com/vitejs/vite/commit/999a1ed8dff5117b2fd205c4e5384b6ac2ede80e))\n* remove `experimental.skipSsrTransform` option ([#20038](https://github.com/vitejs/vite/issues/20038)) ([6c3dd8e](https://github.com/vitejs/vite/commit/6c3dd8e46fa77060603679cda91a4c8d01d095ab))\n* remove `HotBroadcaster` ([#19988](https://github.com/vitejs/vite/issues/19988)) ([cda8c94](https://github.com/vitejs/vite/commit/cda8c947934466da27e874b6c064451cf73f03e5))\n* remove `options?.ssr` support in clientInjectionsPlugin ([#19589](https://github.com/vitejs/vite/issues/19589)) ([88e0076](https://github.com/vitejs/vite/commit/88e00765dbd3de4cb073c722dce3e8ef60c3a50e))\n* remove backward compat for calling internal plugins directly ([#20001](https://github.com/vitejs/vite/issues/20001)) ([9072a72](https://github.com/vitejs/vite/commit/9072a726731eccee32d38f04747fda8793ccc82a))\n* remove deprecated `HotBroadcaster` related types ([#19987](https://github.com/vitejs/vite/issues/19987)) ([86b5e00](https://github.com/vitejs/vite/commit/86b5e0030bf204f8f2db0cf8ee895ab3ecf154b8))\n* remove deprecated env api properties ([#19986](https://github.com/vitejs/vite/issues/19986)) ([52e5a1b](https://github.com/vitejs/vite/commit/52e5a1b32d0ce7604b633f001a352124e3ec623a))\n* remove deprecated hook-level `enforce`/`transform` from `transformIndexHtml` hook ([#19349](https://github.com/vitejs/vite/issues/19349)) ([6198b9d](https://github.com/vitejs/vite/commit/6198b9d2a32f7bd17b3332525a98c06d9a425fb1))\n* remove deprecated no-op type only properties ([#19985](https://github.com/vitejs/vite/issues/19985)) ([9151c24](https://github.com/vitejs/vite/commit/9151c2400f6ab494f73d78aea4435b7c1ef5fc30))\n* remove no-op `legacy.proxySsrExternalModules` ([#20013](https://github.com/vitejs/vite/issues/20013)) ([a37ac83](https://github.com/vitejs/vite/commit/a37ac836ac4da8e854d98c65450f12acb921aa98))\n* **ssr:** remove ssrTransform line offset preservation ([#19829](https://github.com/vitejs/vite/issues/19829)) ([61b6b96](https://github.com/vitejs/vite/commit/61b6b96b191c6071b9c574ad4c795f97f2646f18))\n* use `hostValidationMiddleware` ([#20019](https://github.com/vitejs/vite/issues/20019)) ([83bf90e](https://github.com/vitejs/vite/commit/83bf90edd5856ed6e27051e3e9a6032e02242b18))\n* use `mergeWithDefaults` for experimental option ([#20012](https://github.com/vitejs/vite/issues/20012)) ([98c5741](https://github.com/vitejs/vite/commit/98c57419426201596a962746436e5ad1aeef4eac))\n* use hook filters from rollup ([#19755](https://github.com/vitejs/vite/issues/19755)) ([0d18fc1](https://github.com/vitejs/vite/commit/0d18fc1dc65f5c8d855808f23754c0c4902f07d9))\n\n### Tests\n\n* correct esbuild `useDefineForClassFields` test ([#20143](https://github.com/vitejs/vite/issues/20143)) ([d90796e](https://github.com/vitejs/vite/commit/d90796ece7d30d1879d74c422628be30d1c90a7f))\n* skip writing files in build hook filter test ([#20076](https://github.com/vitejs/vite/issues/20076)) ([bf8b07d](https://github.com/vitejs/vite/commit/bf8b07da3e64dc4de446a9b24a33d5822a7736b9))\n\n### Continuous Integration\n\n* run tests on Node 24 as well ([#20049](https://github.com/vitejs/vite/issues/20049)) ([1fe07d3](https://github.com/vitejs/vite/commit/1fe07d3716012992dd7b2e78d8380add0b606a97))\n\n### Beta Changelogs\n\n\n#### [7.0.0-beta.2](https://github.com/vitejs/vite/compare/v7.0.0-beta.1...v7.0.0-beta.2) (2025-06-17)\n\nSee [7.0.0-beta.2 changelog](https://github.com/vitejs/vite/blob/v7.0.0-beta.2/packages/vite/CHANGELOG.md)\n\n\n#### [7.0.0-beta.1](https://github.com/vitejs/vite/compare/v7.0.0-beta.0...v7.0.0-beta.1) (2025-06-10)\n\nSee [7.0.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v7.0.0-beta.1/packages/vite/CHANGELOG.md)\n\n\n#### [7.0.0-beta.0](https://github.com/vitejs/vite/compare/6.3.5...v7.0.0-beta.0) (2025-06-02)\n\nSee [7.0.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v7.0.0-beta.0/packages/vite/CHANGELOG.md)\n\n\n## <small>[6.3.5](https://github.com/vitejs/vite/compare/v6.3.4...v6.3.5) (2025-05-05)</small>\n### Bug Fixes\n\n* **ssr:** handle uninitialized export access as undefined ([#19959](https://github.com/vitejs/vite/issues/19959)) ([fd38d07](https://github.com/vitejs/vite/commit/fd38d076fe2455aac1e00a7b15cd51159bf12bb5))\n\n## <small>[6.3.4](https://github.com/vitejs/vite/compare/v6.3.3...v6.3.4) (2025-04-30)</small>\n### Bug Fixes\n\n* check static serve file inside sirv ([#19965](https://github.com/vitejs/vite/issues/19965)) ([c22c43d](https://github.com/vitejs/vite/commit/c22c43de612eebb6c182dd67850c24e4fab8cacb))\n* **optimizer:** return plain object when using `require` to import externals in optimized dependencies ([#19940](https://github.com/vitejs/vite/issues/19940)) ([efc5eab](https://github.com/vitejs/vite/commit/efc5eab253419fde0a6a48b8d2f233063d6a9643))\n\n### Code Refactoring\n\n* remove duplicate plugin context type ([#19935](https://github.com/vitejs/vite/issues/19935)) ([d6d01c2](https://github.com/vitejs/vite/commit/d6d01c2292fa4f9603e05b95d81c8724314c20e0))\n\n## <small>[6.3.3](https://github.com/vitejs/vite/compare/v6.3.2...v6.3.3) (2025-04-24)</small>\n### Bug Fixes\n\n* **assets:** ensure ?no-inline is not included in the asset url in the production environment ([#19496](https://github.com/vitejs/vite/issues/19496)) ([16a73c0](https://github.com/vitejs/vite/commit/16a73c05d35daa34117a173784895546212db5f4))\n* **css:** resolve relative imports in sass properly on Windows ([#19920](https://github.com/vitejs/vite/issues/19920)) ([ffab442](https://github.com/vitejs/vite/commit/ffab44270488f54ae344801024474b597249071b))\n* **deps:** update all non-major dependencies ([#19899](https://github.com/vitejs/vite/issues/19899)) ([a4b500e](https://github.com/vitejs/vite/commit/a4b500ef9ccc9b19a2882156a9ba8397e69bc6b2))\n* ignore malformed uris in transform middleware ([#19853](https://github.com/vitejs/vite/issues/19853)) ([e4d5201](https://github.com/vitejs/vite/commit/e4d520141bcd83ad61f16767348b4a813bf9340a))\n* **ssr:** fix execution order of re-export ([#19841](https://github.com/vitejs/vite/issues/19841)) ([ed29dee](https://github.com/vitejs/vite/commit/ed29dee2eb2e3573b2bc337e1a9124c65222a1e5))\n* **ssr:** fix live binding of default export declaration and hoist exports getter ([#19842](https://github.com/vitejs/vite/issues/19842)) ([80a91ff](https://github.com/vitejs/vite/commit/80a91ff82426a4c88d54b9f5ec9a4205cb13899b))\n\n### Performance Improvements\n\n* skip sourcemap generation for renderChunk hook of import-analysis-build plugin ([#19921](https://github.com/vitejs/vite/issues/19921)) ([55cfd04](https://github.com/vitejs/vite/commit/55cfd04b10f98cde7a96814a69b9813543ea79c2))\n\n### Tests\n\n* **ssr:** test `ssrTransform` re-export deps and test stacktrace with first line ([#19629](https://github.com/vitejs/vite/issues/19629)) ([9399cda](https://github.com/vitejs/vite/commit/9399cdaf8c3b2efd5f4015d57dc3b0e4e5b91a9d))\n\n## <small>[6.3.2](https://github.com/vitejs/vite/compare/v6.3.1...v6.3.2) (2025-04-18)</small>\n### Features\n\n* **css:** improve lightningcss messages ([#19880](https://github.com/vitejs/vite/issues/19880)) ([c713f79](https://github.com/vitejs/vite/commit/c713f79b5a4bd98542d8dbe4c85ba4cce9b1f358))\n\n### Bug Fixes\n\n* **css:** respect `css.lightningcss` option in css minification process ([#19879](https://github.com/vitejs/vite/issues/19879)) ([b5055e0](https://github.com/vitejs/vite/commit/b5055e0dd4c0e084115c3dbfead5736a54807e0c))\n* **deps:** update all non-major dependencies ([#19698](https://github.com/vitejs/vite/issues/19698)) ([bab4cb9](https://github.com/vitejs/vite/commit/bab4cb92248adf6b9b18df12b2bf03889b0bd1eb))\n* match default asserts case insensitive ([#19852](https://github.com/vitejs/vite/issues/19852)) ([cbdab1d](https://github.com/vitejs/vite/commit/cbdab1d6a30e07263ec51b2ca042369e736adec6))\n* open first url if host does not match any urls ([#19886](https://github.com/vitejs/vite/issues/19886)) ([6abbdce](https://github.com/vitejs/vite/commit/6abbdce3d77990409e12380e72c7ec9dd3f8bec5))\n\n## <small>[6.3.1](https://github.com/vitejs/vite/compare/v6.3.0...v6.3.1) (2025-04-17)</small>\n### Bug Fixes\n\n* avoid using `Promise.allSettled` in preload function ([#19805](https://github.com/vitejs/vite/issues/19805)) ([35c7f35](https://github.com/vitejs/vite/commit/35c7f35e2b67f2158ededf2af58ecec53b3f16c5))\n* backward compat for internal plugin `transform` calls ([#19878](https://github.com/vitejs/vite/issues/19878)) ([a152b7c](https://github.com/vitejs/vite/commit/a152b7cbac72e05668f8fc23074d531ecebb77a5))\n\n## [6.3.0](https://github.com/vitejs/vite/compare/v6.2.2...v6.3.0) (2025-04-16)\n\n### Features\n\n* **env:** add false option for envDir to disable env loading ([#19503](https://github.com/vitejs/vite/issues/19503)) ([bca89e1](https://github.com/vitejs/vite/commit/bca89e153e58edd2b506807958557a21edacfaf8))\n* **types:** make CustomPluginOptionsVite backward compatible ([#19760](https://github.com/vitejs/vite/issues/19760)) ([821edf1](https://github.com/vitejs/vite/commit/821edf196f281b90af0742647a3feaf3226be439))\n* **config:** improve bad character warning ([#19683](https://github.com/vitejs/vite/issues/19683)) ([998303b](https://github.com/vitejs/vite/commit/998303b438734e8219715fe6883b97fb10404c16))\n* **css:** support preprocessor with lightningcss ([#19071](https://github.com/vitejs/vite/issues/19071)) ([d3450ca](https://github.com/vitejs/vite/commit/d3450cae614af4c2b866903411b6d765df3e5a48))\n* **experimental:** add fetchable environment interface ([#19664](https://github.com/vitejs/vite/issues/19664)) ([c5b7191](https://github.com/vitejs/vite/commit/c5b71915099cfbc15447a166f35620fa0e05c023))\n* implement hook filters ([#19602](https://github.com/vitejs/vite/issues/19602)) ([04d58b4](https://github.com/vitejs/vite/commit/04d58b42ae69547f04ef8fcd574b1ee1b654dc32))\n* **types:** expose `CustomPluginOptionsVite` type ([#19557](https://github.com/vitejs/vite/issues/19557)) ([15abc01](https://github.com/vitejs/vite/commit/15abc01241b0da5c4af6aa59b0bc936ccab0f0b4))\n* **types:** make ImportMetaEnv strictly available ([#19077](https://github.com/vitejs/vite/issues/19077)) ([6cf5141](https://github.com/vitejs/vite/commit/6cf51417cdfc26f100c00c910e00829e48dec79c))\n* **types:** type hints for hmr events ([#19579](https://github.com/vitejs/vite/issues/19579)) ([95424b2](https://github.com/vitejs/vite/commit/95424b26892b005f438169d0ea426cb1a3176bf2))\n* warn if `define['process.env']` contains `path` key with a value ([#19517](https://github.com/vitejs/vite/issues/19517)) ([832b2c4](https://github.com/vitejs/vite/commit/832b2c409ebbb2ba1480e6ae4630c7f047c160d4))\n\n### Bug Fixes\n\n* **hmr:** avoid infinite loop happening with `hot.invalidate` in circular deps ([#19870](https://github.com/vitejs/vite/issues/19870)) ([d4ee5e8](https://github.com/vitejs/vite/commit/d4ee5e8655a85f4d6bebc695b063d69406ab53ac))\n* **preview:** use host url to open browser ([#19836](https://github.com/vitejs/vite/issues/19836)) ([5003434](https://github.com/vitejs/vite/commit/50034340401b4043bb0b158f18ffb7ae1b7f5c86))\n* addWatchFile doesn't work if base is specified (fixes [#19792](https://github.com/vitejs/vite/issues/19792)) ([#19794](https://github.com/vitejs/vite/issues/19794)) ([8bed1de](https://github.com/vitejs/vite/commit/8bed1de5710f2a097af0e22a196545446d98f988))\n* correct the behavior when multiple transform filter options are specified ([#19818](https://github.com/vitejs/vite/issues/19818)) ([7200dee](https://github.com/vitejs/vite/commit/7200deec91a501fb84734e23906f80808734540c))\n* **css:** remove empty chunk imports correctly when chunk file name contained special characters ([#19814](https://github.com/vitejs/vite/issues/19814)) ([b125172](https://github.com/vitejs/vite/commit/b1251720d47f15615ea354991cdaa90d9a94aae5))\n* **dev:** make query selector regexes more inclusive (fix [#19213](https://github.com/vitejs/vite/issues/19213)) ([#19767](https://github.com/vitejs/vite/issues/19767)) ([f530a72](https://github.com/vitejs/vite/commit/f530a72246ec8e73b1f2ba767f6c108e9ac9712a))\n* fs check with svg and relative paths ([#19782](https://github.com/vitejs/vite/issues/19782)) ([62d7e81](https://github.com/vitejs/vite/commit/62d7e81ee189d65899bb65f3263ddbd85247b647))\n* **hmr:** run HMR handler sequentially ([#19793](https://github.com/vitejs/vite/issues/19793)) ([380c10e](https://github.com/vitejs/vite/commit/380c10e665e78ef732a8d7b6c8f60a1226fc4c3b))\n* keep entry asset files imported by other files ([#19779](https://github.com/vitejs/vite/issues/19779)) ([2fa1495](https://github.com/vitejs/vite/commit/2fa149580118a6b7988593dea9e2bf2ee679506c))\n* **module-runner:** allow already resolved id as entry ([#19768](https://github.com/vitejs/vite/issues/19768)) ([e2e11b1](https://github.com/vitejs/vite/commit/e2e11b15a6083777ee521e26a3f79c3859abd411))\n* reject requests with `#` in request-target ([#19830](https://github.com/vitejs/vite/issues/19830)) ([175a839](https://github.com/vitejs/vite/commit/175a83909f02d3b554452a7bd02b9f340cdfef70))\n* **types:** remove the `keepProcessEnv` from the `DefaultEnvironmentOptions` type ([#19796](https://github.com/vitejs/vite/issues/19796)) ([36935b5](https://github.com/vitejs/vite/commit/36935b58eabde46ab845e121e21525df5ad65ff1))\n* unbundle `fdir` to fix `commonjsOptions.dynamicRequireTargets` ([#19791](https://github.com/vitejs/vite/issues/19791)) ([71227be](https://github.com/vitejs/vite/commit/71227be9aab52c1c5df59afba4539646204eff74))\n* align plugin hook filter behavior with pluginutils ([#19736](https://github.com/vitejs/vite/issues/19736)) ([0bbdd2c](https://github.com/vitejs/vite/commit/0bbdd2c1338624fa0e76c81648989f8f9a5b36d7))\n* fs check in transform middleware ([#19761](https://github.com/vitejs/vite/issues/19761)) ([5967313](https://github.com/vitejs/vite/commit/59673137c45ac2bcfad1170d954347c1a17ab949))\n* **hmr:** throw non-standard error info causes logical error ([#19776](https://github.com/vitejs/vite/issues/19776)) ([6b648c7](https://github.com/vitejs/vite/commit/6b648c73ae33a57f648af87204a325335afffca8))\n* add back `.mts` to default `resolve.extensions` ([#19701](https://github.com/vitejs/vite/issues/19701)) ([ae91bd0](https://github.com/vitejs/vite/commit/ae91bd0ad10942898c3d7aa8181249fb9682a4fe))\n* **css:** parse image-set without space after comma correctly ([#19661](https://github.com/vitejs/vite/issues/19661)) ([d0d4c66](https://github.com/vitejs/vite/commit/d0d4c66bd539a5232005ac7ad63ec19f0794f2a5))\n* **css:** scoped css order with non-scoped css ([#19678](https://github.com/vitejs/vite/issues/19678)) ([a3a94ab](https://github.com/vitejs/vite/commit/a3a94abb200c0bb1ed8bc4abb539a9ea27ce1a84))\n* **deps:** update all non-major dependencies ([#19649](https://github.com/vitejs/vite/issues/19649)) ([f4e712f](https://github.com/vitejs/vite/commit/f4e712ff861f8a9504594a4a5e6d35a7547e5a7e))\n* fs raw query with query separators ([#19702](https://github.com/vitejs/vite/issues/19702)) ([262b5ec](https://github.com/vitejs/vite/commit/262b5ec7ae4981208339b7b87fefbd3dd8465851))\n* **optimizer:** fix incorrect picomatch usage in filter() ([#19646](https://github.com/vitejs/vite/issues/19646)) ([300280d](https://github.com/vitejs/vite/commit/300280d52203b6c1d8867d956f7d5c991e2e9dfb))\n* **ssr:** hoist export to handle cyclic import better ([#18983](https://github.com/vitejs/vite/issues/18983)) ([8c04c69](https://github.com/vitejs/vite/commit/8c04c69a52c7b66d551d384ac34bb10ab1522f68))\n\n### Performance Improvements\n\n* **css:** avoid constructing `renderedModules` ([#19775](https://github.com/vitejs/vite/issues/19775)) ([59d0b35](https://github.com/vitejs/vite/commit/59d0b35b30f3a38be33c0a9bdc177945b6f7eb1b))\n* only bundle node version `debug` ([#19715](https://github.com/vitejs/vite/issues/19715)) ([e435aae](https://github.com/vitejs/vite/commit/e435aae22ffda441a24332cd79226bfca55326aa))\n\n### Documentation\n\n* **vite:** fix description of `transformIndexHtml` hook ([#19799](https://github.com/vitejs/vite/issues/19799)) ([a0e1a04](https://github.com/vitejs/vite/commit/a0e1a0402648e0df60fb928ffd97b0230999990d))\n\n### Miscellaneous Chores\n\n* remove unused eslint directive ([#19781](https://github.com/vitejs/vite/issues/19781)) ([cb4f5b4](https://github.com/vitejs/vite/commit/cb4f5b4b6bb7dc96812b126ccc475d1e2c3f7f92))\n* fix some typos in comment ([#19728](https://github.com/vitejs/vite/issues/19728)) ([35ee848](https://github.com/vitejs/vite/commit/35ee84808af3a5443019e36cba351af859113695))\n* **deps:** unbundle tinyglobby ([#19487](https://github.com/vitejs/vite/issues/19487)) ([a5ea6f0](https://github.com/vitejs/vite/commit/a5ea6f09ba79f4a5b72117899bccaa43613a777f))\n\n### Code Refactoring\n\n* simplify pluginFilter implementation ([#19828](https://github.com/vitejs/vite/issues/19828)) ([0a0c50a](https://github.com/vitejs/vite/commit/0a0c50a7ed38017469ed6dcec941c2d8d0efd0d0))\n* `[hookName].handler` in plugins ([#19586](https://github.com/vitejs/vite/issues/19586)) ([9827df2](https://github.com/vitejs/vite/commit/9827df2195905e5eb04b46dce357d12c3dff4876))\n* **reporter:** only call modulesReporter when logLevel is info ([#19708](https://github.com/vitejs/vite/issues/19708)) ([7249553](https://github.com/vitejs/vite/commit/7249553625b667b6affb448d5acb7d6f457640f6))\n\n### Tests\n\n* tweak generateCodeFrame test ([#19812](https://github.com/vitejs/vite/issues/19812)) ([8fe3538](https://github.com/vitejs/vite/commit/8fe3538d9095384c670815dc42ef67e051f3246f))\n\n### Beta Changelogs\n\n#### [6.3.0-beta.2](https://github.com/vitejs/vite/compare/v6.3.0-beta.1...v6.3.0-beta.2) (2025-04-11)\n\nSee [6.3.0-beta.2 changelog](https://github.com/vitejs/vite/blob/v6.3.0-beta.2/packages/vite/CHANGELOG.md)\n\n#### [6.3.0-beta.1](https://github.com/vitejs/vite/compare/v6.3.0-beta.0...v6.3.0-beta.1) (2025-04-03)\n\nSee [6.3.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v6.3.0-beta.1/packages/vite/CHANGELOG.md)\n\n#### [6.3.0-beta.0](https://github.com/vitejs/vite/compare/v6.2.2...v6.3.0-beta.0) (2025-03-26)\n\nSee [6.3.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v6.3.0-beta.0/packages/vite/CHANGELOG.md)\n\n## <small>[6.2.2](https://github.com/vitejs/vite/compare/v6.2.1...v6.2.2) (2025-03-14)</small>\n### Features\n\n* show friendly error for malformed `base` ([#19616](https://github.com/vitejs/vite/issues/19616)) ([2476391](https://github.com/vitejs/vite/commit/2476391b2854aaa67d0ed317b6d0c462e68028f7))\n* **worker:** show asset filename conflict warning ([#19591](https://github.com/vitejs/vite/issues/19591)) ([367d968](https://github.com/vitejs/vite/commit/367d968fbf584e9f0e17192b816e92e8045c6217))\n\n### Bug Fixes\n\n* await client buildStart on top level buildStart ([#19624](https://github.com/vitejs/vite/issues/19624)) ([b31faab](https://github.com/vitejs/vite/commit/b31faab2a81b839e4b747baeb9c7a7cbb724f8d2))\n* **css:** inline css correctly for double quote use strict ([#19590](https://github.com/vitejs/vite/issues/19590)) ([d0aa833](https://github.com/vitejs/vite/commit/d0aa833296668fc420a27a1ea88ecdbdeacdbce7))\n* **deps:** update all non-major dependencies ([#19613](https://github.com/vitejs/vite/issues/19613)) ([363d691](https://github.com/vitejs/vite/commit/363d691b4995d72f26a14eb59ed88a9483b1f931))\n* **indexHtml:** ensure correct URL when querying module graph ([#19601](https://github.com/vitejs/vite/issues/19601)) ([dc5395a](https://github.com/vitejs/vite/commit/dc5395a27e44066ef7725278c4057d9f1071a53f))\n* **preview:** use preview https config, not server ([#19633](https://github.com/vitejs/vite/issues/19633)) ([98b3160](https://github.com/vitejs/vite/commit/98b3160fa5916189e756cd7c5aae87e0d8f1978e))\n* **ssr:** use optional chaining to prevent \"undefined is not an object\" happening in `ssrRewriteStacktrace` ([#19612](https://github.com/vitejs/vite/issues/19612)) ([4309755](https://github.com/vitejs/vite/commit/43097550a1aa8ff633c39fb197b5f9ac1222119b))\n\n### Miscellaneous Chores\n\n* extend commit hash correctly when ambigious with a non-commit object ([#19600](https://github.com/vitejs/vite/issues/19600)) ([89a6287](https://github.com/vitejs/vite/commit/89a62873243805518b672212db7e317989c5c197))\n\n## <small>[6.2.1](https://github.com/vitejs/vite/compare/v6.2.0...v6.2.1) (2025-03-07)</small>\n### Features\n\n* add `*?url&no-inline` type and warning for `.json?inline` / `.json?no-inline` ([#19566](https://github.com/vitejs/vite/issues/19566)) ([c0d3667](https://github.com/vitejs/vite/commit/c0d36677cd305e8fa89153ed6305f0e0df43d289))\n\n### Bug Fixes\n\n* **css:** stabilize css module hashes with lightningcss in dev mode ([#19481](https://github.com/vitejs/vite/issues/19481)) ([92125b4](https://github.com/vitejs/vite/commit/92125b41e4caa3e862bf5fd9b1941546f25d9bf2))\n* **deps:** update all non-major dependencies ([#19555](https://github.com/vitejs/vite/issues/19555)) ([f612e0f](https://github.com/vitejs/vite/commit/f612e0fdf6810317b61fcca1ded125755f261d78))\n* **reporter:** fix incorrect bundle size calculation with non-ASCII characters ([#19561](https://github.com/vitejs/vite/issues/19561)) ([437c0ed](https://github.com/vitejs/vite/commit/437c0ed8baa6739bbe944779b9e7515f9035046a))\n* **sourcemap:** combine sourcemaps with multiple sources without matched source ([#18971](https://github.com/vitejs/vite/issues/18971)) ([e3f6ae1](https://github.com/vitejs/vite/commit/e3f6ae14f7a93118d7341de7379967f815725c4b))\n* **ssr:** named export should overwrite export all ([#19534](https://github.com/vitejs/vite/issues/19534)) ([2fd2fc1](https://github.com/vitejs/vite/commit/2fd2fc110738622651d361488767734cc23c34dd))\n\n### Performance Improvements\n\n* flush compile cache after 10s ([#19537](https://github.com/vitejs/vite/issues/19537)) ([6c8a5a2](https://github.com/vitejs/vite/commit/6c8a5a27e645a182f5b03a4ed6aa726eab85993f))\n\n### Miscellaneous Chores\n\n* **css:** move environment destructuring after condition check ([#19492](https://github.com/vitejs/vite/issues/19492)) ([c9eda23](https://github.com/vitejs/vite/commit/c9eda2348c244d591d23f131c6ddf262b256cbf0))\n* **html:** remove unnecessary value check ([#19491](https://github.com/vitejs/vite/issues/19491)) ([797959f](https://github.com/vitejs/vite/commit/797959f01da583b85a0be1dc89f762fd01d138db))\n\n### Code Refactoring\n\n* remove `isBuild` check from preAliasPlugin ([#19587](https://github.com/vitejs/vite/issues/19587)) ([c9e086d](https://github.com/vitejs/vite/commit/c9e086d35ac35ee1c6d85d48369e8a67a2ba6bfe))\n* restore endsWith usage ([#19554](https://github.com/vitejs/vite/issues/19554)) ([6113a96](https://github.com/vitejs/vite/commit/6113a9670cc9b7d29fe0bffe033f7823e36ded00))\n* use `applyToEnvironment` in internal plugins ([#19588](https://github.com/vitejs/vite/issues/19588)) ([f678442](https://github.com/vitejs/vite/commit/f678442d5701a00648a745956f9d884247e4e710))\n\n### Tests\n\n* add glob import test case ([#19516](https://github.com/vitejs/vite/issues/19516)) ([aa1d807](https://github.com/vitejs/vite/commit/aa1d8075cc7ce7fbba62fea9e37ccb9b304fc039))\n* convert config playground to unit tests ([#19568](https://github.com/vitejs/vite/issues/19568)) ([c0e68da](https://github.com/vitejs/vite/commit/c0e68da4774f3487e9ba0c4d4d2c5e76bdc890ea))\n* convert resolve-config playground to unit tests ([#19567](https://github.com/vitejs/vite/issues/19567)) ([db5fb48](https://github.com/vitejs/vite/commit/db5fb48f5d4c1ee411e59c1e9b70d62fdb9d53d2))\n\n## [6.2.0](https://github.com/vitejs/vite/compare/v6.1.1...v6.2.0) (2025-02-25)\n\n### Features\n\n* **css:** allow scoping css to importers exports ([#19418](https://github.com/vitejs/vite/issues/19418)) ([3ebd838](https://github.com/vitejs/vite/commit/3ebd83833f723dde64098bc617c61b37adb3ad01))\n* show `mode` on server start and add env debugger ([#18808](https://github.com/vitejs/vite/issues/18808)) ([c575b82](https://github.com/vitejs/vite/commit/c575b825596ccaedfac1cfecbb9a464e5e584a60))\n* use host url to open browser ([#19414](https://github.com/vitejs/vite/issues/19414)) ([f6926ca](https://github.com/vitejs/vite/commit/f6926caa1f2c9433ca544172378412795722d8e1))\n\n### Bug Fixes\n\n* **deps:** update all non-major dependencies ([#19501](https://github.com/vitejs/vite/issues/19501)) ([c94c9e0](https://github.com/vitejs/vite/commit/c94c9e052127cf4796374de1d698ec60b2973dfa))\n* **worker:** string interpolation in dynamic worker options ([#19476](https://github.com/vitejs/vite/issues/19476)) ([07091a1](https://github.com/vitejs/vite/commit/07091a1e804e5934208ef0b6324a04317dd0d815))\n* **css:** temporary add `?.` after `this.getModuleInfo` in `vite:css-post` ([#19478](https://github.com/vitejs/vite/issues/19478)) ([12b0b8a](https://github.com/vitejs/vite/commit/12b0b8a953ad7d08ba0540cb4f5cb26a7fa69da2))\n\n### Miscellaneous Chores\n\n* use unicode cross icon instead of x ([#19497](https://github.com/vitejs/vite/issues/19497)) ([5c70296](https://github.com/vitejs/vite/commit/5c70296ffb22fe5a0f4039835aa14feb096b4a97))\n* bump esbuild to 0.25.0 ([#19389](https://github.com/vitejs/vite/issues/19389)) ([73987f2](https://github.com/vitejs/vite/commit/73987f22ec3f2df0d36154f1766ca7a7dc4c2460))\n\n### Beta Changelogs\n\n#### [6.2.0-beta.1](https://github.com/vitejs/vite/compare/v6.2.0-beta.0...v6.2.0-beta.1) (2025-02-21)\n\nSee [6.2.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v6.2.0-beta.1/packages/vite/CHANGELOG.md)\n\n#### [6.2.0-beta.0](https://github.com/vitejs/vite/compare/v6.1.1...v6.2.0-beta.0) (2025-02-21)\n\nSee [6.2.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v6.2.0-beta.0/packages/vite/CHANGELOG.md)\n\n## <small>[6.1.1](https://github.com/vitejs/vite/compare/v6.1.0...v6.1.1) (2025-02-19)</small>\n### Features\n\n* add support for injecting debug IDs ([#18763](https://github.com/vitejs/vite/issues/18763)) ([0ff556a](https://github.com/vitejs/vite/commit/0ff556a6d9b55bff7cac17396ce7d4397becacaa))\n\n### Bug Fixes\n\n* **css:** run rewrite plugin if postcss plugin exists ([#19371](https://github.com/vitejs/vite/issues/19371)) ([bcdb51a](https://github.com/vitejs/vite/commit/bcdb51a1ac082f4e8ed6f820787d6745dfaa972d))\n* **deps:** bump tsconfck ([#19375](https://github.com/vitejs/vite/issues/19375)) ([746a583](https://github.com/vitejs/vite/commit/746a583d42592a31e1e8e80cc790a7c9e6acf58e))\n* **deps:** update all non-major dependencies ([#19392](https://github.com/vitejs/vite/issues/19392)) ([60456a5](https://github.com/vitejs/vite/commit/60456a54fe90872dbd4bed332ecbd85bc88deb92))\n* **deps:** update all non-major dependencies ([#19440](https://github.com/vitejs/vite/issues/19440)) ([ccac73d](https://github.com/vitejs/vite/commit/ccac73d9d0e92c7232f09207d1d6b893e823ed8e))\n* ensure `.[cm]?[tj]sx?` static assets are JS mime ([#19453](https://github.com/vitejs/vite/issues/19453)) ([e7ba55e](https://github.com/vitejs/vite/commit/e7ba55e7d57ad97ab43682b152159e29fa4b3753))\n* **html:** ignore malformed src attrs ([#19397](https://github.com/vitejs/vite/issues/19397)) ([aff7812](https://github.com/vitejs/vite/commit/aff7812f0aed059c05ca36c86bf907d25964119a))\n* ignore `*.ipv4` address in cert ([#19416](https://github.com/vitejs/vite/issues/19416)) ([973283b](https://github.com/vitejs/vite/commit/973283bf84c3dca42e2e20a9f9b8761011878b8b))\n* **worker:** fix web worker type detection ([#19462](https://github.com/vitejs/vite/issues/19462)) ([edc65ea](https://github.com/vitejs/vite/commit/edc65eafa332b57ce44835deb7d7707e2d036c24))\n\n### Miscellaneous Chores\n\n* update 6.1.0 changelog ([#19363](https://github.com/vitejs/vite/issues/19363)) ([fa7c211](https://github.com/vitejs/vite/commit/fa7c211bf3e51269f8a8601e5994fb3ebb6859f9))\n\n### Code Refactoring\n\n* remove custom .jxl mime ([#19457](https://github.com/vitejs/vite/issues/19457)) ([0c85464](https://github.com/vitejs/vite/commit/0c854645bd17960abbe8f01b602d1a1da1a2b9fd))\n\n## [6.1.0](https://github.com/vitejs/vite/compare/v6.1.0-beta.2...v6.1.0) (2025-02-05)\n### Features\n\n* show hosts in cert in CLI ([#19317](https://github.com/vitejs/vite/issues/19317)) ([a5e306f](https://github.com/vitejs/vite/commit/a5e306f2fc34fc70d543028c319367ff9b232ea0))\n* support for env var for defining allowed hosts ([#19325](https://github.com/vitejs/vite/issues/19325)) ([4d88f6c](https://github.com/vitejs/vite/commit/4d88f6c9391f96275b1359f1343ee2ec3e1adb7b))\n* use native runtime to import the config ([#19178](https://github.com/vitejs/vite/issues/19178)) ([7c2a794](https://github.com/vitejs/vite/commit/7c2a7942cc8494a98fbc2b0235d91faf25242d30))\n* print `port` in the logged error message after failed WS connection with `EADDRINUSE` ([#19212](https://github.com/vitejs/vite/issues/19212)) ([14027b0](https://github.com/vitejs/vite/commit/14027b0f2a9b01c14815c38aab22baf5b29594bb))\n* add support for `.jxl` ([#18855](https://github.com/vitejs/vite/issues/18855)) ([57b397c](https://github.com/vitejs/vite/commit/57b397c4aa3d3c657e0117c2468800d627049c8d))\n* add the `builtins` environment `resolve` ([#18584](https://github.com/vitejs/vite/issues/18584)) ([2c2d521](https://github.com/vitejs/vite/commit/2c2d521abfd7a3263b5082f9420738ad0ef67c71))\n* call Logger for plugin logs in build ([#13757](https://github.com/vitejs/vite/issues/13757)) ([bf3e410](https://github.com/vitejs/vite/commit/bf3e41082932f4bf7d828e18ab0346b2ac8b59c9))\n* **css:** add friendly errors for IE hacks that are not supported by lightningcss ([#19072](https://github.com/vitejs/vite/issues/19072)) ([caad985](https://github.com/vitejs/vite/commit/caad985abca6450d56ca3d4e27e1e859fe8909b9))\n* export `defaultAllowedOrigins` for user-land config and 3rd party plugins ([#19259](https://github.com/vitejs/vite/issues/19259)) ([dc8946b](https://github.com/vitejs/vite/commit/dc8946b9f6483ca7d63df3a5cbba307f1c21041e))\n* expose createServerModuleRunnerTransport ([#18730](https://github.com/vitejs/vite/issues/18730)) ([8c24ee4](https://github.com/vitejs/vite/commit/8c24ee4b4fcfa16fdd8bb699643a92ee81f9c92b))\n* **optimizer:** support bun text lockfile ([#18403](https://github.com/vitejs/vite/issues/18403)) ([05b005f](https://github.com/vitejs/vite/commit/05b005fc25a1e8dda749fb14149aa2f3c988b6a1))\n* **reporter:** add `wasm` to the compressible assets regex ([#19085](https://github.com/vitejs/vite/issues/19085)) ([ce84142](https://github.com/vitejs/vite/commit/ce84142110584eadfccbd6ce9319573358af31a6))\n* support async for proxy.bypass ([#18940](https://github.com/vitejs/vite/issues/18940)) ([a6b9587](https://github.com/vitejs/vite/commit/a6b958741bd97d631aba21aa5925bbf2bca65dac))\n* support log related functions in dev ([#18922](https://github.com/vitejs/vite/issues/18922)) ([3766004](https://github.com/vitejs/vite/commit/3766004289fde3300d1278fcf35f3bb980d9785f))\n* use module runner to import the config ([#18637](https://github.com/vitejs/vite/issues/18637)) ([b7e0e42](https://github.com/vitejs/vite/commit/b7e0e42098dd2d42285a9d3c4f39c48a580367e7))\n* **worker:** support dynamic worker option fields ([#19010](https://github.com/vitejs/vite/issues/19010)) ([d0c3523](https://github.com/vitejs/vite/commit/d0c35232c6ccbcf448941328df34d15e9f73919b))\n\n### Bug Fixes\n\n* avoid builtStart during vite optimize ([#19356](https://github.com/vitejs/vite/issues/19356)) ([fdb36e0](https://github.com/vitejs/vite/commit/fdb36e076969c763d4249f6db890f8bf26e9f5d1))\n* **build:** fix stale build manifest on watch rebuild ([#19361](https://github.com/vitejs/vite/issues/19361)) ([fcd5785](https://github.com/vitejs/vite/commit/fcd578587b2fbdef0ff8de8a0d97c9fc6da19ce1))\n* allow expanding env vars in reverse order ([#19352](https://github.com/vitejs/vite/issues/19352)) ([3f5f2bd](https://github.com/vitejs/vite/commit/3f5f2bddf142b2d1b162d4553d26f1ff0758b10d))\n* avoid packageJson without name in `resolveLibCssFilename` ([#19324](https://github.com/vitejs/vite/issues/19324)) ([f183bdf](https://github.com/vitejs/vite/commit/f183bdf2a799e703672ab1887d707ce120053eb2))\n* **html:** fix css disorder when building multiple entry html ([#19143](https://github.com/vitejs/vite/issues/19143)) ([e7b4ba3](https://github.com/vitejs/vite/commit/e7b4ba37f90a033036326b45023a1753584dd259))\n* **css:** less `[@plugin](https://github.com/plugin)` imports of JS files treated as CSS and rebased (fix [#19268](https://github.com/vitejs/vite/issues/19268)) ([#19269](https://github.com/vitejs/vite/issues/19269)) ([602b373](https://github.com/vitejs/vite/commit/602b373dcdc755816ce28913873f70550347e936))\n* **deps:** update all non-major dependencies ([#19296](https://github.com/vitejs/vite/issues/19296)) ([2bea7ce](https://github.com/vitejs/vite/commit/2bea7cec4b7fddbd5f2fb6090a7eaf5ae7ca0f1b))\n* don't call buildStart hooks for `vite optimize` ([#19347](https://github.com/vitejs/vite/issues/19347)) ([19ffad0](https://github.com/vitejs/vite/commit/19ffad0a5aaf8c0ff55409e746048431b8b6640d))\n* don't call next middleware if user sent response in proxy.bypass ([#19318](https://github.com/vitejs/vite/issues/19318)) ([7e6364d](https://github.com/vitejs/vite/commit/7e6364de2b0f3bf65aefaf451646ca500bad8239))\n* **resolve:** preserve hash/search of file url ([#19300](https://github.com/vitejs/vite/issues/19300)) ([d1e1b24](https://github.com/vitejs/vite/commit/d1e1b24c57328b5a808b981829503caa6ffadb56))\n* **resolve:** warn if node-like builtin was imported when `resolve.builtin` is empty ([#19312](https://github.com/vitejs/vite/issues/19312)) ([b7aba0b](https://github.com/vitejs/vite/commit/b7aba0bc925f6d672bbb6a1e6c8c5c123a3bef55))\n* respect top-level `server.preTransformRequests` ([#19272](https://github.com/vitejs/vite/issues/19272)) ([12aaa58](https://github.com/vitejs/vite/commit/12aaa585bc3fac403bf93f48ea117482cc7f43b1))\n* **ssr:** fix transform error due to export all id scope ([#19331](https://github.com/vitejs/vite/issues/19331)) ([e28bce2](https://github.com/vitejs/vite/commit/e28bce244918dac27b26d4e428f86b323a1c51ba))\n* **ssr:** pretty print plugin error in `ssrLoadModule` ([#19290](https://github.com/vitejs/vite/issues/19290)) ([353c467](https://github.com/vitejs/vite/commit/353c467610e2d92c0929fa4abd03f2cbd26e34ed))\n* use `nodeLikeBuiltins` for `ssr.target: 'webworker'` without `noExternal: true` ([#19313](https://github.com/vitejs/vite/issues/19313)) ([9fc31b6](https://github.com/vitejs/vite/commit/9fc31b6e4d4f2a5bd9711d4f84dcb55061ebead0))\n* change ResolvedConfig type to interface to allow extending it ([#19210](https://github.com/vitejs/vite/issues/19210)) ([bc851e3](https://github.com/vitejs/vite/commit/bc851e31d88cb26a2cba3fa46763bcd368e8df36))\n* correctly resolve hmr dep ids and fallback to url  ([#18840](https://github.com/vitejs/vite/issues/18840)) ([b84498b](https://github.com/vitejs/vite/commit/b84498b6def7d57ff6719da2d2baf6e29f0bb819))\n* **deps:** update all non-major dependencies ([#19190](https://github.com/vitejs/vite/issues/19190)) ([f2c07db](https://github.com/vitejs/vite/commit/f2c07dbfc874b46f6e09bb04996d0514663e4544))\n* **hmr:** register inlined assets as a dependency of CSS file ([#18979](https://github.com/vitejs/vite/issues/18979)) ([eb22a74](https://github.com/vitejs/vite/commit/eb22a74d29813d30be48d4413d785eedb0064b2c))\n* make `--force` work for all environments ([#18901](https://github.com/vitejs/vite/issues/18901)) ([51a42c6](https://github.com/vitejs/vite/commit/51a42c6b6a285fb1f092be5bbd2e18cd1fe2b214))\n* **resolve:** support resolving TS files by JS extension specifiers in JS files ([#18889](https://github.com/vitejs/vite/issues/18889)) ([612332b](https://github.com/vitejs/vite/commit/612332b9bbe8d489265aea31c9c9a712319abc51))\n* **ssr:** combine empty source mappings ([#19226](https://github.com/vitejs/vite/issues/19226)) ([ba03da2](https://github.com/vitejs/vite/commit/ba03da2a8c9ea6b26533cbcc4e50d58dc36499e2))\n* use loc.file from rollup errors if available ([#19222](https://github.com/vitejs/vite/issues/19222)) ([ce3fe23](https://github.com/vitejs/vite/commit/ce3fe236de625de745643e127e27f2a5b52c6d2e))\n* **utils:** clone `RegExp` values with `new RegExp` instead of `structuredClone` (fix [#19245](https://github.com/vitejs/vite/issues/19245), fix [#18875](https://github.com/vitejs/vite/issues/18875)) ([#19247](https://github.com/vitejs/vite/issues/19247)) ([56ad2be](https://github.com/vitejs/vite/commit/56ad2bef0353a4d00cd18789de7f4e7e5329d663))\n\n### Performance Improvements\n\n* **css:** only run postcss when needed ([#19061](https://github.com/vitejs/vite/issues/19061)) ([30194fa](https://github.com/vitejs/vite/commit/30194fa1e41dda6470aa20f2bb34655c4bfd9cd1))\n\n### Documentation\n\n* rephrase browser range and features relation ([#19286](https://github.com/vitejs/vite/issues/19286)) ([97569ef](https://github.com/vitejs/vite/commit/97569efd9d26b5c24d3a702d3171426f97c403cc))\n* update `build.manifest` jsdocs ([#19332](https://github.com/vitejs/vite/issues/19332)) ([4583781](https://github.com/vitejs/vite/commit/45837817dea1fd76fbc3dcf05ca7fcd46daa7b23))\n\n### Code Refactoring\n\n* deprecate `vite optimize` command ([#19348](https://github.com/vitejs/vite/issues/19348)) ([6e0e3c0](https://github.com/vitejs/vite/commit/6e0e3c0b990f1132db923e4599e18b270baa3a93))\n\n### Miscellaneous Chores\n\n* update deprecate links domain ([#19353](https://github.com/vitejs/vite/issues/19353)) ([2b2299c](https://github.com/vitejs/vite/commit/2b2299cbac37548a163f0523c0cb92eb70a9aacf))\n* **deps:** update dependency strip-literal to v3 ([#19231](https://github.com/vitejs/vite/issues/19231)) ([1172d65](https://github.com/vitejs/vite/commit/1172d655c19e689e03e6a6346eefe3ac7cc5baad))\n* remove outdated code comment about `scanImports` not being used in ssr ([#19285](https://github.com/vitejs/vite/issues/19285)) ([fbbc6da](https://github.com/vitejs/vite/commit/fbbc6da186d72b7c2ad1efce22d42d302f673516))\n* unneeded name in lockfileFormats ([#19275](https://github.com/vitejs/vite/issues/19275)) ([96092cb](https://github.com/vitejs/vite/commit/96092cb566ee50881edb391187d33f71af8f47b1))\n\n### Beta Changelogs\n\n\n#### [6.1.0-beta.2](https://github.com/vitejs/vite/compare/v6.1.0-beta.1...v6.1.0-beta.2) (2025-02-04)\n\nSee [6.1.0-beta.2 changelog](https://github.com/vitejs/vite/blob/v6.1.0-beta.2/packages/vite/CHANGELOG.md)\n\n\n#### [6.1.0-beta.1](https://github.com/vitejs/vite/compare/v6.1.0-beta.0...v6.1.0-beta.1) (2025-02-04)\n\nSee [6.1.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v6.1.0-beta.1/packages/vite/CHANGELOG.md)\n\n\n#### [6.1.0-beta.0](https://github.com/vitejs/vite/compare/v6.0.11...v6.1.0-beta.0) (2025-01-24)\n\nSee [6.1.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.10/packages/vite/CHANGELOG.md)\n\n## <small>[6.0.11](https://github.com/vitejs/vite/compare/v6.0.10...v6.0.11) (2025-01-21)</small>\n### Bug Fixes\n\n* `preview.allowedHosts` with specific values was not respected ([#19246](https://github.com/vitejs/vite/issues/19246)) ([aeb3ec8](https://github.com/vitejs/vite/commit/aeb3ec84a288d6be227a1284607f13428a4f14a1))\n* allow CORS from loopback addresses by default ([#19249](https://github.com/vitejs/vite/issues/19249)) ([3d03899](https://github.com/vitejs/vite/commit/3d038997377a30022b6a6b7916e0b4b5d8b9a363))\n\n## <small>[6.0.10](https://github.com/vitejs/vite/compare/v6.0.9...v6.0.10) (2025-01-20)</small>\n### Bug Fixes\n\n* try parse `server.origin` URL ([#19241](https://github.com/vitejs/vite/issues/19241)) ([2495022](https://github.com/vitejs/vite/commit/2495022420fda05ee389c2dcf26921b21e2aed3b))\n\n## <small>[6.0.9](https://github.com/vitejs/vite/compare/v6.0.8...v6.0.9) (2025-01-20)</small>\n### ⚠ BREAKING CHANGES\n\n* check host header to prevent DNS rebinding attacks and introduce `server.allowedHosts`\n* default `server.cors: false` to disallow fetching from untrusted origins\n\n### Bug Fixes\n\n* check host header to prevent DNS rebinding attacks and introduce `server.allowedHosts` ([bd896fb](https://github.com/vitejs/vite/commit/bd896fb5f312fc0ff1730166d1d142fc0d34ba6d))\n* default `server.cors: false` to disallow fetching from untrusted origins ([b09572a](https://github.com/vitejs/vite/commit/b09572acc939351f4e4c50ddf793017a92c678b1))\n* verify token for HMR WebSocket connection ([029dcd6](https://github.com/vitejs/vite/commit/029dcd6d77d3e3ef10bc38e9a0829784d9760fdb))\n\n## <small>[6.0.8](https://github.com/vitejs/vite/compare/v6.0.7...v6.0.8) (2025-01-20)</small>\n### Bug Fixes\n\n* avoid SSR HMR for HTML files ([#19193](https://github.com/vitejs/vite/issues/19193)) ([3bd55bc](https://github.com/vitejs/vite/commit/3bd55bcb7e831d2c4f66c90d7bbb3e1fbf7a02b6))\n* build time display 7m 60s ([#19108](https://github.com/vitejs/vite/issues/19108)) ([cf0d2c8](https://github.com/vitejs/vite/commit/cf0d2c8e232a1af716c71cdd2218d180f7ecc02b))\n* **deps:** update all non-major dependencies ([#19098](https://github.com/vitejs/vite/issues/19098)) ([8639538](https://github.com/vitejs/vite/commit/8639538e6498d1109da583ad942c1472098b5919))\n* don't resolve URL starting with double slash ([#19059](https://github.com/vitejs/vite/issues/19059)) ([35942cd](https://github.com/vitejs/vite/commit/35942cde11fd8a68fa89bf25f7aa1ddb87d775b2))\n* ensure `server.close()` only called once ([#19204](https://github.com/vitejs/vite/issues/19204)) ([db81c2d](https://github.com/vitejs/vite/commit/db81c2dada961f40c0882b5182adf2f34bb5c178))\n* **optimizer:** use correct default install state path for yarn PnP ([#19119](https://github.com/vitejs/vite/issues/19119)) ([e690d8b](https://github.com/vitejs/vite/commit/e690d8bb1e5741e81df5b7a6a5c8c3c1c971fa41))\n* resolve.conditions in ResolvedConfig was `defaultServerConditions` ([#19174](https://github.com/vitejs/vite/issues/19174)) ([ad75c56](https://github.com/vitejs/vite/commit/ad75c56dce5618a3a416e18f9a5c3880d437a107))\n* tree shake stringified JSON imports ([#19189](https://github.com/vitejs/vite/issues/19189)) ([f2aed62](https://github.com/vitejs/vite/commit/f2aed62d0bf1b66e870ee6b4aab80cd1702793ab))\n* **types:** improve `ESBuildOptions.include / exclude` type to allow `readonly (string | RegExp)[]` ([#19146](https://github.com/vitejs/vite/issues/19146)) ([ea53e70](https://github.com/vitejs/vite/commit/ea53e7095297ea4192490fd58556414cc59a8975))\n* use shared sigterm callback ([#19203](https://github.com/vitejs/vite/issues/19203)) ([47039f4](https://github.com/vitejs/vite/commit/47039f4643179be31a8d7c7fbff83c5c13deb787))\n\n### Miscellaneous Chores\n\n* **deps:** update dependency pathe to v2 ([#19139](https://github.com/vitejs/vite/issues/19139)) ([71506f0](https://github.com/vitejs/vite/commit/71506f0a8deda5254cb49c743cd439dfe42859ce))\n\n## <small>[6.0.7](https://github.com/vitejs/vite/compare/v6.0.6...v6.0.7) (2025-01-02)</small>\n### Features\n\n* **css:** show lightningcss warnings ([#19076](https://github.com/vitejs/vite/issues/19076)) ([b07c036](https://github.com/vitejs/vite/commit/b07c036faf6849fe5ffd03125f25dc00f460f8ba))\n\n### Bug Fixes\n\n* fix `minify` when `builder.sharedPlugins: true` ([#19025](https://github.com/vitejs/vite/issues/19025)) ([f7b1964](https://github.com/vitejs/vite/commit/f7b1964d3a93a21f80b61638fa6ae9606d0a6f4f))\n* **html:** error while removing `vite-ignore` attribute for inline script ([#19062](https://github.com/vitejs/vite/issues/19062)) ([a492253](https://github.com/vitejs/vite/commit/a4922537a8d705da7769d30626a0d846511fc124))\n* skip the plugin if it has been called before with the same id and importer ([#19016](https://github.com/vitejs/vite/issues/19016)) ([b178c90](https://github.com/vitejs/vite/commit/b178c90c7d175ea31f8b67dccad3918f820357a4))\n* **ssr:** fix semicolon injection by ssr transform ([#19097](https://github.com/vitejs/vite/issues/19097)) ([1c102d5](https://github.com/vitejs/vite/commit/1c102d517de52531faf5765632703977a17de65a))\n\n### Performance Improvements\n\n* skip globbing for static path in warmup ([#19107](https://github.com/vitejs/vite/issues/19107)) ([677508b](https://github.com/vitejs/vite/commit/677508bf8268a7b8661e5557a3d0a2a76cab8bd1))\n\n## <small>[6.0.6](https://github.com/vitejs/vite/compare/v6.0.5...v6.0.6) (2024-12-26)</small>\n### Bug Fixes\n\n* **css:** resolve style tags in HTML files correctly for lightningcss ([#19001](https://github.com/vitejs/vite/issues/19001)) ([afff05c](https://github.com/vitejs/vite/commit/afff05c03266fc76d5ab8928215c89f5992f40f8))\n* **css:** show correct error when unknown placeholder is used for CSS modules pattern in lightningcss ([#19070](https://github.com/vitejs/vite/issues/19070)) ([9290d85](https://github.com/vitejs/vite/commit/9290d85b5d2ad64991bd296157cb3bcb959c341d))\n* replace runner-side path normalization with `fetchModule`-side resolve ([#18361](https://github.com/vitejs/vite/issues/18361)) ([9f10261](https://github.com/vitejs/vite/commit/9f10261e7609098b832fd0fb23a64840b3a0d1a0))\n* **resolve:** handle package.json with UTF-8 BOM ([#19000](https://github.com/vitejs/vite/issues/19000)) ([902567a](https://github.com/vitejs/vite/commit/902567ac5327e915ce65d090045fa4922ef9f2b5))\n* **ssrTransform:** preserve line offset when transforming imports ([#19004](https://github.com/vitejs/vite/issues/19004)) ([1aa434e](https://github.com/vitejs/vite/commit/1aa434e8017012bf0939b2ff1a3a66b4bd12b76d))\n\n### Reverts\n\n* unpin esbuild version ([#19043](https://github.com/vitejs/vite/issues/19043)) ([8bfe247](https://github.com/vitejs/vite/commit/8bfe247511517c631a26f3931bb3c93a7b0b7446))\n\n### Miscellaneous Chores\n\n* fix typo in comment ([#19067](https://github.com/vitejs/vite/issues/19067)) ([eb06ec3](https://github.com/vitejs/vite/commit/eb06ec30bb02ced66274f0fc6e90aff2bb20c632))\n* update comment about `build.target` ([#19047](https://github.com/vitejs/vite/issues/19047)) ([0e9e81f](https://github.com/vitejs/vite/commit/0e9e81f622f13d78ee238c0fa72ba920e23419f4))\n\n### Tests\n\n* **ssr:** test virtual module with query ([#19044](https://github.com/vitejs/vite/issues/19044)) ([a1f4b46](https://github.com/vitejs/vite/commit/a1f4b46896cb4b442b54a8336db8eca6df9ee02d))\n\n## <small>[6.0.5](https://github.com/vitejs/vite/compare/v6.0.4...v6.0.5) (2024-12-20)</small>\n### Bug Fixes\n\n* esbuild regression (pin to 0.24.0) ([#19027](https://github.com/vitejs/vite/issues/19027)) ([4359e0d](https://github.com/vitejs/vite/commit/4359e0d5b33afd6259a4dcef787cc2670e963126))\n\n## <small>[6.0.4](https://github.com/vitejs/vite/compare/v6.0.3...v6.0.4) (2024-12-19)</small>\n### Bug Fixes\n\n* `this.resolve` skipSelf should not skip for different `id` or `import` ([#18903](https://github.com/vitejs/vite/issues/18903)) ([4727320](https://github.com/vitejs/vite/commit/472732057cb2273908e1fca8aa7dc18a7e1f7c74))\n* **css:** escape double quotes in `url()` when lightningcss is used ([#18997](https://github.com/vitejs/vite/issues/18997)) ([3734f80](https://github.com/vitejs/vite/commit/3734f8099e3922c189497ce404fe7ff2f8929ae1))\n* **css:** root relative import in sass modern API on Windows ([#18945](https://github.com/vitejs/vite/issues/18945)) ([c4b532c](https://github.com/vitejs/vite/commit/c4b532cc900bf988073583511f57bd581755d5e3))\n* **css:** skip non css in custom sass importer ([#18970](https://github.com/vitejs/vite/issues/18970)) ([21680bd](https://github.com/vitejs/vite/commit/21680bdf9ca7c12f677136b56e47f46469db8be2))\n* **deps:** update all non-major dependencies ([#18967](https://github.com/vitejs/vite/issues/18967)) ([d88d000](https://github.com/vitejs/vite/commit/d88d0004a8e891ca6026d356695e0b319caa7fce))\n* **deps:** update all non-major dependencies ([#18996](https://github.com/vitejs/vite/issues/18996)) ([2b4f115](https://github.com/vitejs/vite/commit/2b4f115129fb3fbd730a92078acb724f8527b7f7))\n* fallback terser to main thread when function options are used ([#18987](https://github.com/vitejs/vite/issues/18987)) ([12b612d](https://github.com/vitejs/vite/commit/12b612d8be2a18456fd94a2f0291d32d1ffb29d4))\n* merge client and ssr values for `pluginContainer.getModuleInfo` ([#18895](https://github.com/vitejs/vite/issues/18895)) ([258cdd6](https://github.com/vitejs/vite/commit/258cdd637d1ee80a3c4571685135e89fe283f3a6))\n* **optimizer:** keep NODE_ENV as-is when keepProcessEnv is `true` ([#18899](https://github.com/vitejs/vite/issues/18899)) ([8a6bb4e](https://github.com/vitejs/vite/commit/8a6bb4e11d5c1b61511ae1e5ed3ae3c65a33b2dc))\n* **ssr:** recreate ssrCompatModuleRunner on restart ([#18973](https://github.com/vitejs/vite/issues/18973)) ([7d6dd5d](https://github.com/vitejs/vite/commit/7d6dd5d1d655d173668192509f63ac4ebf7af299))\n\n### Miscellaneous Chores\n\n* better validation error message for dts build ([#18948](https://github.com/vitejs/vite/issues/18948)) ([63b82f1](https://github.com/vitejs/vite/commit/63b82f1e29a00d06a82144fd03ea8d6eff114290))\n* **deps:** update all non-major dependencies ([#18916](https://github.com/vitejs/vite/issues/18916)) ([ef7a6a3](https://github.com/vitejs/vite/commit/ef7a6a35e6827b92445e5a0c2c0022616efc80dd))\n* **deps:** update dependency @rollup/plugin-node-resolve to v16 ([#18968](https://github.com/vitejs/vite/issues/18968)) ([62fad6d](https://github.com/vitejs/vite/commit/62fad6d79f83daf916dde866909a2a3dd0c79583))\n\n### Code Refactoring\n\n* make internal invoke event to use the same interface with `handleInvoke` ([#18902](https://github.com/vitejs/vite/issues/18902)) ([27f691b](https://github.com/vitejs/vite/commit/27f691b0c7dca2259108fe6b79583b459429bf7f))\n* simplify manifest plugin code ([#18890](https://github.com/vitejs/vite/issues/18890)) ([1bfe21b](https://github.com/vitejs/vite/commit/1bfe21b9440f318c940f90e425a18588595225fd))\n\n### Tests\n\n* test `ModuleRunnerTransport` `invoke` API ([#18865](https://github.com/vitejs/vite/issues/18865)) ([e5f5301](https://github.com/vitejs/vite/commit/e5f5301924b775837b2a1253c37f76555bce3e3e))\n* test output hash changes ([#18898](https://github.com/vitejs/vite/issues/18898)) ([bfbb130](https://github.com/vitejs/vite/commit/bfbb130fccefbe7e3880f09defb4fceacce39481))\n\n## <small>[6.0.3](https://github.com/vitejs/vite/compare/v6.0.2...v6.0.3) (2024-12-05)</small>\n### Bug Fixes\n\n* **config:** bundle files referenced with imports field ([#18887](https://github.com/vitejs/vite/issues/18887)) ([2b5926a](https://github.com/vitejs/vite/commit/2b5926a0e79ce47d22536d38eed2629d326caca0))\n* **config:** make stacktrace path correct when sourcemap is enabled ([#18833](https://github.com/vitejs/vite/issues/18833)) ([20fdf21](https://github.com/vitejs/vite/commit/20fdf210ee0ac0824b2db74876527cb7f378a9e8))\n* **css:** rewrite url when image-set and url exist at the same time ([#18868](https://github.com/vitejs/vite/issues/18868)) ([d59efd8](https://github.com/vitejs/vite/commit/d59efd8dfd1c5bf2e7c45c7cdb1c0abc2a05ba02))\n* **deps:** update all non-major dependencies ([#18853](https://github.com/vitejs/vite/issues/18853)) ([5c02236](https://github.com/vitejs/vite/commit/5c0223636fa277d5daeb4d93c3f32d9f3cd69fc5))\n* handle postcss load unhandled rejections ([#18886](https://github.com/vitejs/vite/issues/18886)) ([d5fb653](https://github.com/vitejs/vite/commit/d5fb653c15903ccf84a093f212da86f0327a9a6f))\n* **html:** allow unexpected question mark in tag name ([#18852](https://github.com/vitejs/vite/issues/18852)) ([1b54e50](https://github.com/vitejs/vite/commit/1b54e506a44420d0c8a9e000cf45b1c4f5e33026))\n* make handleInvoke interface compatible with invoke ([#18876](https://github.com/vitejs/vite/issues/18876)) ([a1dd396](https://github.com/vitejs/vite/commit/a1dd396da856401a12c921d0cd2c4e97cb63f1b5))\n* make result interfaces for `ModuleRunnerTransport[#invoke](https://github.com/vitejs/vite/issues/invoke)` more explicit ([#18851](https://github.com/vitejs/vite/issues/18851)) ([a75fc31](https://github.com/vitejs/vite/commit/a75fc3193d5e8d8756dfb3a046873e9c222bb6c8))\n* merge `environments.ssr.resolve` with root `ssr` config ([#18857](https://github.com/vitejs/vite/issues/18857)) ([3104331](https://github.com/vitejs/vite/commit/310433106e1e8a0c39dc397e3eace8a71a2416c2))\n* **module-runner:** decode uri for file url passed to import ([#18837](https://github.com/vitejs/vite/issues/18837)) ([88e49aa](https://github.com/vitejs/vite/commit/88e49aa0418cb3f6b579b744ba59daeda68432f3))\n* no permission to create vite config file ([#18844](https://github.com/vitejs/vite/issues/18844)) ([ff47778](https://github.com/vitejs/vite/commit/ff47778004d609dbeef7f192783e6f253dd66237))\n* remove CSS import in CJS correctly in some cases ([#18885](https://github.com/vitejs/vite/issues/18885)) ([690a36f](https://github.com/vitejs/vite/commit/690a36ffdb7d6f6568f35a304b4904e7aa475f17))\n\n### Miscellaneous Chores\n\n* fix duplicate attributes issue number in comment ([#18860](https://github.com/vitejs/vite/issues/18860)) ([ffee618](https://github.com/vitejs/vite/commit/ffee61893cfe9f2b0db4aecf9ddb62ca79c80458))\n\n### Code Refactoring\n\n* fix logic errors found by no-unnecessary-condition rule ([#18891](https://github.com/vitejs/vite/issues/18891)) ([ea802f8](https://github.com/vitejs/vite/commit/ea802f8f8bcf3771a35c1eaf687378613fbabb24))\n\n## <small>[6.0.2](https://github.com/vitejs/vite/compare/v6.0.1...v6.0.2) (2024-12-02)</small>\n### Features\n\n* **css:** format lightningcss error ([#18818](https://github.com/vitejs/vite/issues/18818)) ([dac7992](https://github.com/vitejs/vite/commit/dac7992e8725234007c7515f86f543992874c7b8))\n\n### Bug Fixes\n\n* **css:** referencing aliased svg asset with lightningcss enabled errored ([#18819](https://github.com/vitejs/vite/issues/18819)) ([ae68958](https://github.com/vitejs/vite/commit/ae6895869157e48b32088f0a1f85d2fddb2d713f))\n* don't store temporary vite config file in `node_modules` if deno ([#18823](https://github.com/vitejs/vite/issues/18823)) ([a20267b](https://github.com/vitejs/vite/commit/a20267bb93118468a2e20f0f77b77ed7bfa94165))\n* **manifest:** use `style.css` as a key for the style file for `cssCodesplit: false` ([#18820](https://github.com/vitejs/vite/issues/18820)) ([ec51115](https://github.com/vitejs/vite/commit/ec511152558cb573acf55e88e5244bdead1b5a17))\n* **optimizer:** resolve all promises when cancelled ([#18826](https://github.com/vitejs/vite/issues/18826)) ([d6e6194](https://github.com/vitejs/vite/commit/d6e6194706f0e3a889caa9303de2293cc0f131b2))\n* **resolve:** don't set builtinModules to `external` by default ([#18821](https://github.com/vitejs/vite/issues/18821)) ([2250ffa](https://github.com/vitejs/vite/commit/2250ffac62e55c89232d745d2f99ece539be9195))\n* **ssr:** set `ssr.target: 'webworker'` defaults as fallback ([#18827](https://github.com/vitejs/vite/issues/18827)) ([b39e696](https://github.com/vitejs/vite/commit/b39e69638b3e2e658ff6712be83b549b28103c3d))\n\n### Miscellaneous Chores\n\n* run typecheck in unit tests ([#18858](https://github.com/vitejs/vite/issues/18858)) ([49f20bb](https://github.com/vitejs/vite/commit/49f20bb77749ec7b44344fd9c42d593ae20c78f0))\n* update broken links in changelog ([#18802](https://github.com/vitejs/vite/issues/18802)) ([cb754f8](https://github.com/vitejs/vite/commit/cb754f8acc1b579dae9fe70a08e3ef53984402cc))\n* update broken links in changelog ([#18804](https://github.com/vitejs/vite/issues/18804)) ([47ec49f](https://github.com/vitejs/vite/commit/47ec49ffa170cac5d04cf2eef01f45e0b5ccde03))\n\n### Code Refactoring\n\n* make properties of ResolvedServerOptions and ResolvedPreviewOptions required ([#18796](https://github.com/vitejs/vite/issues/18796)) ([51a5569](https://github.com/vitejs/vite/commit/51a5569e66bd7f0de79ac14b9e902d1382ccd0aa))\n\n## <small>[6.0.1](https://github.com/vitejs/vite/compare/v6.0.0...v6.0.1) (2024-11-27)</small>\n### Bug Fixes\n\n* default empty server `proxy` prevents starting http2 server ([#18788](https://github.com/vitejs/vite/issues/18788)) ([bbaf514](https://github.com/vitejs/vite/commit/bbaf514fb718952e0f17a15545c593125f1d1b9c))\n* **manifest:** do not override existing js manifest entry  ([#18776](https://github.com/vitejs/vite/issues/18776)) ([3b0837e](https://github.com/vitejs/vite/commit/3b0837e0b997e14dacc347719353b8b0cea35bda))\n* **server:** close _ssrCompatModuleRunner on server close ([#18784](https://github.com/vitejs/vite/issues/18784)) ([9b4c410](https://github.com/vitejs/vite/commit/9b4c410dddb80c8858549355e175735976a82134))\n* **server:** skip hot channel client normalization for wsServer  ([#18782](https://github.com/vitejs/vite/issues/18782)) ([cc7670a](https://github.com/vitejs/vite/commit/cc7670abaffeda1338cf3acfef2bc41a38c223a0))\n* **worker:** fix `applyToEnvironment` hooks on worker build ([#18793](https://github.com/vitejs/vite/issues/18793)) ([0c6cdb0](https://github.com/vitejs/vite/commit/0c6cdb0f88d32ce041272977e786006008223f44))\n\n### Reverts\n\n* update moduleResolution value casing ([#18409](https://github.com/vitejs/vite/issues/18409)) ([#18774](https://github.com/vitejs/vite/issues/18774)) ([b0fc6e3](https://github.com/vitejs/vite/commit/b0fc6e3c2591a30360d3714263cf7cc0e2acbfdf))\n\n### Miscellaneous Chores\n\n* flat v6 config file ([#18777](https://github.com/vitejs/vite/issues/18777)) ([c7b3308](https://github.com/vitejs/vite/commit/c7b330832675ee6385ee1a8750762e496c8e18e6))\n* split changelog ([#18787](https://github.com/vitejs/vite/issues/18787)) ([8542632](https://github.com/vitejs/vite/commit/8542632b3b205b61999b6d998928d5fb17ba90c4))\n* update changelog for v6 ([#18773](https://github.com/vitejs/vite/issues/18773)) ([b254fac](https://github.com/vitejs/vite/commit/b254fac4aa35a3522aeafb3259e60acd050aeb51))\n\n## [6.0.0](https://github.com/vitejs/vite/compare/v6.0.0-beta.10...v6.0.0) (2024-11-26)\n\n![Vite 6 is out!](../../docs/public/og-image-announcing-vite6.png)\n\nToday, we're taking another big step in Vite's story. The Vite [team](https://vite.dev/team), [contributors](https://github.com/vitejs/vite/graphs/contributors), and ecosystem partners are excited to announce the release of the next Vite major:\n\n- **[Vite 6.0 announcement blog post](https://vite.dev/blog/announcing-vite6.html)**\n- [Docs](https://vite.dev/)\n- Translations: [简体中文](https://cn.vite.dev/), [日本語](https://ja.vite.dev/), [Español](https://es.vite.dev/), [Português](https://pt.vite.dev/), [한국어](https://ko.vite.dev/), [Deutsch](https://de.vite.dev/)\n- [Migration Guide](https://vite.dev/guide/migration.html)\n\nWe want to thank the more than [1K contributors to Vite Core](https://github.com/vitejs/vite/graphs/contributors) and the maintainers and contributors of Vite plugins, integrations, tools, and translations that have helped us craft this new major. We invite you to get involved and help us improve Vite for the whole ecosystem. Learn more at our [Contributing Guide](https://github.com/vitejs/vite/blob/main/CONTRIBUTING.md).\n\n### ⚠ BREAKING CHANGES\n\n* drop node 21 support in version ranges (#18729)\n* **deps:** update dependency dotenv-expand to v12 (#18697)\n* **resolve:** allow removing conditions (#18395)\n* **html:** support more asset sources (#11138)\n* remove fs.cachedChecks option (#18493)\n* proxy bypass with WebSocket (#18070)\n* **css:** remove default import in ssr dev (#17922)\n* **lib:** use package name for css output file name (#18488)\n* update to chokidar v4 (#18453)\n* support `file://` resolution (#18422)\n* **deps:** update postcss-load-config to v6 (#15235)\n* **css:** change default sass api to modern/modern-compiler (#17937)\n* **css:** load postcss config within workspace root only (#18440)\n* default `build.cssMinify` to `'esbuild'` for SSR (#15637)\n* **json:** add `json.stringify: 'auto'` and make that the default (#18303)\n* bump minimal terser version to 5.16.0 (#18209)\n* **deps:** migrate `fast-glob` to `tinyglobby` (#18243)\n\n### Features\n\n* add support for .cur type ([#18680](https://github.com/vitejs/vite/issues/18680)) ([5ec9eed](https://github.com/vitejs/vite/commit/5ec9eedc80bbf39a33b498198ba07ed1bd9cacc7))\n* drop node 21 support in version ranges ([#18729](https://github.com/vitejs/vite/issues/18729)) ([a384d8f](https://github.com/vitejs/vite/commit/a384d8fd39162190675abcfea31ba657383a3d03))\n* enable HMR by default on ModuleRunner side ([#18749](https://github.com/vitejs/vite/issues/18749)) ([4d2abc7](https://github.com/vitejs/vite/commit/4d2abc7bba95cf516ce7341d5d8f349d61b75224))\n* support `module-sync` condition when loading config if enabled ([#18650](https://github.com/vitejs/vite/issues/18650)) ([cf5028d](https://github.com/vitejs/vite/commit/cf5028d4bf0a0d59b4a98323beaadc268204056b))\n* add `isSsrTargetWebWorker` flag to `configEnvironment` hook ([#18620](https://github.com/vitejs/vite/issues/18620)) ([3f5fab0](https://github.com/vitejs/vite/commit/3f5fab04aa64c0e9b45068e842f033583b365de0))\n* add `ssr.resolve.mainFields` option ([#18646](https://github.com/vitejs/vite/issues/18646)) ([a6f5f5b](https://github.com/vitejs/vite/commit/a6f5f5baca7a5d2064f5f4cb689764ad939fab4b))\n* expose default mainFields/conditions ([#18648](https://github.com/vitejs/vite/issues/18648)) ([c12c653](https://github.com/vitejs/vite/commit/c12c653ca5fab354e0f71394e2fbe636dccf6b2f))\n* extended applyToEnvironment and perEnvironmentPlugin ([#18544](https://github.com/vitejs/vite/issues/18544)) ([8fa70cd](https://github.com/vitejs/vite/commit/8fa70cdfa65ce8254ab8da8be0d92614126764c0))\n* **optimizer:** allow users to specify their esbuild `platform` option ([#18611](https://github.com/vitejs/vite/issues/18611)) ([0924879](https://github.com/vitejs/vite/commit/09248795ca79a7053b803af8977c3422f5cd5824))\n* show error when accessing variables not exposed in CJS build ([#18649](https://github.com/vitejs/vite/issues/18649)) ([87c5502](https://github.com/vitejs/vite/commit/87c55022490d4710934c482abf5fbd4fcda9c3c9))\n* **asset:** add `?inline` and `?no-inline` queries to control inlining ([#15454](https://github.com/vitejs/vite/issues/15454)) ([9162172](https://github.com/vitejs/vite/commit/9162172e039ae67ad4ee8dce18f04b7444f7d9de))\n* **asset:** inline svg in dev if within limit ([#18581](https://github.com/vitejs/vite/issues/18581)) ([f08b146](https://github.com/vitejs/vite/commit/f08b1463db50f39b571faa871d05c92b10f3434c))\n* use a single transport for fetchModule and HMR support ([#18362](https://github.com/vitejs/vite/issues/18362)) ([78dc490](https://github.com/vitejs/vite/commit/78dc4902ffef7f316e84d21648b04dc62dd0ae0a))\n* **html:** support more asset sources ([#11138](https://github.com/vitejs/vite/issues/11138)) ([8a7af50](https://github.com/vitejs/vite/commit/8a7af50b5ddf72f21098406e9668bc609b323899))\n* **resolve:** allow removing conditions ([#18395](https://github.com/vitejs/vite/issues/18395)) ([d002e7d](https://github.com/vitejs/vite/commit/d002e7d05a0f23110f9185b39222819bcdfffc16))\n* **html:** support `vite-ignore` attribute to opt-out of processing ([#18494](https://github.com/vitejs/vite/issues/18494)) ([d951310](https://github.com/vitejs/vite/commit/d9513104e21175e1d23e0f614df55cd53291ab4e))\n* **lib:** use package name for css output file name ([#18488](https://github.com/vitejs/vite/issues/18488)) ([61cbf6f](https://github.com/vitejs/vite/commit/61cbf6f2cfcd5afc91fe0a0ad56abfc36a32f1ab))\n* log complete config in debug mode ([#18289](https://github.com/vitejs/vite/issues/18289)) ([04f6736](https://github.com/vitejs/vite/commit/04f6736fd7ac3da22141929c01a151f5a6fe4e45))\n* proxy bypass with WebSocket ([#18070](https://github.com/vitejs/vite/issues/18070)) ([3c9836d](https://github.com/vitejs/vite/commit/3c9836d96f118ff5748916241bc3871a54247ad1))\n* support `file://` resolution ([#18422](https://github.com/vitejs/vite/issues/18422)) ([6a7e313](https://github.com/vitejs/vite/commit/6a7e313754dce5faa5cd7c1e2343448cd7f3a2a2))\n* update to chokidar v4 ([#18453](https://github.com/vitejs/vite/issues/18453)) ([192d555](https://github.com/vitejs/vite/commit/192d555f88bba7576e8a40cc027e8a11e006079c))\n* allow custom `console` in `createLogger` ([#18379](https://github.com/vitejs/vite/issues/18379)) ([0c497d9](https://github.com/vitejs/vite/commit/0c497d9cb63bd4a6bb8e01c0e3b843890a239d23))\n* **css:** add more stricter typing of lightningcss ([#18460](https://github.com/vitejs/vite/issues/18460)) ([b9b925e](https://github.com/vitejs/vite/commit/b9b925eb3f911ab63972124dc8ab0455449b925d))\n* **css:** change default sass api to modern/modern-compiler ([#17937](https://github.com/vitejs/vite/issues/17937)) ([d4e0442](https://github.com/vitejs/vite/commit/d4e0442f9d6adc70b72ea0713dc8abb4b1f75ae4))\n* read `sec-fetch-dest` header to detect JS in transform ([#9981](https://github.com/vitejs/vite/issues/9981)) ([e51dc40](https://github.com/vitejs/vite/commit/e51dc40b5907cf14d7aefaaf01fb8865a852ef15))\n* **css:** load postcss config within workspace root only ([#18440](https://github.com/vitejs/vite/issues/18440)) ([d23a493](https://github.com/vitejs/vite/commit/d23a493cc4b54a2e2b2c1337b3b1f0c9b1be311e))\n* **json:** add `json.stringify: 'auto'` and make that the default ([#18303](https://github.com/vitejs/vite/issues/18303)) ([b80daa7](https://github.com/vitejs/vite/commit/b80daa7c0970645dca569d572892648f66c6799c))\n* add .git to deny list by default ([#18382](https://github.com/vitejs/vite/issues/18382)) ([105ca12](https://github.com/vitejs/vite/commit/105ca12b34e466dc9de838643954a873ac1ce804))\n* add `environment::listen` ([#18263](https://github.com/vitejs/vite/issues/18263)) ([4d5f51d](https://github.com/vitejs/vite/commit/4d5f51d13f92cc8224a028c27df12834a0667659))\n* enable dependencies discovery and pre-bundling in ssr environments ([#18358](https://github.com/vitejs/vite/issues/18358)) ([9b21f69](https://github.com/vitejs/vite/commit/9b21f69405271f1b864fa934a96adcb0e1a2bc4d))\n* restrict characters useable for environment name ([#18255](https://github.com/vitejs/vite/issues/18255)) ([9ab6180](https://github.com/vitejs/vite/commit/9ab6180d3a20be71eb7aedef000f8c4ae3591c40))\n* support arbitrary module namespace identifier imports from cjs deps ([#18236](https://github.com/vitejs/vite/issues/18236)) ([4389a91](https://github.com/vitejs/vite/commit/4389a917f8f5e8e67222809fb7b166bb97f6d02c))\n* introduce RunnableDevEnvironment ([#18190](https://github.com/vitejs/vite/issues/18190)) ([fb292f2](https://github.com/vitejs/vite/commit/fb292f226f988e80fee4f4aea878eb3d5d229022))\n* support `this.environment` in `options` and `onLog` hook ([#18142](https://github.com/vitejs/vite/issues/18142)) ([7722c06](https://github.com/vitejs/vite/commit/7722c061646bc8587f55f560bfe06b2a9643639a))\n* **css:** support es2023 build target for lightningcss ([#17998](https://github.com/vitejs/vite/issues/17998)) ([1a76300](https://github.com/vitejs/vite/commit/1a76300cd16827f0640924fdc21747ce140c35fb))\n* Environment API ([#16471](https://github.com/vitejs/vite/issues/16471)) ([242f550](https://github.com/vitejs/vite/commit/242f550eb46c93896fca6b55495578921e29a8af))\n* expose `EnvironmentOptions` type ([#18080](https://github.com/vitejs/vite/issues/18080)) ([35cf59c](https://github.com/vitejs/vite/commit/35cf59c9d53ef544eb5f2fe2f9ff4d6cb225e63b))\n\n### Bug Fixes\n\n* `createRunnableDevEnvironment` returns `RunnableDevEnvironment`, not `DevEnvironment` ([#18673](https://github.com/vitejs/vite/issues/18673)) ([74221c3](https://github.com/vitejs/vite/commit/74221c391bffd61b9ef39b7c0f9ea2e405913a6f))\n* `getModulesByFile` should return a `serverModule` ([#18715](https://github.com/vitejs/vite/issues/18715)) ([b80d5ec](https://github.com/vitejs/vite/commit/b80d5ecbbcc374bd8f32b2ed5ceb3cbfffaae77b))\n* catch error in full reload handler ([#18713](https://github.com/vitejs/vite/issues/18713)) ([a10e741](https://github.com/vitejs/vite/commit/a10e7410656d3614cbfd07ba772776ff334a8d60))\n* **client:** overlay not appearing when multiple vite clients were loaded ([#18647](https://github.com/vitejs/vite/issues/18647)) ([27d70b5](https://github.com/vitejs/vite/commit/27d70b5fa61f1c1a836d52809549cb57569f42a4))\n* **deps:** update all non-major dependencies ([#18691](https://github.com/vitejs/vite/issues/18691)) ([f005461](https://github.com/vitejs/vite/commit/f005461ecce89ada21cb0c021f7af460b5479736))\n* **deps:** update dependency dotenv-expand to v12 ([#18697](https://github.com/vitejs/vite/issues/18697)) ([0c658de](https://github.com/vitejs/vite/commit/0c658de41f4c1576c526a8c48a8ea0a019c6311c))\n* display pre-transform error details ([#18764](https://github.com/vitejs/vite/issues/18764)) ([554f45f](https://github.com/vitejs/vite/commit/554f45f4d820c57c0874ebe48ef2fddfafdd0750))\n* exit code on `SIGTERM` ([#18741](https://github.com/vitejs/vite/issues/18741)) ([cc55e36](https://github.com/vitejs/vite/commit/cc55e36dd39fef134568f53acc66514cbb7175ea))\n* expose missing `InterceptorOptions` type ([#18766](https://github.com/vitejs/vite/issues/18766)) ([6252c60](https://github.com/vitejs/vite/commit/6252c6035695365c93773fbe06a4b2a307e86368))\n* **html:** fix inline proxy modules invalidation ([#18696](https://github.com/vitejs/vite/issues/18696)) ([8ab04b7](https://github.com/vitejs/vite/commit/8ab04b70ada119fbca2fc5a53c36f233423febbe))\n* log error when send in module runner failed ([#18753](https://github.com/vitejs/vite/issues/18753)) ([ba821bb](https://github.com/vitejs/vite/commit/ba821bb63eca6d8a9199ee2253ef2607375f5702))\n* **module-runner:** make evaluator optional ([#18672](https://github.com/vitejs/vite/issues/18672)) ([fd1283f](https://github.com/vitejs/vite/commit/fd1283fe27cc1a19b5c7d9d72664832e4daa1bbf))\n* **optimizer:** detect npm / yarn / pnpm dependency changes correctly ([#17336](https://github.com/vitejs/vite/issues/17336)) ([#18560](https://github.com/vitejs/vite/issues/18560)) ([818cf3e](https://github.com/vitejs/vite/commit/818cf3e7bf1b6c2dc56e7cd8f056bc1d185c2cd7))\n* **optimizer:** trigger onCrawlEnd after manual included deps are registered ([#18733](https://github.com/vitejs/vite/issues/18733)) ([dc60410](https://github.com/vitejs/vite/commit/dc6041099ccd5767764fb8c99a169869bbd13f16))\n* **optimizer:** workaround firefox's false warning for no sources source map ([#18665](https://github.com/vitejs/vite/issues/18665)) ([473424e](https://github.com/vitejs/vite/commit/473424ee8d6b743c1565bf0749deb5d9fbedcea7))\n* **ssr:** replace `__vite_ssr_identity__` with `(0, ...)` and inject `;` between statements ([#18748](https://github.com/vitejs/vite/issues/18748)) ([94546be](https://github.com/vitejs/vite/commit/94546be18354a457bced5107aa31533b09e304ec))\n* cjs build for perEnvironmentState et al ([#18656](https://github.com/vitejs/vite/issues/18656)) ([95c4b3c](https://github.com/vitejs/vite/commit/95c4b3c371dc7fb12c28cb1307f6f389887eb1e1))\n* **html:** externalize `rollup.external` scripts correctly ([#18618](https://github.com/vitejs/vite/issues/18618)) ([55461b4](https://github.com/vitejs/vite/commit/55461b43329db6a5e737eab591163a8681ba9230))\n* include more modules to prefix-only module list ([#18667](https://github.com/vitejs/vite/issues/18667)) ([5a2103f](https://github.com/vitejs/vite/commit/5a2103f0d486a7725c23c70710b11559c00e9b93))\n* **ssr:** format `ssrTransform` parse error  ([#18644](https://github.com/vitejs/vite/issues/18644)) ([d9be921](https://github.com/vitejs/vite/commit/d9be92187cb17d740856af27d0ab60c84e04d58c))\n* **ssr:** preserve fetchModule error details ([#18626](https://github.com/vitejs/vite/issues/18626)) ([866a433](https://github.com/vitejs/vite/commit/866a433a34ab2f6d2910506e781b346091de1b9e))\n* browser field should not be included by default for `consumer: 'server'` ([#18575](https://github.com/vitejs/vite/issues/18575)) ([87b2347](https://github.com/vitejs/vite/commit/87b2347a13ea8ae8282f0f1e2233212c040bfed8))\n* **client:** detect ws close correctly ([#18548](https://github.com/vitejs/vite/issues/18548)) ([637d31b](https://github.com/vitejs/vite/commit/637d31bcc59d964e51f7969093cc369deee88ca1))\n* **resolve:** run ensureVersionQuery for SSR ([#18591](https://github.com/vitejs/vite/issues/18591)) ([63207e5](https://github.com/vitejs/vite/commit/63207e5d0fbedc8ddddb7d1faaa8ea9a45a118d4))\n* use `server.perEnvironmentStartEndDuringDev` ([#18549](https://github.com/vitejs/vite/issues/18549)) ([fe30349](https://github.com/vitejs/vite/commit/fe30349d350ef08bccd56404ccc3e6d6e0a2e156))\n* allow nested dependency selector to be used for `optimizeDeps.include` for SSR ([#18506](https://github.com/vitejs/vite/issues/18506)) ([826c81a](https://github.com/vitejs/vite/commit/826c81a40bb25914d55cd2e96b548f1a2c384a19))\n* asset `new URL(,import.meta.url)` match ([#18194](https://github.com/vitejs/vite/issues/18194)) ([5286a90](https://github.com/vitejs/vite/commit/5286a90a3c1b693384f99903582a1f70b7b44945))\n* close watcher if it's disabled ([#18521](https://github.com/vitejs/vite/issues/18521)) ([85bd0e9](https://github.com/vitejs/vite/commit/85bd0e9b0dc637c7645f2b56f93071d6e1ec149c))\n* **config:** write temporary vite config to node_modules ([#18509](https://github.com/vitejs/vite/issues/18509)) ([72eaef5](https://github.com/vitejs/vite/commit/72eaef5300d20b7163050461733c3208a4013e1e))\n* **css:** `cssCodeSplit` uses the current environment configuration ([#18486](https://github.com/vitejs/vite/issues/18486)) ([eefe895](https://github.com/vitejs/vite/commit/eefe8957167681b85f0e1b07bc5feefa307cccb0))\n* **json:** don't `json.stringify` arrays ([#18541](https://github.com/vitejs/vite/issues/18541)) ([fa50b03](https://github.com/vitejs/vite/commit/fa50b03390dae280293174f65f850522599b9ab7))\n* **less:** prevent rebasing `[@import](https://github.com/import) url(...)` ([#17857](https://github.com/vitejs/vite/issues/17857)) ([aec5fdd](https://github.com/vitejs/vite/commit/aec5fdd72e3aeb2aa26796001b98f3f330be86d1))\n* **lib:** only resolve css bundle name if have styles ([#18530](https://github.com/vitejs/vite/issues/18530)) ([5d6dc49](https://github.com/vitejs/vite/commit/5d6dc491b6bb78613694eaf686e2e305b71af5e1))\n* **scss:** improve error logs ([#18522](https://github.com/vitejs/vite/issues/18522)) ([3194a6a](https://github.com/vitejs/vite/commit/3194a6a60714a3978f5e4b39d6223f32a8dc01ef))\n* `define` in environment config was not working ([#18515](https://github.com/vitejs/vite/issues/18515)) ([052799e](https://github.com/vitejs/vite/commit/052799e8939cfcdd7a7ff48daf45a766bf6cc546))\n* **build:** apply resolve.external/noExternal to server environments ([#18495](https://github.com/vitejs/vite/issues/18495)) ([5a967cb](https://github.com/vitejs/vite/commit/5a967cb596c7c4b0548be1d9025bc1e34b36169a))\n* **config:** remove error if require resolve to esm ([#18437](https://github.com/vitejs/vite/issues/18437)) ([f886f75](https://github.com/vitejs/vite/commit/f886f75396cdb5a43ec5377bbbaaffc0e8ae03e9))\n* consider URLs with any protocol to be external ([#17369](https://github.com/vitejs/vite/issues/17369)) ([a0336bd](https://github.com/vitejs/vite/commit/a0336bd5197bb4427251be4c975e30fb596c658f))\n* **css:** remove default import in ssr dev ([#17922](https://github.com/vitejs/vite/issues/17922)) ([eccf663](https://github.com/vitejs/vite/commit/eccf663e35a17458425860895bb30b3b0613ea96))\n* use picomatch to align with tinyglobby ([#18503](https://github.com/vitejs/vite/issues/18503)) ([437795d](https://github.com/vitejs/vite/commit/437795db8307ce4491d066bcaaa5bd9432193773))\n* **css:** `cssCodeSplit` in `environments.xxx.build` is invalid ([#18464](https://github.com/vitejs/vite/issues/18464)) ([993e71c](https://github.com/vitejs/vite/commit/993e71c4cb227bd8c347b918f52ccd83f85a645a))\n* **css:** make sass types work with sass-embedded ([#18459](https://github.com/vitejs/vite/issues/18459)) ([89f8303](https://github.com/vitejs/vite/commit/89f8303e727791aa7be6f35833a708b6a50e9120))\n* **deps:** update all non-major dependencies ([#18484](https://github.com/vitejs/vite/issues/18484)) ([2ec12df](https://github.com/vitejs/vite/commit/2ec12df98d07eb4c986737e86a4a9f8066724658))\n* handle warmup glob hang ([#18462](https://github.com/vitejs/vite/issues/18462)) ([409fa5c](https://github.com/vitejs/vite/commit/409fa5c9dee0e394bcdc3b111f5b2e4261131ca0))\n* **manifest:** non entry CSS chunk src was wrong ([#18133](https://github.com/vitejs/vite/issues/18133)) ([c148676](https://github.com/vitejs/vite/commit/c148676c90dc4823bc6bdeb8ba1e36386c5d9654))\n* **module-runner:** delay function eval until module runner instantiation ([#18480](https://github.com/vitejs/vite/issues/18480)) ([472afbd](https://github.com/vitejs/vite/commit/472afbd010db3f1c7a59826c7bf4067191b7f48a))\n* **plugins:** noop if config hook returns same config reference ([#18467](https://github.com/vitejs/vite/issues/18467)) ([bd540d5](https://github.com/vitejs/vite/commit/bd540d52eb609ca12dad8e2f3fe8011821bda878))\n* return the same instance of ModuleNode for the same EnvironmentModuleNode ([#18455](https://github.com/vitejs/vite/issues/18455)) ([5ead461](https://github.com/vitejs/vite/commit/5ead461b374d76ceb134063477eaf3f97fe3da97))\n* set scripts imported by HTML moduleSideEffects=true ([#18411](https://github.com/vitejs/vite/issues/18411)) ([2ebe4b4](https://github.com/vitejs/vite/commit/2ebe4b44430dd311028f72520ac977bb202ce50b))\n* use websocket to test server liveness before client reload ([#17891](https://github.com/vitejs/vite/issues/17891)) ([7f9f8c6](https://github.com/vitejs/vite/commit/7f9f8c6851d1eb49a72dcb6c134873148a2e81eb))\n* add typing to `CSSOptions.preprocessorOptions` ([#18001](https://github.com/vitejs/vite/issues/18001)) ([7eeb6f2](https://github.com/vitejs/vite/commit/7eeb6f2f97abf5dfc71c225b9cff9779baf2ed2f))\n* default `build.cssMinify` to `'esbuild'` for SSR ([#15637](https://github.com/vitejs/vite/issues/15637)) ([f1d3bf7](https://github.com/vitejs/vite/commit/f1d3bf74cc7f12e759442fd7111d07e2c0262a67))\n* **dev:** prevent double URL encoding in server.open on macOS ([#18443](https://github.com/vitejs/vite/issues/18443)) ([56b7176](https://github.com/vitejs/vite/commit/56b71768f3ee498962fba898804086299382bb59))\n* **preview:** set resolvedUrls null after close ([#18445](https://github.com/vitejs/vite/issues/18445)) ([65014a3](https://github.com/vitejs/vite/commit/65014a32ef618619c5a34b729d67340d9253bdd5))\n* **ssr:** inject identity function at the top ([#18449](https://github.com/vitejs/vite/issues/18449)) ([0ab20a3](https://github.com/vitejs/vite/commit/0ab20a3ee26eacf302415b3087732497d0a2f358))\n* **ssr:** preserve source maps for hoisted imports (fix [#16355](https://github.com/vitejs/vite/issues/16355)) ([#16356](https://github.com/vitejs/vite/issues/16356)) ([8e382a6](https://github.com/vitejs/vite/commit/8e382a6a1fed2cd41051b81f9cd9c94b484352a5))\n* augment hash for CSS files to prevent chromium erroring by loading previous files ([#18367](https://github.com/vitejs/vite/issues/18367)) ([a569f42](https://github.com/vitejs/vite/commit/a569f42ee93229308be7a327b7a71e79f3d58b01))\n* **cli:** `--watch` should not override `build.watch` options ([#18390](https://github.com/vitejs/vite/issues/18390)) ([b2965c8](https://github.com/vitejs/vite/commit/b2965c8e9f74410bc8047a05528c74b68a3856d7))\n* **css:** don't transform sass function calls with namespace ([#18414](https://github.com/vitejs/vite/issues/18414)) ([dbb2604](https://github.com/vitejs/vite/commit/dbb260499f894d495bcff3dcdf5635d015a2f563))\n* **deps:** update `open` dependency to 10.1.0 ([#18349](https://github.com/vitejs/vite/issues/18349)) ([5cca4bf](https://github.com/vitejs/vite/commit/5cca4bfd3202c7aea690acf63f60bfe57fa165de))\n* **deps:** update all non-major dependencies ([#18345](https://github.com/vitejs/vite/issues/18345)) ([5552583](https://github.com/vitejs/vite/commit/5552583a2272cd4208b30ad60e99d984e34645f0))\n* more robust plugin.sharedDuringBuild ([#18351](https://github.com/vitejs/vite/issues/18351)) ([47b1270](https://github.com/vitejs/vite/commit/47b12706ce2d0c009d6078a61e16e81a04c9f49c))\n* **ssr:** `this` in exported function should be `undefined` ([#18329](https://github.com/vitejs/vite/issues/18329)) ([bae6a37](https://github.com/vitejs/vite/commit/bae6a37628c4870f3db92351e8af2a7b4a07e248))\n* **worker:** rewrite rollup `output.format` with `worker.format` on worker build error ([#18165](https://github.com/vitejs/vite/issues/18165)) ([dc82334](https://github.com/vitejs/vite/commit/dc823347bb857a9f63eee7e027a52236d7e331e0))\n* `injectQuery` double encoding ([#18246](https://github.com/vitejs/vite/issues/18246)) ([2c5f948](https://github.com/vitejs/vite/commit/2c5f948d0646f6a0237570ab5d36b06d31cb94c9))\n* add position to import analysis resolve exception ([#18344](https://github.com/vitejs/vite/issues/18344)) ([0fe95d4](https://github.com/vitejs/vite/commit/0fe95d4a71930cf55acd628efef59e6eae0f77f7))\n* **assets:** make srcset parsing HTML spec compliant ([#16323](https://github.com/vitejs/vite/issues/16323)) ([#18242](https://github.com/vitejs/vite/issues/18242)) ([0e6d4a5](https://github.com/vitejs/vite/commit/0e6d4a5e23cdfb2ec433f687e455b9827269527c))\n* **css:** dont remove JS chunk for pure CSS chunk when the export is used ([#18307](https://github.com/vitejs/vite/issues/18307)) ([889bfc0](https://github.com/vitejs/vite/commit/889bfc0ada6d6cd356bb7a92efdce96298f82fef))\n* **deps:** bump tsconfck ([#18322](https://github.com/vitejs/vite/issues/18322)) ([67783b2](https://github.com/vitejs/vite/commit/67783b2d5513e013bf74844186eb9b2b70d17d5c))\n* **deps:** update all non-major dependencies ([#18292](https://github.com/vitejs/vite/issues/18292)) ([5cac054](https://github.com/vitejs/vite/commit/5cac0544dca2764f0114aac38e9922a0c13d7ef4))\n* destroy the runner when runnable environment is closed ([#18282](https://github.com/vitejs/vite/issues/18282)) ([5212d09](https://github.com/vitejs/vite/commit/5212d09579a82bc09b149c77e996d0e5c3972455))\n* handle yarn command fail when root does not exist ([#18141](https://github.com/vitejs/vite/issues/18141)) ([460aaff](https://github.com/vitejs/vite/commit/460aaffbf134a9eda6e092a564afc2eeebf8f935))\n* **hmr:** don't try to rewrite imports for direct CSS soft invalidation ([#18252](https://github.com/vitejs/vite/issues/18252)) ([a03bb0e](https://github.com/vitejs/vite/commit/a03bb0e2ba35af314c57fc98600bb76566592239))\n* make it easier to configure environment runner ([#18273](https://github.com/vitejs/vite/issues/18273)) ([fb35a78](https://github.com/vitejs/vite/commit/fb35a7800e21ed2c6f9d0f843898afa1fcc87795))\n* **middleware-mode:** call all hot.listen when server restart ([#18261](https://github.com/vitejs/vite/issues/18261)) ([007773b](https://github.com/vitejs/vite/commit/007773b550e7c6bcaeb8d88970fd6dfe999d5a4a))\n* **optimizer:** don't externalize transitive dep package name with asset extension ([#18152](https://github.com/vitejs/vite/issues/18152)) ([fafc7e2](https://github.com/vitejs/vite/commit/fafc7e28d3395292fbc2f2355417dcc15871ab1e))\n* **resolve:** fix resolve cache key for external conditions ([#18332](https://github.com/vitejs/vite/issues/18332)) ([93d286c](https://github.com/vitejs/vite/commit/93d286c4c1af0b379002a6ff495e82bb87acd65c))\n* **resolve:** fix resolve cache to consider `conditions` and more ([#18302](https://github.com/vitejs/vite/issues/18302)) ([2017a33](https://github.com/vitejs/vite/commit/2017a330f5576dfc9db1538e0b899a1776cd100a))\n* **types:** add more overload to `defineConfig` ([#18299](https://github.com/vitejs/vite/issues/18299)) ([94e34cf](https://github.com/vitejs/vite/commit/94e34cf1dfe6fdb331b6508e830b2cc446000aac))\n* asset import should skip handling data URIs ([#18163](https://github.com/vitejs/vite/issues/18163)) ([70813c7](https://github.com/vitejs/vite/commit/70813c7f05fc9a45d102a53514ecac23831e6d6b))\n* cache the runnable environment module runner ([#18215](https://github.com/vitejs/vite/issues/18215)) ([95020ab](https://github.com/vitejs/vite/commit/95020ab49e12d143262859e095025cf02423c1d9))\n* call `this.hot.close` for non-ws HotChannel ([#18212](https://github.com/vitejs/vite/issues/18212)) ([bad0ccc](https://github.com/vitejs/vite/commit/bad0cccee80c02fa309f274220f6d324d03c3b19))\n* close HotChannel on environment close ([#18206](https://github.com/vitejs/vite/issues/18206)) ([2d148e3](https://github.com/vitejs/vite/commit/2d148e347e8fbcc6f0e4e627a20acc81d9ced3e0))\n* **config:** treat all files as ESM on deno ([#18081](https://github.com/vitejs/vite/issues/18081)) ([c1ed8a5](https://github.com/vitejs/vite/commit/c1ed8a595a02ec7f8f5a8d23f97b2f21d3834ab1))\n* **css:** ensure sass compiler initialized only once ([#18128](https://github.com/vitejs/vite/issues/18128)) ([4cc5322](https://github.com/vitejs/vite/commit/4cc53224e9b207aa6a5a111e40ed0a0464cf37f4))\n* **css:** fix lightningcss dep url resolution with custom root ([#18125](https://github.com/vitejs/vite/issues/18125)) ([eb08f60](https://github.com/vitejs/vite/commit/eb08f605ddadef99a5d68f55de143e3e47c91618))\n* **css:** fix missing source file warning with sass modern api custom importer ([#18113](https://github.com/vitejs/vite/issues/18113)) ([d7763a5](https://github.com/vitejs/vite/commit/d7763a5615a238cb1b5dceb7bdfc4aac7678fb0a))\n* **data-uri:** only match ids starting with `data:` ([#18241](https://github.com/vitejs/vite/issues/18241)) ([ec0efe8](https://github.com/vitejs/vite/commit/ec0efe8a06d0271ef0154f38fb9beabcd4b1bd89))\n* **deps:** update all non-major dependencies ([#18170](https://github.com/vitejs/vite/issues/18170)) ([c8aea5a](https://github.com/vitejs/vite/commit/c8aea5ae0af90dc6796ef3bdd612d1eb819f157b))\n* **deps:** upgrade rollup 4.22.4+ to ensure avoiding XSS ([#18180](https://github.com/vitejs/vite/issues/18180)) ([ea1d0b9](https://github.com/vitejs/vite/commit/ea1d0b9af9b28b57166d4ca67bece21650221a04))\n* **html:** make build-html plugin work with `sharedPlugins` ([#18214](https://github.com/vitejs/vite/issues/18214)) ([34041b9](https://github.com/vitejs/vite/commit/34041b9d8ea39aa9138d0c2417bfbe39cc9aabdc))\n* **mixedModuleGraph:** handle undefined id in getModulesByFile ([#18201](https://github.com/vitejs/vite/issues/18201)) ([768a50f](https://github.com/vitejs/vite/commit/768a50f7ac668dbf876feef557d8c0f8ff32b8ff))\n* **optimizer:** re-optimize when changing config `webCompatible` ([#18221](https://github.com/vitejs/vite/issues/18221)) ([a44b0a2](https://github.com/vitejs/vite/commit/a44b0a2690812788aaaba00fd3acd2c6fa36669b))\n* require serialization for `HMRConnection.send` on implementation side ([#18186](https://github.com/vitejs/vite/issues/18186)) ([9470011](https://github.com/vitejs/vite/commit/9470011570503a917021915c47e6a2f36aae16b5))\n* **ssr:** fix source map remapping with multiple sources ([#18150](https://github.com/vitejs/vite/issues/18150)) ([e003a2c](https://github.com/vitejs/vite/commit/e003a2ca73b04648e14ebf40f3616838e2da3d6d))\n* use `config.consumer` instead of `options?.ssr` / `config.build.ssr` ([#18140](https://github.com/vitejs/vite/issues/18140)) ([21ec1ce](https://github.com/vitejs/vite/commit/21ec1ce7f041efa5cd781924f7bc536ab406a197))\n* **vite:** refactor \"module cache\" to \"evaluated modules\", pass down module to \"runInlinedModule\" ([#18092](https://github.com/vitejs/vite/issues/18092)) ([e83beff](https://github.com/vitejs/vite/commit/e83beff596072f9c7a42f6e2410f154668981d71))\n* avoid DOM Clobbering gadget in `getRelativeUrlFromDocument` ([#18115](https://github.com/vitejs/vite/issues/18115)) ([ade1d89](https://github.com/vitejs/vite/commit/ade1d89660e17eedfd35652165b0c26905259fad))\n* fs raw query ([#18112](https://github.com/vitejs/vite/issues/18112)) ([9d2413c](https://github.com/vitejs/vite/commit/9d2413c8b64bfb1dfd953340b4e1b5972d5440aa))\n* **preload:** throw error preloading module as well ([#18098](https://github.com/vitejs/vite/issues/18098)) ([ba56cf4](https://github.com/vitejs/vite/commit/ba56cf43b5480f8519349f7d7fe60718e9af5f1a))\n* allow scanning exports from `script module` in svelte ([#18063](https://github.com/vitejs/vite/issues/18063)) ([7d699aa](https://github.com/vitejs/vite/commit/7d699aa98155cbf281e3f7f6a8796dcb3b4b0fd6))\n* **build:** declare `preload-helper` has no side effects ([#18057](https://github.com/vitejs/vite/issues/18057)) ([587ad7b](https://github.com/vitejs/vite/commit/587ad7b17beba50279eaf46b06c5bf5559c4f36e))\n* **css:** fallback to mainthread if logger or pkgImporter option is set for sass ([#18071](https://github.com/vitejs/vite/issues/18071)) ([d81dc59](https://github.com/vitejs/vite/commit/d81dc59473b1053bf48c45a9d45f87ee6ecf2c02))\n* **dynamicImportVars:** correct glob pattern for paths with parentheses ([#17940](https://github.com/vitejs/vite/issues/17940)) ([2a391a7](https://github.com/vitejs/vite/commit/2a391a7df6e5b4a8d9e8313fba7ddf003df41e12))\n* ensure req.url matches moduleByEtag URL to avoid incorrect 304 ([#17997](https://github.com/vitejs/vite/issues/17997)) ([abf04c3](https://github.com/vitejs/vite/commit/abf04c3a84f4d9962a6f9697ca26cd639fa76e87))\n* **html:** escape html attribute ([#18067](https://github.com/vitejs/vite/issues/18067)) ([5983f36](https://github.com/vitejs/vite/commit/5983f366d499f74d473097154bbbcc8e51476dc4))\n* incorrect environment consumer option resolution ([#18079](https://github.com/vitejs/vite/issues/18079)) ([0e3467e](https://github.com/vitejs/vite/commit/0e3467e503aef45119260fe75b399b26f7a80b66))\n* **preload:** allow ignoring dep errors ([#18046](https://github.com/vitejs/vite/issues/18046)) ([3fb2889](https://github.com/vitejs/vite/commit/3fb28896d916e03cef1b5bd6877ac184c7ec8003))\n* store backwards compatible `ssrModule` and `ssrError` ([#18031](https://github.com/vitejs/vite/issues/18031)) ([cf8ced5](https://github.com/vitejs/vite/commit/cf8ced56ea4932e917e2c4ef3d04a87f0ab4f20b))\n\n### Performance Improvements\n\n* reduce bundle size for `Object.keys(import.meta.glob(...))` / `Object.values(import.meta.glob(...))` ([#18666](https://github.com/vitejs/vite/issues/18666)) ([ed99a2c](https://github.com/vitejs/vite/commit/ed99a2cd31e8d3c2b791885bcc4b188570539e45))\n* **worker:** inline worker without base64 ([#18752](https://github.com/vitejs/vite/issues/18752)) ([90c66c9](https://github.com/vitejs/vite/commit/90c66c95aba3d2edd86637a77adc699f3fd6c1ff))\n* remove strip-ansi for a node built-in ([#18630](https://github.com/vitejs/vite/issues/18630)) ([5182272](https://github.com/vitejs/vite/commit/5182272d52fc092a6219c8efe73ecb3f8e65a0b5))\n* **css:** skip style.css extraction if code-split css ([#18470](https://github.com/vitejs/vite/issues/18470)) ([34fdb6b](https://github.com/vitejs/vite/commit/34fdb6bef558724330d2411b9666facef669b3a0))\n* call `module.enableCompileCache()` ([#18323](https://github.com/vitejs/vite/issues/18323)) ([18f1dad](https://github.com/vitejs/vite/commit/18f1daddd125b07dcb8c32056ee0cec61bd65971))\n* use `crypto.hash` when available ([#18317](https://github.com/vitejs/vite/issues/18317)) ([2a14884](https://github.com/vitejs/vite/commit/2a148844cf2382a5377b75066351f00207843352))\n\n### Documentation\n\n* rename `HotUpdateContext` to `HotUpdateOptions` ([#18718](https://github.com/vitejs/vite/issues/18718)) ([824c347](https://github.com/vitejs/vite/commit/824c347fa21aaf5bbf811994385b790db4287ab0))\n* add jsdocs to flags in BuilderOptions ([#18516](https://github.com/vitejs/vite/issues/18516)) ([1507068](https://github.com/vitejs/vite/commit/1507068b6d460cf54336fe7e8d3539fdb4564bfb))\n* missing changes guides ([#18491](https://github.com/vitejs/vite/issues/18491)) ([5da78a6](https://github.com/vitejs/vite/commit/5da78a6859f3b5c677d896144b915381e4497432))\n* update fs.deny default in JSDoc ([#18514](https://github.com/vitejs/vite/issues/18514)) ([1fcc83d](https://github.com/vitejs/vite/commit/1fcc83dd7ade429f889e4ce19d5c67b3e5b46419))\n* update homepage ([#18274](https://github.com/vitejs/vite/issues/18274)) ([a99a0aa](https://github.com/vitejs/vite/commit/a99a0aab7c600301a5c314b6071afa46915ce248))\n* fix typo in proxy.ts ([#18162](https://github.com/vitejs/vite/issues/18162)) ([49087bd](https://github.com/vitejs/vite/commit/49087bd5738a2cf69ee46b10a74cfd61c18e9959))\n\n### Reverts\n\n* use chokidar v3 ([#18659](https://github.com/vitejs/vite/issues/18659)) ([49783da](https://github.com/vitejs/vite/commit/49783da298bc45f3f3c5ad4ce2fb1260ee8856bb))\n\n### Miscellaneous Chores\n\n* add 5.4.x changelogs ([#18768](https://github.com/vitejs/vite/issues/18768)) ([26b58c8](https://github.com/vitejs/vite/commit/26b58c8130f232dcd4e839a337bbe478352f23ab))\n* add some comments about mimes ([#18705](https://github.com/vitejs/vite/issues/18705)) ([f07e9b9](https://github.com/vitejs/vite/commit/f07e9b9d01d790c727edc2497304f07b1ef5d28f))\n* **deps:** update all non-major dependencies ([#18746](https://github.com/vitejs/vite/issues/18746)) ([0ad16e9](https://github.com/vitejs/vite/commit/0ad16e92d57453d9e5392c90fd06bda947be9de6))\n* **deps:** update all non-major dependencies ([#18634](https://github.com/vitejs/vite/issues/18634)) ([e2231a9](https://github.com/vitejs/vite/commit/e2231a92af46db144b9c94fb57918ac683dc93cb))\n* **deps:** update transitive deps ([#18602](https://github.com/vitejs/vite/issues/18602)) ([0c8b152](https://github.com/vitejs/vite/commit/0c8b15238b669b8ab0a3f90bcf2f690d4450e18f))\n* tweak build config ([#18622](https://github.com/vitejs/vite/issues/18622)) ([2a88f71](https://github.com/vitejs/vite/commit/2a88f71aef87ed23b155af26f8aca6bb7f65e899))\n* add warning for `/` mapping in `resolve.alias` ([#18588](https://github.com/vitejs/vite/issues/18588)) ([a51c254](https://github.com/vitejs/vite/commit/a51c254265bbfe3d77f834fe81a503ce27c05b32))\n* **deps:** update all non-major dependencies ([#18562](https://github.com/vitejs/vite/issues/18562)) ([fb227ec](https://github.com/vitejs/vite/commit/fb227ec4402246b5a13e274c881d9de6dd8082dd))\n* remove unused `ssr` variable ([#18594](https://github.com/vitejs/vite/issues/18594)) ([23c39fc](https://github.com/vitejs/vite/commit/23c39fc994a6164bc68d69e56f39735a6bb7a71d))\n* fix moduleSideEffects in build script on Windows ([#18518](https://github.com/vitejs/vite/issues/18518)) ([25fe9e3](https://github.com/vitejs/vite/commit/25fe9e3b48e29d49e90d6aed5ec3825dceafec18))\n* use premove instead of rimraf ([#18499](https://github.com/vitejs/vite/issues/18499)) ([f97a578](https://github.com/vitejs/vite/commit/f97a57893b3a7ddf11ca4c126b6be33cd2d9283b))\n* **deps:** update postcss-load-config to v6 ([#15235](https://github.com/vitejs/vite/issues/15235)) ([3a27f62](https://github.com/vitejs/vite/commit/3a27f627df278f6c9778a55f44cb347665b65204))\n* **deps:** update dependency picomatch to v4 ([#15876](https://github.com/vitejs/vite/issues/15876)) ([3774881](https://github.com/vitejs/vite/commit/377488178a7ef372d9b76526bb01fd60b97f51df))\n* combine deps license with same text ([#18356](https://github.com/vitejs/vite/issues/18356)) ([b5d1a05](https://github.com/vitejs/vite/commit/b5d1a058f9dab6a6b1243c2a0b11d2c421dd3291))\n* **create-vite:** mark template files as CC0 ([#18366](https://github.com/vitejs/vite/issues/18366)) ([f6b9074](https://github.com/vitejs/vite/commit/f6b90747eb2b1ad863e5f147a80c75b15e38a51b))\n* **deps:** bump TypeScript to 5.6 ([#18254](https://github.com/vitejs/vite/issues/18254)) ([57a0e85](https://github.com/vitejs/vite/commit/57a0e85186b88118bf5f79dd53391676fb91afec))\n* **deps:** migrate `fast-glob` to `tinyglobby` ([#18243](https://github.com/vitejs/vite/issues/18243)) ([6f74a3a](https://github.com/vitejs/vite/commit/6f74a3a1b2469a24a86743d16267b0cc3653bc4a))\n* **deps:** update all non-major dependencies ([#18404](https://github.com/vitejs/vite/issues/18404)) ([802839d](https://github.com/vitejs/vite/commit/802839d48335a69eb15f71f2cd816d0b6e4d3556))\n* **deps:** update dependency sirv to v3 ([#18346](https://github.com/vitejs/vite/issues/18346)) ([5ea4b00](https://github.com/vitejs/vite/commit/5ea4b00a984bc76d0d000f621ab72763a4c9a48b))\n* fix grammar ([#18385](https://github.com/vitejs/vite/issues/18385)) ([8030231](https://github.com/vitejs/vite/commit/8030231596edcd688e324ea507dc1ba80564f75c))\n* mark builder api experimental ([#18436](https://github.com/vitejs/vite/issues/18436)) ([b57321c](https://github.com/vitejs/vite/commit/b57321cc198ee7b9012f1be632cfd4bea006cd89))\n* tiny typo ([#18374](https://github.com/vitejs/vite/issues/18374)) ([7d97a9b](https://github.com/vitejs/vite/commit/7d97a9b2ba11ab566865dcf9ee0350a9e479dfca))\n* update moduleResolution value casing ([#18409](https://github.com/vitejs/vite/issues/18409)) ([ff018dc](https://github.com/vitejs/vite/commit/ff018dca959c73481ae5f8328cd77d3b02f02134))\n* **deps:** update dependency @rollup/plugin-commonjs to v28 ([#18231](https://github.com/vitejs/vite/issues/18231)) ([78e749e](https://github.com/vitejs/vite/commit/78e749ea9a42e7f82dbca37c26e8ab2a5e6e0c16))\n* point deprecation error URLs to main branch docs ([#18321](https://github.com/vitejs/vite/issues/18321)) ([11c0fb1](https://github.com/vitejs/vite/commit/11c0fb1388744624dac40cc267ad21dc7f85cb4e))\n* update all url references of vitejs.dev to vite.dev ([#18276](https://github.com/vitejs/vite/issues/18276)) ([7052c8f](https://github.com/vitejs/vite/commit/7052c8f6fc253f0a88ff04a4c18c108f3bfdaa78))\n* update built LICENSE ([69b6764](https://github.com/vitejs/vite/commit/69b6764d49dd0d04819a8aa9b4061974e0e00f62))\n* update license copyright ([#18278](https://github.com/vitejs/vite/issues/18278)) ([56eb869](https://github.com/vitejs/vite/commit/56eb869a67551a257d20cba00016ea59b1e1a2c4))\n* **deps:** update all non-major dependencies ([#18108](https://github.com/vitejs/vite/issues/18108)) ([a73bbaa](https://github.com/vitejs/vite/commit/a73bbaadb512a884924cc884060e50ea6d809d74))\n* **deps:** update all non-major dependencies ([#18230](https://github.com/vitejs/vite/issues/18230)) ([c0edd26](https://github.com/vitejs/vite/commit/c0edd26bbfeb9a8d80ebaa420e54fbb7f165bd9b))\n* **deps:** update esbuild ([#18173](https://github.com/vitejs/vite/issues/18173)) ([e59e2ca](https://github.com/vitejs/vite/commit/e59e2cacab476305c3cdfb31732c27b174fb8fe2))\n* escape template tag in CHANGELOG.md ([#18126](https://github.com/vitejs/vite/issues/18126)) ([caaa683](https://github.com/vitejs/vite/commit/caaa6836e9a104cc9d63b68ad850149687ad104c))\n* **optimizer:** fix typo in comment ([#18239](https://github.com/vitejs/vite/issues/18239)) ([b916ab6](https://github.com/vitejs/vite/commit/b916ab601d2ec1c842ea0c6139bf216166010e56))\n* **deps:** update all non-major dependencies ([#18050](https://github.com/vitejs/vite/issues/18050)) ([7cac03f](https://github.com/vitejs/vite/commit/7cac03fa5197a72d2e2422bd0243a85a9a18abfc))\n* enable some eslint rules ([#18084](https://github.com/vitejs/vite/issues/18084)) ([e9a2746](https://github.com/vitejs/vite/commit/e9a2746ca77473b1814fd05db3d299c074135fe5))\n* remove npm-run-all2 ([#18083](https://github.com/vitejs/vite/issues/18083)) ([41180d0](https://github.com/vitejs/vite/commit/41180d02730a7ce7c9b6ec7ac71fc6e750dd22c6))\n* silence unnecessary logs during test ([#18052](https://github.com/vitejs/vite/issues/18052)) ([a3ef052](https://github.com/vitejs/vite/commit/a3ef052d408edbec71081fd2f7b3e4b1d4ea0174))\n\n### Code Refactoring\n\n* first character judgment replacement regexp ([#18658](https://github.com/vitejs/vite/issues/18658)) ([58f1df3](https://github.com/vitejs/vite/commit/58f1df3288b0f9584bb413dd34b8d65671258f6f))\n* introduce `mergeWithDefaults` and organize how default values for config options are set ([#18550](https://github.com/vitejs/vite/issues/18550)) ([0e1f437](https://github.com/vitejs/vite/commit/0e1f437d53683b57f0157ce3ff0b0f02acabb408))\n* **resolve:** remove `allowLinkedExternal` parameter from `tryNodeResolve` ([#18670](https://github.com/vitejs/vite/issues/18670)) ([b74d363](https://github.com/vitejs/vite/commit/b74d3632693b6a829b4d1cdc2a9d4ba8234c093b))\n* **resolve:** remove `environmentsOptions` parameter ([#18590](https://github.com/vitejs/vite/issues/18590)) ([3ef0bf1](https://github.com/vitejs/vite/commit/3ef0bf19a3457c46395bdcb2201bbf32807d7231))\n* client-only top-level warmup ([#18524](https://github.com/vitejs/vite/issues/18524)) ([a50ff60](https://github.com/vitejs/vite/commit/a50ff6000bca46a6fe429f2c3a98c486ea5ebc8e))\n* remove fs.cachedChecks option ([#18493](https://github.com/vitejs/vite/issues/18493)) ([94b0857](https://github.com/vitejs/vite/commit/94b085735372588d5f92c7f4a8cf68e8291f2db0))\n* separate tsconfck caches per config in a weakmap ([#17317](https://github.com/vitejs/vite/issues/17317)) ([b9b01d5](https://github.com/vitejs/vite/commit/b9b01d57fdaf5d291c78a8156e17b534c8c51eb4))\n* **css:** hide internal preprocessor types and expose types used for options ([#18458](https://github.com/vitejs/vite/issues/18458)) ([c32837c](https://github.com/vitejs/vite/commit/c32837cf868f0fdb97a22a0be8c95c433f4069c8))\n* optimizeDeps back to top level ([#18465](https://github.com/vitejs/vite/issues/18465)) ([1ac22de](https://github.com/vitejs/vite/commit/1ac22de41cf5a8647847070eadeac3231c94c3ed))\n* top-level createEnvironment is client-only ([#18475](https://github.com/vitejs/vite/issues/18475)) ([6022fc2](https://github.com/vitejs/vite/commit/6022fc2c87e0f59c3e6ccfa307a352a378d8273a))\n* use `originalFileNames`/`names` ([#18240](https://github.com/vitejs/vite/issues/18240)) ([f2957c8](https://github.com/vitejs/vite/commit/f2957c84f69c14c882809889fbd0fc66b97ca3e9))\n* bump minimal terser version to 5.16.0 ([#18209](https://github.com/vitejs/vite/issues/18209)) ([19ce525](https://github.com/vitejs/vite/commit/19ce525b974328e4668ad8c6540c2a5ea652795b))\n* **resolve:** remove `tryEsmOnly` flag ([#18394](https://github.com/vitejs/vite/issues/18394)) ([7cebe38](https://github.com/vitejs/vite/commit/7cebe3847f934ff4875ff3ecc6a96a82bac5f8f4))\n* use builder in `build` ([#18432](https://github.com/vitejs/vite/issues/18432)) ([cc61d16](https://github.com/vitejs/vite/commit/cc61d169a4826996f7b2289618c383f8c5c6d470))\n* rename runner.destroy() to runner.close() ([#18304](https://github.com/vitejs/vite/issues/18304)) ([cd368f9](https://github.com/vitejs/vite/commit/cd368f9fed393a8649597f0e5d873504a9ac62e2))\n* break circular dependencies to fix test-unit ([#18237](https://github.com/vitejs/vite/issues/18237)) ([a577828](https://github.com/vitejs/vite/commit/a577828d826805c5693d773eea4c4179e21f1a16))\n* remove `_onCrawlEnd` ([#18207](https://github.com/vitejs/vite/issues/18207)) ([bea0272](https://github.com/vitejs/vite/commit/bea0272decd908cd04ac0a2c87dd0a676f218a1a))\n* remove the need for \"processSourceMap\" ([#18187](https://github.com/vitejs/vite/issues/18187)) ([08ff233](https://github.com/vitejs/vite/commit/08ff23319964903b9f380859c216b10e577ddb6f))\n* replace `parse` with `splitFileAndPostfix` ([#18185](https://github.com/vitejs/vite/issues/18185)) ([6f030ec](https://github.com/vitejs/vite/commit/6f030ec15f25a2a1d7d912f1b84d83ebb28a3515))\n* use `resolvePackageData` to get rollup version ([#18208](https://github.com/vitejs/vite/issues/18208)) ([220d6ec](https://github.com/vitejs/vite/commit/220d6ec2bf3fc7063eac7c625d4ccda9a4204cb7))\n* **create-vite:** use picocolors ([#18085](https://github.com/vitejs/vite/issues/18085)) ([ba37df0](https://github.com/vitejs/vite/commit/ba37df0813ad3864fc4b8c6c0b289a1f2bc00c36))\n* remove custom resolveOptions from pre-alias plugin ([#18041](https://github.com/vitejs/vite/issues/18041)) ([6f60adc](https://github.com/vitejs/vite/commit/6f60adc15283c6b25218d2392738671b6ab4b392))\n* remove unnecessary escape ([#18044](https://github.com/vitejs/vite/issues/18044)) ([8062d36](https://github.com/vitejs/vite/commit/8062d36773cafaec98196965d33d79887e58f437))\n\n### Build System\n\n* ignore cjs warning ([#18660](https://github.com/vitejs/vite/issues/18660)) ([33b0d5a](https://github.com/vitejs/vite/commit/33b0d5a6ca18e9f7c27b0159decd84fee3859e09))\n* reduce package size ([#18517](https://github.com/vitejs/vite/issues/18517)) ([b83f60b](https://github.com/vitejs/vite/commit/b83f60b159f3b6f4a61db180fa03cc5b20bd110f))\n\n### Tests\n\n* simplify `playground/json/__tests__/ssr` ([#18701](https://github.com/vitejs/vite/issues/18701)) ([f731ca2](https://github.com/vitejs/vite/commit/f731ca21ea4cfe38418880f15f6064e156a43a5e))\n* update filename regex ([#18593](https://github.com/vitejs/vite/issues/18593)) ([dd25c1a](https://github.com/vitejs/vite/commit/dd25c1ab5d5510b955fa24830bc223cacc855560))\n* fix test conflict ([#18446](https://github.com/vitejs/vite/issues/18446)) ([94cd1e6](https://github.com/vitejs/vite/commit/94cd1e6f95e2434d2b52b5c16d50fe0472214634))\n* remove unnecessary logs from output ([#18368](https://github.com/vitejs/vite/issues/18368)) ([f50d358](https://github.com/vitejs/vite/commit/f50d3583e2c460bb02c118371a79b5ceac9877f3))\n* replace fs mocking in css module compose test ([#18413](https://github.com/vitejs/vite/issues/18413)) ([ddee0ad](https://github.com/vitejs/vite/commit/ddee0ad38fd53993155fc11174d5ee194d6648d8))\n* ssr external / resolveId test ([#18327](https://github.com/vitejs/vite/issues/18327)) ([4c5cf91](https://github.com/vitejs/vite/commit/4c5cf91d124d423fe028beecda952125698c1d5d))\n* test optimized dep as ssr entry ([#18301](https://github.com/vitejs/vite/issues/18301)) ([466f94a](https://github.com/vitejs/vite/commit/466f94aa6465f0a3b932f55e93660f7cf6cd936e))\n* fix server-worker-runner flaky test ([#18247](https://github.com/vitejs/vite/issues/18247)) ([8f82730](https://github.com/vitejs/vite/commit/8f82730b86abed953800ade6e726f70ee55ab7fe))\n* move glob test root to reduce snapshot change ([#18053](https://github.com/vitejs/vite/issues/18053)) ([04d7e77](https://github.com/vitejs/vite/commit/04d7e7749496f5d1972338c7de1502c7f6f65cb6))\n\n### Beta Changelogs\n\n\n#### [6.0.0-beta.10](https://github.com/vitejs/vite/compare/v6.0.0-beta.9...v6.0.0-beta.10) (2024-11-14)\n\nSee [6.0.0-beta.10 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.10/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.9](https://github.com/vitejs/vite/compare/v6.0.0-beta.8...v6.0.0-beta.9) (2024-11-07)\n\nSee [6.0.0-beta.9 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.9/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.8](https://github.com/vitejs/vite/compare/v6.0.0-beta.7...v6.0.0-beta.8) (2024-11-01)\n\nSee [6.0.0-beta.8 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.8/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.7](https://github.com/vitejs/vite/compare/v6.0.0-beta.6...v6.0.0-beta.7) (2024-10-30)\n\nSee [6.0.0-beta.7 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.7/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.6](https://github.com/vitejs/vite/compare/v6.0.0-beta.5...v6.0.0-beta.6) (2024-10-28)\n\nSee [6.0.0-beta.6 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.6/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.5](https://github.com/vitejs/vite/compare/v6.0.0-beta.4...v6.0.0-beta.5) (2024-10-24)\n\nSee [6.0.0-beta.5 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.5/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.4](https://github.com/vitejs/vite/compare/v6.0.0-beta.3...v6.0.0-beta.4) (2024-10-23)\n\nSee [6.0.0-beta.4 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.4/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.3](https://github.com/vitejs/vite/compare/v6.0.0-beta.2...v6.0.0-beta.3) (2024-10-15)\n\nSee [6.0.0-beta.3 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.3/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.2](https://github.com/vitejs/vite/compare/v6.0.0-beta.1...v6.0.0-beta.2) (2024-10-01)\n\nSee [6.0.0-beta.2 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.2/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.1](https://github.com/vitejs/vite/compare/v6.0.0-beta.0...v6.0.0-beta.1) (2024-09-16)\n\nSee [6.0.0-beta.1 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.1/packages/vite/CHANGELOG.md)\n\n\n#### [6.0.0-beta.0](https://github.com/vitejs/vite/compare/v5.4.11...v6.0.0-beta.0) (2024-09-12)\n\nSee [6.0.0-beta.0 changelog](https://github.com/vitejs/vite/blob/v6.0.0-beta.0/packages/vite/CHANGELOG.md)\n\n\n\n## Previous Changelogs\n\n### 5.4.x (2024-08-07 - 2024-11-11)\nSee [5.4.11 changelog](https://github.com/vitejs/vite/blob/v5.4.11/packages/vite/CHANGELOG.md)\n\n### 5.3.x (2024-06-13 - 2024-07-25)\nSee [5.3.5 changelog](https://github.com/vitejs/vite/blob/v5.3.5/packages/vite/CHANGELOG.md)\n\n### 5.2.x (2024-03-20 - 2024-05-28)\nSee [5.2.12 changelog](https://github.com/vitejs/vite/blob/v5.2.12/packages/vite/CHANGELOG.md)\n\n### 5.1.x (2024-02-08 - 2024-03-11)\nSee [5.1.6 changelog](https://github.com/vitejs/vite/blob/v5.1.6/packages/vite/CHANGELOG.md)\n\n### 5.0.x (2023-11-16 - 2024-01-05)\nSee [5.0.11 changelog](https://github.com/vitejs/vite/blob/v5.0.11/packages/vite/CHANGELOG.md)\n\n### 4.5.x (2023-10-18)\nSee [4.5.0 changelog](https://github.com/vitejs/vite/blob/v4.5.0/packages/vite/CHANGELOG.md)\n\n### 4.4.x (2023-07-06 - 2023-10-05)\nSee [4.4.11 changelog](https://github.com/vitejs/vite/blob/v4.4.11/packages/vite/CHANGELOG.md)\n\n### 4.3.x (2023-04-20 - 2023-05-26)\nSee [4.3.0 changelog](https://github.com/vitejs/vite/blob/v4.3.9/packages/vite/CHANGELOG.md)\n\n### 4.2.x (2023-03-16 - 2023-04-18)\nSee [4.2.2 changelog](https://github.com/vitejs/vite/blob/v4.2.2/packages/vite/CHANGELOG.md)\n\n### 4.1.x (2023-02-02 - 2023-02-21)\nSee [4.1.4 changelog](https://github.com/vitejs/vite/blob/v4.1.4/packages/vite/CHANGELOG.md)\n\n### 4.0.x (2022-12-09 - 2023-01-03)\nSee [4.0.4 changelog](https://github.com/vitejs/vite/blob/v4.0.4/packages/vite/CHANGELOG.md)\n\n### 3.2.x (2022-10-26 - 2023-04-18)\nSee [3.2.6 changelog](https://github.com/vitejs/vite/blob/v3.2.6/packages/vite/CHANGELOG.md)\n\n### 3.1.x (2022-09-05 - 2022-09-19)\nSee [3.1.3 changelog](https://github.com/vitejs/vite/blob/v3.1.3/packages/vite/CHANGELOG.md)\n\n### 3.0.x (2022-07-13 - 2022-08-19)\nSee [3.0.9 changelog](https://github.com/vitejs/vite/blob/v3.0.9/packages/vite/CHANGELOG.md)\n\n### 2.9.x (2022-03-30 - 2022-08-12)\nSee [2.9.15 changelog](https://github.com/vitejs/vite/blob/v2.9.15/packages/vite/CHANGELOG.md)\n\n### 2.8.x (2022-02-09 - 2022-03-01)\nSee [2.8.6 changelog](https://github.com/vitejs/vite/blob/v2.8.6/packages/vite/CHANGELOG.md)\n\n### 2.7.x (2021-10-28 - 2021-12-28)\nSee [2.7.13 changelog](https://github.com/vitejs/vite/blob/v2.7.13/packages/vite/CHANGELOG.md)\n\n### 2.6.x (2021-09-20 - 2021-10-27)\nSee [2.6.14 changelog](https://github.com/vitejs/vite/blob/v2.6.14/packages/vite/CHANGELOG.md)\n\n### 2.5.x (2021-08-03 - 2021-09-13)\nSee [2.5.10 changelog](https://github.com/vitejs/vite/blob/v2.5.10/packages/vite/CHANGELOG.md)\n\n### 2.4.x (2021-06-27 - 2021-07-27)\nSee [2.4.4 changelog](https://github.com/vitejs/vite/blob/v2.4.4/packages/vite/CHANGELOG.md)\n\n### 2.3.x (2021-05-11 - 2021-06-19)\nSee [2.3.8 changelog](https://github.com/vitejs/vite/blob/v2.3.8/packages/vite/CHANGELOG.md)\n\n### 2.2.x (2021-04-19 - 2021-05-03)\nSee [2.2.4 changelog](https://github.com/vitejs/vite/blob/v2.2.4/packages/vite/CHANGELOG.md)\n\n### 2.1.x (2021-03-15 - 2021-03-31)\nSee [2.1.5 changelog](https://github.com/vitejs/vite/blob/v2.1.5/packages/vite/CHANGELOG.md)\n\n### 2.0.x (2021-02-16 - 2021-03-02)\nSee [2.0.5 changelog](https://github.com/vitejs/vite/blob/v2.0.5/packages/vite/CHANGELOG.md)\n"
  },
  {
    "path": "packages/vite/LICENSE.md",
    "content": "# Vite core license\nVite is released under the MIT license:\n\nMIT License\n\nCopyright (c) 2019-present, VoidZero Inc. and Vite contributors\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\n# Licenses of bundled dependencies\nThe published Vite artifact additionally contains code with the following licenses:\nApache-2.0, BSD-2-Clause, CC0-1.0, ISC, MIT\n\n# Bundled dependencies:\n## @jridgewell/gen-mapping, @jridgewell/remapping, @jridgewell/sourcemap-codec, @jridgewell/trace-mapping\nLicense: MIT\nBy: Justin Ridgewell\nRepositories: https://github.com/jridgewell/sourcemaps, https://github.com/jridgewell/sourcemaps, https://github.com/jridgewell/sourcemaps, https://github.com/jridgewell/sourcemaps\n\n> Copyright 2024 Justin Ridgewell <justin@ridgewell.name>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## @jridgewell/resolve-uri\nLicense: MIT\nBy: Justin Ridgewell\nRepository: https://github.com/jridgewell/resolve-uri\n\n> Copyright 2019 Justin Ridgewell <jridgewell@google.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## @polka/compression\nLicense: MIT\nRepository: https://github.com/lukeed/polka\n\n---------------------------------------\n\n## @polka/url\nLicense: MIT\nBy: Luke Edwards\nRepository: https://github.com/lukeed/polka\n\n---------------------------------------\n\n## @rollup/plugin-alias, @rollup/plugin-dynamic-import-vars, @rollup/pluginutils\nLicense: MIT\nBy: Johannes Stein\nRepository: https://github.com/rollup/plugins\n\nLicense: MIT\nBy: LarsDenBakker\nRepository: https://github.com/rollup/plugins\n\nLicense: MIT\nBy: Rich Harris\nRepository: https://github.com/rollup/plugins\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## @vercel/detect-agent\nLicense: Apache-2.0\nBy: Vercel\nRepository: https://github.com/vercel/vercel\n\n> Apache License\n>                            Version 2.0, January 2004\n>                         http://www.apache.org/licenses/\n> \n>    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n> \n>    1. Definitions.\n> \n>       \"License\" shall mean the terms and conditions for use, reproduction,\n>       and distribution as defined by Sections 1 through 9 of this document.\n> \n>       \"Licensor\" shall mean the copyright owner or entity authorized by\n>       the copyright owner that is granting the License.\n> \n>       \"Legal Entity\" shall mean the union of the acting entity and all\n>       other entities that control, are controlled by, or are under common\n>       control with that entity. For the purposes of this definition,\n>       \"control\" means (i) the power, direct or indirect, to cause the\n>       direction or management of such entity, whether by contract or\n>       otherwise, or (ii) ownership of fifty percent (50%) or more of the\n>       outstanding shares, or (iii) beneficial ownership of such entity.\n> \n>       \"You\" (or \"Your\") shall mean an individual or Legal Entity\n>       exercising permissions granted by this License.\n> \n>       \"Source\" form shall mean the preferred form for making modifications,\n>       including but not limited to software source code, documentation\n>       source, and configuration files.\n> \n>       \"Object\" form shall mean any form resulting from mechanical\n>       transformation or translation of a Source form, including but\n>       not limited to compiled object code, generated documentation,\n>       and conversions to other media types.\n> \n>       \"Work\" shall mean the work of authorship, whether in Source or\n>       Object form, made available under the License, as indicated by a\n>       copyright notice that is included in or attached to the work\n>       (an example is provided in the Appendix below).\n> \n>       \"Derivative Works\" shall mean any work, whether in Source or Object\n>       form, that is based on (or derived from) the Work and for which the\n>       editorial revisions, annotations, elaborations, or other modifications\n>       represent, as a whole, an original work of authorship. For the purposes\n>       of this License, Derivative Works shall not include works that remain\n>       separable from, or merely link (or bind by name) to the interfaces of,\n>       the Work and Derivative Works thereof.\n> \n>       \"Contribution\" shall mean any work of authorship, including\n>       the original version of the Work and any modifications or additions\n>       to that Work or Derivative Works thereof, that is intentionally\n>       submitted to Licensor for inclusion in the Work by the copyright owner\n>       or by an individual or Legal Entity authorized to submit on behalf of\n>       the copyright owner. For the purposes of this definition, \"submitted\"\n>       means any form of electronic, verbal, or written communication sent\n>       to the Licensor or its representatives, including but not limited to\n>       communication on electronic mailing lists, source code control systems,\n>       and issue tracking systems that are managed by, or on behalf of, the\n>       Licensor for the purpose of discussing and improving the Work, but\n>       excluding communication that is conspicuously marked or otherwise\n>       designated in writing by the copyright owner as \"Not a Contribution.\"\n> \n>       \"Contributor\" shall mean Licensor and any individual or Legal Entity\n>       on behalf of whom a Contribution has been received by Licensor and\n>       subsequently incorporated within the Work.\n> \n>    2. Grant of Copyright License. Subject to the terms and conditions of\n>       this License, each Contributor hereby grants to You a perpetual,\n>       worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n>       copyright license to reproduce, prepare Derivative Works of,\n>       publicly display, publicly perform, sublicense, and distribute the\n>       Work and such Derivative Works in Source or Object form.\n> \n>    3. Grant of Patent License. Subject to the terms and conditions of\n>       this License, each Contributor hereby grants to You a perpetual,\n>       worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n>       (except as stated in this section) patent license to make, have made,\n>       use, offer to sell, sell, import, and otherwise transfer the Work,\n>       where such license applies only to those patent claims licensable\n>       by such Contributor that are necessarily infringed by their\n>       Contribution(s) alone or by combination of their Contribution(s)\n>       with the Work to which such Contribution(s) was submitted. If You\n>       institute patent litigation against any entity (including a\n>       cross-claim or counterclaim in a lawsuit) alleging that the Work\n>       or a Contribution incorporated within the Work constitutes direct\n>       or contributory patent infringement, then any patent licenses\n>       granted to You under this License for that Work shall terminate\n>       as of the date such litigation is filed.\n> \n>    4. Redistribution. You may reproduce and distribute copies of the\n>       Work or Derivative Works thereof in any medium, with or without\n>       modifications, and in Source or Object form, provided that You\n>       meet the following conditions:\n> \n>       (a) You must give any other recipients of the Work or\n>           Derivative Works a copy of this License; and\n> \n>       (b) You must cause any modified files to carry prominent notices\n>           stating that You changed the files; and\n> \n>       (c) You must retain, in the Source form of any Derivative Works\n>           that You distribute, all copyright, patent, trademark, and\n>           attribution notices from the Source form of the Work,\n>           excluding those notices that do not pertain to any part of\n>           the Derivative Works; and\n> \n>       (d) If the Work includes a \"NOTICE\" text file as part of its\n>           distribution, then any Derivative Works that You distribute must\n>           include a readable copy of the attribution notices contained\n>           within such NOTICE file, excluding those notices that do not\n>           pertain to any part of the Derivative Works, in at least one\n>           of the following places: within a NOTICE text file distributed\n>           as part of the Derivative Works; within the Source form or\n>           documentation, if provided along with the Derivative Works; or,\n>           within a display generated by the Derivative Works, if and\n>           wherever such third-party notices normally appear. The contents\n>           of the NOTICE file are for informational purposes only and\n>           do not modify the License. You may add Your own attribution\n>           notices within Derivative Works that You distribute, alongside\n>           or as an addendum to the NOTICE text from the Work, provided\n>           that such additional attribution notices cannot be construed\n>           as modifying the License.\n> \n>       You may add Your own copyright statement to Your modifications and\n>       may provide additional or different license terms and conditions\n>       for use, reproduction, or distribution of Your modifications, or\n>       for any such Derivative Works as a whole, provided Your use,\n>       reproduction, and distribution of the Work otherwise complies with\n>       the conditions stated in this License.\n> \n>    5. Submission of Contributions. Unless You explicitly state otherwise,\n>       any Contribution intentionally submitted for inclusion in the Work\n>       by You to the Licensor shall be under the terms and conditions of\n>       this License, without any additional terms or conditions.\n>       Notwithstanding the above, nothing herein shall supersede or modify\n>       the terms of any separate license agreement you may have executed\n>       with Licensor regarding such Contributions.\n> \n>    6. Trademarks. This License does not grant permission to use the trade\n>       names, trademarks, service marks, or product names of the Licensor,\n>       except as required for reasonable and customary use in describing the\n>       origin of the Work and reproducing the content of the NOTICE file.\n> \n>    7. Disclaimer of Warranty. Unless required by applicable law or\n>       agreed to in writing, Licensor provides the Work (and each\n>       Contributor provides its Contributions) on an \"AS IS\" BASIS,\n>       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n>       implied, including, without limitation, any warranties or conditions\n>       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n>       PARTICULAR PURPOSE. You are solely responsible for determining the\n>       appropriateness of using or redistributing the Work and assume any\n>       risks associated with Your exercise of permissions under this License.\n> \n>    8. Limitation of Liability. In no event and under no legal theory,\n>       whether in tort (including negligence), contract, or otherwise,\n>       unless required by applicable law (such as deliberate and grossly\n>       negligent acts) or agreed to in writing, shall any Contributor be\n>       liable to You for damages, including any direct, indirect, special,\n>       incidental, or consequential damages of any character arising as a\n>       result of this License or out of the use or inability to use the\n>       Work (including but not limited to damages for loss of goodwill,\n>       work stoppage, computer failure or malfunction, or any and all\n>       other commercial damages or losses), even if such Contributor\n>       has been advised of the possibility of such damages.\n> \n>    9. Accepting Warranty or Additional Liability. While redistributing\n>       the Work or Derivative Works thereof, You may choose to offer,\n>       and charge a fee for, acceptance of support, warranty, indemnity,\n>       or other liability obligations and/or rights consistent with this\n>       License. However, in accepting such obligations, You may act only\n>       on Your own behalf and on Your sole responsibility, not on behalf\n>       of any other Contributor, and only if You agree to indemnify,\n>       defend, and hold each Contributor harmless for any liability\n>       incurred by, or claims asserted against, such Contributor by reason\n>       of your accepting any such warranty or additional liability.\n> \n>    END OF TERMS AND CONDITIONS\n> \n>    APPENDIX: How to apply the Apache License to your work.\n> \n>       To apply the Apache License to your work, attach the following\n>       boilerplate notice, with the fields enclosed by brackets \"[]\"\n>       replaced with your own identifying information. (Don't include\n>       the brackets!)  The text should be enclosed in the appropriate\n>       comment syntax for the file format. We also recommend that a\n>       file or class name and description of purpose be included on the\n>       same \"printed page\" as the copyright notice for easier\n>       identification within third-party archives.\n> \n>    Copyright 2017 Vercel, Inc.\n> \n>    Licensed under the Apache License, Version 2.0 (the \"License\");\n>    you may not use this file except in compliance with the License.\n>    You may obtain a copy of the License at\n> \n>        http://www.apache.org/licenses/LICENSE-2.0\n> \n>    Unless required by applicable law or agreed to in writing, software\n>    distributed under the License is distributed on an \"AS IS\" BASIS,\n>    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n>    See the License for the specific language governing permissions and\n>    limitations under the License.\n\n---------------------------------------\n\n## @vitest/utils\nLicense: MIT\nRepository: https://github.com/vitest-dev/vitest\n\n> MIT License\n> \n> Copyright (c) 2021-Present VoidZero Inc. and Vitest contributors\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## anymatch\nLicense: ISC\nBy: Elan Shanker\nRepository: https://github.com/micromatch/anymatch\n\n> The ISC License\n> \n> Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com)\n> \n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\n> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## artichokie\nLicense: MIT\nBy: sapphi-red, Evan You\nRepository: https://github.com/sapphi-red/artichokie\n\n> MIT License\n> \n> Copyright (c) 2020-present, Yuxi (Evan) You\n> Copyright (c) 2023-present, sapphi-red\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## binary-extensions\nLicense: MIT\nBy: Sindre Sorhus\nRepository: https://github.com/sindresorhus/binary-extensions\n\n> MIT License\n> \n> Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n> Copyright (c) Paul Miller (https://paulmillr.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## braces, fill-range, is-number\nLicense: MIT\nBy: Jon Schlinkert, Brian Woodward, Elan Shanker, Eugene Sharygin, hemanth.hm\nRepository: https://github.com/micromatch/braces\n\nLicense: MIT\nBy: Jon Schlinkert, Edo Rivai, Paul Miller, Rouven Weßling\nRepository: https://github.com/jonschlinkert/fill-range\n\nLicense: MIT\nBy: Jon Schlinkert, Olsten Larck, Rouven Weßling\nRepository: https://github.com/jonschlinkert/is-number\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014-present, Jon Schlinkert.\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## bundle-name, default-browser, default-browser-id, define-lazy-prop, is-docker, is-inside-container, is-wsl, open, run-applescript, wsl-utils\nLicense: MIT\nBy: Sindre Sorhus\nRepositories: https://github.com/sindresorhus/bundle-name, https://github.com/sindresorhus/default-browser, https://github.com/sindresorhus/default-browser-id, https://github.com/sindresorhus/define-lazy-prop, https://github.com/sindresorhus/is-docker, https://github.com/sindresorhus/is-inside-container, https://github.com/sindresorhus/is-wsl, https://github.com/sindresorhus/open, https://github.com/sindresorhus/run-applescript, https://github.com/sindresorhus/wsl-utils\n\n> MIT License\n> \n> Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## cac\nLicense: MIT\nBy: egoist\nRepository: https://github.com/cacjs/cac\n\n> The MIT License (MIT)\n> \n> Copyright (c) EGOIST <0x142857@gmail.com> (https://github.com/egoist)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## chokidar\nLicense: MIT\nBy: Paul Miller, Elan Shanker\nRepository: https://github.com/paulmillr/chokidar\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the “Software”), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## connect\nLicense: MIT\nBy: TJ Holowaychuk, Douglas Christopher Wilson, Jonathan Ong, Tim Caswell\nRepository: https://github.com/senchalabs/connect\n\n> (The MIT License)\n> \n> Copyright (c) 2010 Sencha Inc.\n> Copyright (c) 2011 LearnBoost\n> Copyright (c) 2011-2014 TJ Holowaychuk\n> Copyright (c) 2015 Douglas Christopher Wilson\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## convert-source-map\nLicense: MIT\nBy: Thorsten Lorenz\nRepository: https://github.com/thlorenz/convert-source-map\n\n> Copyright 2013 Thorsten Lorenz. \n> All rights reserved.\n> \n> Permission is hereby granted, free of charge, to any person\n> obtaining a copy of this software and associated documentation\n> files (the \"Software\"), to deal in the Software without\n> restriction, including without limitation the rights to use,\n> copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the\n> Software is furnished to do so, subject to the following\n> conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n> HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n> OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## cors\nLicense: MIT\nBy: Troy Goode\nRepository: https://github.com/expressjs/cors\n\n> (The MIT License)\n> \n> Copyright (c) 2013 Troy Goode <troygoode@gmail.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## cross-spawn\nLicense: MIT\nBy: André Cruz\nRepository: https://github.com/moxystudio/node-cross-spawn\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## cssesc\nLicense: MIT\nBy: Mathias Bynens\nRepository: https://github.com/mathiasbynens/cssesc\n\n> Copyright Mathias Bynens <https://mathiasbynens.be/>\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## dotenv-expand\nLicense: BSD-2-Clause\nBy: motdotla\nRepository: https://github.com/motdotla/dotenv-expand\n\n> Copyright (c) 2016, Scott Motte\n> All rights reserved.\n> \n> Redistribution and use in source and binary forms, with or without\n> modification, are permitted provided that the following conditions are met:\n> \n> * Redistributions of source code must retain the above copyright notice, this\n>   list of conditions and the following disclaimer.\n> \n> * Redistributions in binary form must reproduce the above copyright notice,\n>   this list of conditions and the following disclaimer in the documentation\n>   and/or other materials provided with the distribution.\n> \n> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------\n\n## ee-first\nLicense: MIT\nBy: Jonathan Ong, Douglas Christopher Wilson\nRepository: https://github.com/jonathanong/ee-first\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014 Jonathan Ong me@jongleberry.com\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## encodeurl\nLicense: MIT\nBy: Douglas Christopher Wilson\nRepository: https://github.com/pillarjs/encodeurl\n\n> (The MIT License)\n> \n> Copyright (c) 2016 Douglas Christopher Wilson\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## entities\nLicense: BSD-2-Clause\nBy: Felix Boehm\nRepository: https://github.com/fb55/entities\n\n> Copyright (c) Felix Böhm\n> All rights reserved.\n> \n> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n> \n> Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n> \n> Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n> \n> THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,\n> EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n---------------------------------------\n\n## es-module-lexer\nLicense: MIT\nBy: Guy Bedford\nRepository: https://github.com/guybedford/es-module-lexer\n\n> MIT License\n> -----------\n> \n> Copyright (C) 2018-2022 Guy Bedford\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## escape-html\nLicense: MIT\nRepository: https://github.com/component/escape-html\n\n> (The MIT License)\n> \n> Copyright (c) 2012-2013 TJ Holowaychuk\n> Copyright (c) 2015 Andreas Lubbe\n> Copyright (c) 2015 Tiancheng \"Timothy\" Gu\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## estree-walker\nLicense: MIT\nBy: Rich Harris\nRepository: https://github.com/Rich-Harris/estree-walker\n\n> Copyright (c) 2015-20 [these people](https://github.com/Rich-Harris/estree-walker/graphs/contributors)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## etag\nLicense: MIT\nBy: Douglas Christopher Wilson, David Björklund\nRepository: https://github.com/jshttp/etag\n\n> (The MIT License)\n> \n> Copyright (c) 2014-2016 Douglas Christopher Wilson\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## finalhandler\nLicense: MIT\nBy: Douglas Christopher Wilson\nRepository: https://github.com/pillarjs/finalhandler\n\n> (The MIT License)\n> \n> Copyright (c) 2014-2017 Douglas Christopher Wilson <doug@somethingdoug.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## follow-redirects\nLicense: MIT\nBy: Ruben Verborgh, Olivier Lalonde, James Talmage\nRepository: https://github.com/follow-redirects/follow-redirects\n\n> Copyright 2014–present Olivier Lalonde <olalonde@gmail.com>, James Talmage <james@talmage.io>, Ruben Verborgh\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n> of the Software, and to permit persons to whom the Software is furnished to do\n> so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\n> IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## generic-names\nLicense: MIT\nBy: Alexey Litvinov\nRepository: https://github.com/css-modules/generic-names\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2015 Alexey Litvinov\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## glob-parent\nLicense: ISC\nBy: Gulp Team, Elan Shanker, Blaine Bublitz\nRepository: https://github.com/gulpjs/glob-parent\n\n> The ISC License\n> \n> Copyright (c) 2015, 2019 Elan Shanker\n> \n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\n> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## host-validation-middleware\nLicense: MIT\nBy: sapphi-red\nRepository: https://github.com/sapphi-red/host-validation-middleware\n\n> MIT License\n> \n> Copyright (c) 2025 sapphi-red\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## http-proxy-3\nLicense: MIT\nBy: William Stein, Charlie Robbins, Jimb Esser, jcrugzz\nRepository: https://github.com/sagemathinc/http-proxy-3\n\n> node-http-3\n> \n> Copyright (c) 2010-2025 William Stein, Charlie Robbins, Jarrett Cruger & the Contributors.\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## icss-utils\nLicense: ISC\nBy: Glen Maddern\nRepository: https://github.com/css-modules/icss-utils\n\n> ISC License (ISC)\n> Copyright 2018 Glen Maddern\n> \n> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## is-binary-path\nLicense: MIT\nBy: Sindre Sorhus\nRepository: https://github.com/sindresorhus/is-binary-path\n\n> MIT License\n> \n> Copyright (c) 2019 Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com), Paul Miller (https://paulmillr.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## is-extglob\nLicense: MIT\nBy: Jon Schlinkert\nRepository: https://github.com/jonschlinkert/is-extglob\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014-2016, Jon Schlinkert\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## is-glob\nLicense: MIT\nBy: Jon Schlinkert, Brian Woodward, Daniel Perez\nRepository: https://github.com/micromatch/is-glob\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014-2017, Jon Schlinkert.\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## isexe, which\nLicense: ISC\nBy: Isaac Z. Schlueter\nRepositories: https://github.com/isaacs/isexe, https://github.com/isaacs/node-which\n\n> The ISC License\n> \n> Copyright (c) Isaac Z. Schlueter and Contributors\n> \n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\n> IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## js-tokens\nLicense: MIT\nBy: Simon Lydell\nRepository: https://github.com/lydell/js-tokens\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024 Simon Lydell\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## launch-editor, launch-editor-middleware\nLicense: MIT\nBy: Evan You\nRepositories: https://github.com/yyx990803/launch-editor, https://github.com/yyx990803/launch-editor\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2017-present, Yuxi (Evan) You\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## lilconfig\nLicense: MIT\nBy: antonk52\nRepository: https://github.com/antonk52/lilconfig\n\n> MIT License\n> \n> Copyright (c) 2022 Anton Kastritskiy\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## loader-utils\nLicense: MIT\nBy: Tobias Koppers @sokra\nRepository: https://github.com/webpack/loader-utils\n\n> Copyright JS Foundation and other contributors\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## lodash.camelcase\nLicense: MIT\nBy: John-David Dalton, Blaine Bublitz, Mathias Bynens\nRepository: https://github.com/lodash/lodash\n\n> Copyright jQuery Foundation and other contributors <https://jquery.org/>\n> \n> Based on Underscore.js, copyright Jeremy Ashkenas,\n> DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n> \n> This software consists of voluntary contributions made by many\n> individuals. For exact contribution history, see the revision history\n> available at https://github.com/lodash/lodash\n> \n> The following license applies to all parts of this software except as\n> documented below:\n> \n> ====\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n> \n> ====\n> \n> Copyright and related rights for sample code are waived via CC0. Sample\n> code is defined as all source code displayed within the prose of the\n> documentation.\n> \n> CC0: http://creativecommons.org/publicdomain/zero/1.0/\n> \n> ====\n> \n> Files located in the node_modules and vendor directories are externally\n> maintained libraries used by this software which have their own\n> licenses; we recommend you read them, as their terms may differ from the\n> terms above.\n\n---------------------------------------\n\n## magic-string\nLicense: MIT\nBy: Rich Harris\nRepository: https://github.com/Rich-Harris/magic-string\n\n> Copyright 2018 Rich Harris\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## mlly, ufo\nLicense: MIT\nRepositories: https://github.com/unjs/mlly, https://github.com/unjs/ufo\n\n> MIT License\n> \n> Copyright (c) Pooya Parsa <pooya@pi0.io>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## mrmime\nLicense: MIT\nBy: Luke Edwards\nRepository: https://github.com/lukeed/mrmime\n\n> The MIT License (MIT)\n> \n> Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (https://lukeed.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## normalize-path\nLicense: MIT\nBy: Jon Schlinkert, Blaine Bublitz\nRepository: https://github.com/jonschlinkert/normalize-path\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014-2018, Jon Schlinkert.\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## object-assign\nLicense: MIT\nBy: Sindre Sorhus\nRepository: https://github.com/sindresorhus/object-assign\n\n> The MIT License (MIT)\n> \n> Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## obug\nLicense: MIT\nBy: Kevin Deng\nRepository: https://github.com/sxzz/obug\n\n> The MIT License (MIT)\n> \n> Copyright © 2025-PRESENT Kevin Deng (https://github.com/sxzz)\n> Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>\n> Copyright (c) 2018-2021 Josh Junon\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## on-finished\nLicense: MIT\nBy: Douglas Christopher Wilson, Jonathan Ong\nRepository: https://github.com/jshttp/on-finished\n\n> (The MIT License)\n> \n> Copyright (c) 2013 Jonathan Ong <me@jongleberry.com>\n> Copyright (c) 2014 Douglas Christopher Wilson <doug@somethingdoug.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## parse5\nLicense: MIT\nBy: Ivan Nikulin, https://github.com/inikulin/parse5/graphs/contributors\nRepository: https://github.com/inikulin/parse5\n\n> Copyright (c) 2013-2019 Ivan Nikulin (ifaaan@gmail.com, https://github.com/inikulin)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## parseurl\nLicense: MIT\nBy: Douglas Christopher Wilson, Jonathan Ong\nRepository: https://github.com/pillarjs/parseurl\n\n> (The MIT License)\n> \n> Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>\n> Copyright (c) 2014-2017 Douglas Christopher Wilson <doug@somethingdoug.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## path-key, shebang-regex\nLicense: MIT\nBy: Sindre Sorhus\nRepositories: https://github.com/sindresorhus/path-key, https://github.com/sindresorhus/shebang-regex\n\n> MIT License\n> \n> Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## periscopic\nLicense: MIT\nRepository: https://github.com/Rich-Harris/periscopic\n\n> Copyright (c) 2019 Rich Harris\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## picocolors\nLicense: ISC\nBy: Alexey Raspopov\nRepository: https://github.com/alexeyraspopov/picocolors\n\n> ISC License\n> \n> Copyright (c) 2021-2024 Oleksii Raspopov, Kostiantyn Denysov, Anton Verinov\n> \n> Permission to use, copy, modify, and/or distribute this software for any\n> purpose with or without fee is hereby granted, provided that the above\n> copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n> OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## postcss-import\nLicense: MIT\nBy: Maxime Thirouin\nRepository: https://github.com/postcss/postcss-import\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014 Maxime Thirouin, Jason Campbell & Kevin Mårtensson\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## postcss-load-config\nLicense: MIT\nBy: Michael Ciniawky, Ryan Dunckel, Mateusz Derks, Dalton Santos, Patrick Gilday, François Wouts\nRepository: https://github.com/postcss/postcss-load-config\n\n> The MIT License (MIT)\n> \n> Copyright Michael Ciniawsky <michael.ciniawsky@gmail.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## postcss-modules\nLicense: MIT\nBy: Alexander Madyankin\nRepository: https://github.com/css-modules/postcss-modules\n\n> The MIT License (MIT)\n> \n> Copyright 2015-present Alexander Madyankin <alexander@madyankin.name>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## postcss-modules-extract-imports\nLicense: ISC\nBy: Glen Maddern\nRepository: https://github.com/css-modules/postcss-modules-extract-imports\n\n> Copyright 2015 Glen Maddern\n> \n> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## postcss-modules-local-by-default\nLicense: MIT\nBy: Mark Dalgleish\nRepository: https://github.com/css-modules/postcss-modules-local-by-default\n\n> The MIT License (MIT)\n> \n> Copyright 2015 Mark Dalgleish <mark.john.dalgleish@gmail.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## postcss-modules-scope\nLicense: ISC\nBy: Glen Maddern\nRepository: https://github.com/css-modules/postcss-modules-scope\n\n> ISC License (ISC)\n> \n> Copyright (c) 2015, Glen Maddern\n> \n> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## postcss-modules-values\nLicense: ISC\nBy: Glen Maddern\nRepository: https://github.com/css-modules/postcss-modules-values\n\n> ISC License (ISC)\n> \n> Copyright (c) 2015, Glen Maddern\n> \n> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n---------------------------------------\n\n## postcss-selector-parser\nLicense: MIT\nBy: Ben Briggs, Chris Eppstein\nRepository: https://github.com/postcss/postcss-selector-parser\n\n> Copyright (c) Ben Briggs <beneb.info@gmail.com> (http://beneb.info)\n> \n> Permission is hereby granted, free of charge, to any person\n> obtaining a copy of this software and associated documentation\n> files (the \"Software\"), to deal in the Software without\n> restriction, including without limitation the rights to use,\n> copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the\n> Software is furnished to do so, subject to the following\n> conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n> HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n> OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## postcss-value-parser\nLicense: MIT\nBy: Bogdan Chadkin\nRepository: https://github.com/TrySound/postcss-value-parser\n\n> Copyright (c) Bogdan Chadkin <trysound@yandex.ru>\n> \n> Permission is hereby granted, free of charge, to any person\n> obtaining a copy of this software and associated documentation\n> files (the \"Software\"), to deal in the Software without\n> restriction, including without limitation the rights to use,\n> copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the\n> Software is furnished to do so, subject to the following\n> conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n> HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n> OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## readdirp\nLicense: MIT\nBy: Thorsten Lorenz, Paul Miller\nRepository: https://github.com/paulmillr/readdirp\n\n> MIT License\n> \n> Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## resolve.exports, totalist\nLicense: MIT\nBy: Luke Edwards\nRepositories: https://github.com/lukeed/resolve.exports, https://github.com/lukeed/totalist\n\n> The MIT License (MIT)\n> \n> Copyright (c) Luke Edwards <luke.edwards05@gmail.com> (lukeed.com)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## shebang-command\nLicense: MIT\nBy: Kevin Mårtensson\nRepository: https://github.com/kevva/shebang-command\n\n> MIT License\n> \n> Copyright (c) Kevin Mårtensson <kevinmartensson@gmail.com> (github.com/kevva)\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## shell-quote\nLicense: MIT\nBy: James Halliday\nRepository: http://github.com/ljharb/shell-quote\n\n> The MIT License\n> \n> Copyright (c) 2013 James Halliday (mail@substack.net)\n> \n> Permission is hereby granted, free of charge, \n> to any person obtaining a copy of this software and \n> associated documentation files (the \"Software\"), to \n> deal in the Software without restriction, including \n> without limitation the rights to use, copy, modify, \n> merge, publish, distribute, sublicense, and/or sell \n> copies of the Software, and to permit persons to whom \n> the Software is furnished to do so, \n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice \n> shall be included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, \n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \n> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. \n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR \n> ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, \n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## sirv\nLicense: MIT\nBy: Luke Edwards\nRepository: https://github.com/lukeed/sirv\n\n---------------------------------------\n\n## statuses\nLicense: MIT\nBy: Douglas Christopher Wilson, Jonathan Ong\nRepository: https://github.com/jshttp/statuses\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2014 Jonathan Ong <me@jongleberry.com>\n> Copyright (c) 2016 Douglas Christopher Wilson <doug@somethingdoug.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## string-hash\nLicense: CC0-1.0\nBy: The Dark Sky Company\nRepository: https://github.com/darkskyapp/string-hash\n\n---------------------------------------\n\n## strip-literal\nLicense: MIT\nBy: Anthony Fu\nRepository: https://github.com/antfu/strip-literal\n\n> MIT License\n> \n> Copyright (c) 2022 Anthony Fu <https://github.com/antfu>\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n> SOFTWARE.\n\n---------------------------------------\n\n## to-regex-range\nLicense: MIT\nBy: Jon Schlinkert, Rouven Weßling\nRepository: https://github.com/micromatch/to-regex-range\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2015-present, Jon Schlinkert.\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy\n> of this software and associated documentation files (the \"Software\"), to deal\n> in the Software without restriction, including without limitation the rights\n> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the Software is\n> furnished to do so, subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in\n> all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n> THE SOFTWARE.\n\n---------------------------------------\n\n## unpipe\nLicense: MIT\nBy: Douglas Christopher Wilson\nRepository: https://github.com/stream-utils/unpipe\n\n> (The MIT License)\n> \n> Copyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## util-deprecate\nLicense: MIT\nBy: Nathan Rajlich\nRepository: https://github.com/TooTallNate/util-deprecate\n\n> (The MIT License)\n> \n> Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>\n> \n> Permission is hereby granted, free of charge, to any person\n> obtaining a copy of this software and associated documentation\n> files (the \"Software\"), to deal in the Software without\n> restriction, including without limitation the rights to use,\n> copy, modify, merge, publish, distribute, sublicense, and/or sell\n> copies of the Software, and to permit persons to whom the\n> Software is furnished to do so, subject to the following\n> conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n> OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n> HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n> WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n> FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n> OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## utils-merge\nLicense: MIT\nBy: Jared Hanson\nRepository: https://github.com/jaredhanson/utils-merge\n\n> The MIT License (MIT)\n> \n> Copyright (c) 2013-2017 Jared Hanson\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## vary\nLicense: MIT\nBy: Douglas Christopher Wilson\nRepository: https://github.com/jshttp/vary\n\n> (The MIT License)\n> \n> Copyright (c) 2014-2017 Douglas Christopher Wilson\n> \n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> 'Software'), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n> \n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n---------------------------------------\n\n## ws\nLicense: MIT\nBy: Einar Otto Stangvik\nRepository: https://github.com/websockets/ws\n\n> Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>\n> Copyright (c) 2013 Arnout Kazemier and contributors\n> Copyright (c) 2016 Luigi Pinca and contributors\n> \n> Permission is hereby granted, free of charge, to any person obtaining a copy of\n> this software and associated documentation files (the \"Software\"), to deal in\n> the Software without restriction, including without limitation the rights to\n> use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n> the Software, and to permit persons to whom the Software is furnished to do so,\n> subject to the following conditions:\n> \n> The above copyright notice and this permission notice shall be included in all\n> copies or substantial portions of the Software.\n> \n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n> FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "packages/vite/README.md",
    "content": "# Vite ⚡\n\n> Next Generation Frontend Tooling\n\n- 💡 Instant Server Start\n- ⚡️ Lightning Fast HMR\n- 🛠️ Rich Features\n- 📦 Optimized Build\n- 🔩 Universal Plugin Interface\n- 🔑 Fully Typed APIs\n\nVite (French word for \"fast\", pronounced `/viːt/`) is a new breed of frontend build tool that significantly improves the frontend development experience. It consists of two major parts:\n\n- A dev server that serves your source files over [native ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), with [rich built-in features](https://vite.dev/guide/features.html) and astonishingly fast [Hot Module Replacement (HMR)](https://vite.dev/guide/features.html#hot-module-replacement).\n\n- A [build command](https://vite.dev/guide/build.html) that bundles your code with [Rollup](https://rollupjs.org), pre-configured to output highly optimized static assets for production.\n\nIn addition, Vite is highly extensible via its [Plugin API](https://vite.dev/guide/api-plugin.html) and [JavaScript API](https://vite.dev/guide/api-javascript.html) with full typing support.\n\n[Read the Docs to Learn More](https://vite.dev).\n"
  },
  {
    "path": "packages/vite/bin/openChrome.js",
    "content": "/*\nCopyright (c) 2015-present, Facebook, Inc.\n\nThis source code is licensed under the MIT license found in the\nLICENSE file at\nhttps://github.com/facebook/create-react-app/blob/main/LICENSE\n*/\n\n/* global Application */\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction run(argv) {\n  const urlToOpen = argv[0]\n  // Allow requested program to be optional, default to Google Chrome\n  const programName = argv[1] ?? 'Google Chrome'\n\n  const app = Application(programName)\n\n  if (app.windows.length === 0) {\n    app.Window().make()\n  }\n\n  // 1: Looking for tab running debugger then,\n  //    Reload debugging tab if found, then return\n  const found = lookupTabWithUrl(urlToOpen, app)\n  if (found) {\n    found.targetWindow.activeTabIndex = found.targetTabIndex\n    found.targetTab.reload()\n    found.targetWindow.index = 1\n    app.activate()\n    return\n  }\n\n  // 2: Looking for Empty tab\n  //    In case debugging tab was not found\n  //    We try to find an empty tab instead\n  const emptyTabFound = lookupTabWithUrl('chrome://newtab/', app)\n  if (emptyTabFound) {\n    emptyTabFound.targetWindow.activeTabIndex = emptyTabFound.targetTabIndex\n    emptyTabFound.targetTab.url = urlToOpen\n    app.activate()\n    return\n  }\n\n  // 3: Create new tab\n  //    both debugging and empty tab were not found make a new tab with url\n  const firstWindow = app.windows[0]\n  firstWindow.tabs.push(app.Tab({ url: urlToOpen }))\n  app.activate()\n}\n\n/**\n * Lookup tab with given url\n */\nfunction lookupTabWithUrl(lookupUrl, app) {\n  const windows = app.windows()\n  for (const window of windows) {\n    for (const [tabIndex, tab] of window.tabs().entries()) {\n      if (tab.url().includes(lookupUrl)) {\n        return {\n          targetTab: tab,\n          targetTabIndex: tabIndex + 1,\n          targetWindow: window,\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/bin/vite.js",
    "content": "#!/usr/bin/env node\nimport { performance } from 'node:perf_hooks'\nimport module from 'node:module'\n\nif (!import.meta.url.includes('node_modules')) {\n  if (!process.env.DEBUG_DISABLE_SOURCE_MAP) {\n    // eslint-disable-next-line n/no-unsupported-features/node-builtins -- only used in dev\n    process.setSourceMapsEnabled(true)\n  }\n\n  process.on('unhandledRejection', (err) => {\n    throw new Error('UNHANDLED PROMISE REJECTION', { cause: err })\n  })\n}\n\nglobal.__vite_start_time = performance.now()\n\n// check debug mode first before requiring the CLI.\nconst debugIndex = process.argv.findIndex((arg) => /^(?:-d|--debug)$/.test(arg))\nconst filterIndex = process.argv.findIndex((arg) =>\n  /^(?:-f|--filter)$/.test(arg),\n)\nconst profileIndex = process.argv.indexOf('--profile')\n\nif (debugIndex > 0) {\n  let value = process.argv[debugIndex + 1]\n  if (!value || value[0] === '-') {\n    value = 'vite:*'\n  } else {\n    // support debugging multiple flags with comma-separated list\n    value = value\n      .split(',')\n      .map((v) => `vite:${v}`)\n      .join(',')\n  }\n  process.env.DEBUG = `${\n    process.env.DEBUG ? process.env.DEBUG + ',' : ''\n  }${value}`\n\n  if (filterIndex > 0) {\n    const filter = process.argv[filterIndex + 1]\n    if (filter && filter[0] !== '-') {\n      process.env.VITE_DEBUG_FILTER = filter\n    }\n  }\n}\n\nfunction start() {\n  try {\n    // eslint-disable-next-line n/no-unsupported-features/node-builtins -- it is supported in Node 22.8.0+ and only called if it exists\n    module.enableCompileCache?.()\n    // flush the cache after 10s because the cache is not flushed until process end\n    // for dev server, the cache is never flushed unless manually flushed because the process.exit is called\n    // also flushing the cache in SIGINT handler seems to cause the process to hang\n    setTimeout(() => {\n      try {\n        // eslint-disable-next-line n/no-unsupported-features/node-builtins -- it is supported in Node 22.12.0+ and only called if it exists\n        module.flushCompileCache?.()\n      } catch {}\n    }, 10 * 1000).unref()\n  } catch {}\n  return import('../dist/node/cli.js')\n}\n\nif (profileIndex > 0) {\n  process.argv.splice(profileIndex, 1)\n  const next = process.argv[profileIndex]\n  if (next && next[0] !== '-') {\n    process.argv.splice(profileIndex, 1)\n  }\n  const inspector = await import('node:inspector').then((r) => r.default)\n  const session = (global.__vite_profile_session = new inspector.Session())\n  session.connect()\n  session.post('Profiler.enable', () => {\n    session.post('Profiler.start', start)\n  })\n} else {\n  start()\n}\n"
  },
  {
    "path": "packages/vite/client.d.ts",
    "content": "/// <reference path=\"./types/importMeta.d.ts\" />\n\n// CSS modules\ntype CSSModuleClasses = { readonly [key: string]: string }\n\ndeclare module '*.module.css' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.scss' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.sass' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.less' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.styl' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.stylus' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.pcss' {\n  const classes: CSSModuleClasses\n  export default classes\n}\ndeclare module '*.module.sss' {\n  const classes: CSSModuleClasses\n  export default classes\n}\n\n// CSS\ndeclare module '*.css' {}\ndeclare module '*.scss' {}\ndeclare module '*.sass' {}\ndeclare module '*.less' {}\ndeclare module '*.styl' {}\ndeclare module '*.stylus' {}\ndeclare module '*.pcss' {}\ndeclare module '*.sss' {}\n\n// Built-in asset types\n// see `src/node/constants.ts`\n\n// images\ndeclare module '*.apng' {\n  const src: string\n  export default src\n}\ndeclare module '*.bmp' {\n  const src: string\n  export default src\n}\ndeclare module '*.png' {\n  const src: string\n  export default src\n}\ndeclare module '*.jpg' {\n  const src: string\n  export default src\n}\ndeclare module '*.jpeg' {\n  const src: string\n  export default src\n}\ndeclare module '*.jfif' {\n  const src: string\n  export default src\n}\ndeclare module '*.pjpeg' {\n  const src: string\n  export default src\n}\ndeclare module '*.pjp' {\n  const src: string\n  export default src\n}\ndeclare module '*.gif' {\n  const src: string\n  export default src\n}\ndeclare module '*.svg' {\n  const src: string\n  export default src\n}\ndeclare module '*.ico' {\n  const src: string\n  export default src\n}\ndeclare module '*.webp' {\n  const src: string\n  export default src\n}\ndeclare module '*.avif' {\n  const src: string\n  export default src\n}\ndeclare module '*.cur' {\n  const src: string\n  export default src\n}\ndeclare module '*.jxl' {\n  const src: string\n  export default src\n}\n\n// media\ndeclare module '*.mp4' {\n  const src: string\n  export default src\n}\ndeclare module '*.webm' {\n  const src: string\n  export default src\n}\ndeclare module '*.ogg' {\n  const src: string\n  export default src\n}\ndeclare module '*.mp3' {\n  const src: string\n  export default src\n}\ndeclare module '*.wav' {\n  const src: string\n  export default src\n}\ndeclare module '*.flac' {\n  const src: string\n  export default src\n}\ndeclare module '*.aac' {\n  const src: string\n  export default src\n}\ndeclare module '*.opus' {\n  const src: string\n  export default src\n}\ndeclare module '*.mov' {\n  const src: string\n  export default src\n}\ndeclare module '*.m4a' {\n  const src: string\n  export default src\n}\ndeclare module '*.vtt' {\n  const src: string\n  export default src\n}\n\n// fonts\ndeclare module '*.woff' {\n  const src: string\n  export default src\n}\ndeclare module '*.woff2' {\n  const src: string\n  export default src\n}\ndeclare module '*.eot' {\n  const src: string\n  export default src\n}\ndeclare module '*.ttf' {\n  const src: string\n  export default src\n}\ndeclare module '*.otf' {\n  const src: string\n  export default src\n}\n\n// other\ndeclare module '*.webmanifest' {\n  const src: string\n  export default src\n}\ndeclare module '*.pdf' {\n  const src: string\n  export default src\n}\ndeclare module '*.txt' {\n  const src: string\n  export default src\n}\n\n// wasm?init\ndeclare module '*.wasm?init' {\n  const initWasm: (\n    options?: WebAssembly.Imports,\n  ) => Promise<WebAssembly.Instance>\n  export default initWasm\n}\n\n// web worker\ndeclare module '*?worker' {\n  const workerConstructor: {\n    new (options?: { name?: string }): Worker\n  }\n  export default workerConstructor\n}\n\ndeclare module '*?worker&inline' {\n  const workerConstructor: {\n    new (options?: { name?: string }): Worker\n  }\n  export default workerConstructor\n}\n\ndeclare module '*?worker&url' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?sharedworker' {\n  const sharedWorkerConstructor: {\n    new (options?: { name?: string }): SharedWorker\n  }\n  export default sharedWorkerConstructor\n}\n\ndeclare module '*?sharedworker&inline' {\n  const sharedWorkerConstructor: {\n    new (options?: { name?: string }): SharedWorker\n  }\n  export default sharedWorkerConstructor\n}\n\ndeclare module '*?sharedworker&url' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?raw' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?url' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?inline' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?no-inline' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?url&inline' {\n  const src: string\n  export default src\n}\n\ndeclare module '*?url&no-inline' {\n  const src: string\n  export default src\n}\n\ndeclare interface VitePreloadErrorEvent extends Event {\n  payload: Error\n}\n\ndeclare interface WindowEventMap {\n  'vite:preloadError': VitePreloadErrorEvent\n}\n"
  },
  {
    "path": "packages/vite/misc/false.d.ts",
    "content": "declare const result: boolean\nexport default result\n"
  },
  {
    "path": "packages/vite/misc/false.js",
    "content": "export default false\n"
  },
  {
    "path": "packages/vite/misc/true.d.ts",
    "content": "declare const result: boolean\nexport default result\n"
  },
  {
    "path": "packages/vite/misc/true.js",
    "content": "export default true\n"
  },
  {
    "path": "packages/vite/package.json",
    "content": "{\n  \"name\": \"vite\",\n  \"version\": \"8.0.1\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"author\": \"Evan You\",\n  \"description\": \"Native-ESM powered web dev build tool\",\n  \"bin\": {\n    \"vite\": \"bin/vite.js\"\n  },\n  \"keywords\": [\n    \"frontend\",\n    \"framework\",\n    \"hmr\",\n    \"dev-server\",\n    \"build-tool\",\n    \"vite\"\n  ],\n  \"exports\": {\n    \".\": \"./dist/node/index.js\",\n    \"./client\": {\n      \"types\": \"./client.d.ts\"\n    },\n    \"./module-runner\": \"./dist/node/module-runner.js\",\n    \"./internal\": \"./dist/node/internal.js\",\n    \"./dist/client/*\": \"./dist/client/*\",\n    \"./types/*\": {\n      \"types\": \"./types/*\"\n    },\n    \"./types/internal/*\": null,\n    \"./package.json\": \"./package.json\"\n  },\n  \"imports\": {\n    \"#module-sync-enabled\": {\n      \"module-sync\": \"./misc/true.js\",\n      \"default\": \"./misc/false.js\"\n    },\n    \"#types/*\": \"./types/*.d.ts\",\n    \"#dep-types/*\": \"./src/types/*.d.ts\"\n  },\n  \"files\": [\n    \"bin\",\n    \"dist\",\n    \"misc/**/*.js\",\n    \"client.d.ts\",\n    \"types\"\n  ],\n  \"engines\": {\n    \"node\": \"^20.19.0 || >=22.12.0\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/vitejs/vite.git\",\n    \"directory\": \"packages/vite\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/vitejs/vite/issues\"\n  },\n  \"homepage\": \"https://vite.dev\",\n  \"funding\": \"https://github.com/vitejs/vite?sponsor=1\",\n  \"scripts\": {\n    \"dev\": \"premove dist && pnpm build-bundle -w\",\n    \"build\": \"premove dist && pnpm build-bundle && pnpm build-types\",\n    \"build-bundle\": \"rolldown --config rolldown.config.ts\",\n    \"build-types\": \"pnpm build-types-roll && pnpm build-types-check\",\n    \"build-types-roll\": \"rolldown --config rolldown.dts.config.ts\",\n    \"build-types-check\": \"tsc --project tsconfig.check.json\",\n    \"typecheck\": \"tsc && tsc -p src/node && tsc -p src/module-runner && tsc -p src/shared && tsc -p src/node/__tests_dts__ && tsc -p src/module-runner/__tests_dts__\",\n    \"lint\": \"eslint --cache --ext .ts src/**\",\n    \"format\": \"prettier --write --cache --parser typescript \\\"src/**/*.ts\\\"\",\n    \"generate-target\": \"tsx scripts/generateTarget.ts\",\n    \"prepublishOnly\": \"npm run build\"\n  },\n  \"//\": \"READ CONTRIBUTING.md to understand what to put under deps vs. devDeps!\",\n  \"dependencies\": {\n    \"lightningcss\": \"^1.32.0\",\n    \"picomatch\": \"^4.0.3\",\n    \"postcss\": \"^8.5.8\",\n    \"rolldown\": \"1.0.0-rc.10\",\n    \"tinyglobby\": \"^0.2.15\"\n  },\n  \"optionalDependencies\": {\n    \"fsevents\": \"~2.3.3\"\n  },\n  \"devDependencies\": {\n    \"@babel/parser\": \"^7.29.0\",\n    \"@jridgewell/remapping\": \"^2.3.5\",\n    \"@jridgewell/trace-mapping\": \"^0.3.31\",\n    \"@polka/compression\": \"^1.0.0-next.25\",\n    \"@rollup/plugin-alias\": \"^6.0.0\",\n    \"@rollup/plugin-dynamic-import-vars\": \"2.1.4\",\n    \"@rollup/pluginutils\": \"^5.3.0\",\n    \"@vercel/detect-agent\": \"^1.2.1\",\n    \"@types/escape-html\": \"^1.0.4\",\n    \"@types/pnpapi\": \"^0.0.5\",\n    \"@vitest/utils\": \"4.1.0\",\n    \"@vitejs/devtools\": \"^0.1.0\",\n    \"artichokie\": \"^0.4.2\",\n    \"baseline-browser-mapping\": \"^2.10.8\",\n    \"cac\": \"^7.0.0\",\n    \"chokidar\": \"^3.6.0\",\n    \"connect\": \"^3.7.0\",\n    \"convert-source-map\": \"^2.0.0\",\n    \"cors\": \"^2.8.6\",\n    \"cross-spawn\": \"^7.0.6\",\n    \"dotenv-expand\": \"^12.0.3\",\n    \"es-module-lexer\": \"^1.7.0\",\n    \"esbuild\": \"^0.27.4\",\n    \"escape-html\": \"^1.0.3\",\n    \"estree-walker\": \"^3.0.3\",\n    \"etag\": \"^1.8.1\",\n    \"host-validation-middleware\": \"^0.1.2\",\n    \"http-proxy-3\": \"^1.23.2\",\n    \"launch-editor-middleware\": \"^2.13.1\",\n    \"magic-string\": \"^0.30.21\",\n    \"mlly\": \"^1.8.1\",\n    \"mrmime\": \"^2.0.1\",\n    \"nanoid\": \"^5.1.7\",\n    \"obug\": \"^1.0.2\",\n    \"open\": \"^10.2.0\",\n    \"parse5\": \"^8.0.0\",\n    \"pathe\": \"^2.0.3\",\n    \"periscopic\": \"^4.0.2\",\n    \"picocolors\": \"^1.1.1\",\n    \"postcss-import\": \"^16.1.1\",\n    \"postcss-load-config\": \"^6.0.1\",\n    \"postcss-modules\": \"^6.0.1\",\n    \"premove\": \"^4.0.0\",\n    \"resolve.exports\": \"^2.0.3\",\n    \"rolldown-plugin-dts\": \"^0.22.5\",\n    \"rollup\": \"^4.59.0\",\n    \"rollup-plugin-license\": \"^3.7.0\",\n    \"sass\": \"^1.98.0\",\n    \"sass-embedded\": \"^1.98.0\",\n    \"sirv\": \"^3.0.2\",\n    \"strip-literal\": \"^3.1.0\",\n    \"terser\": \"^5.46.0\",\n    \"ufo\": \"^1.6.3\",\n    \"ws\": \"^8.19.0\"\n  },\n  \"peerDependencies\": {\n    \"@types/node\": \"^20.19.0 || >=22.12.0\",\n    \"@vitejs/devtools\": \"^0.1.0\",\n    \"esbuild\": \"^0.27.0\",\n    \"jiti\": \">=1.21.0\",\n    \"less\": \"^4.0.0\",\n    \"sass\": \"^1.70.0\",\n    \"sass-embedded\": \"^1.70.0\",\n    \"stylus\": \">=0.54.8\",\n    \"sugarss\": \"^5.0.0\",\n    \"terser\": \"^5.16.0\",\n    \"tsx\": \"^4.8.1\",\n    \"yaml\": \"^2.4.2\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@types/node\": {\n      \"optional\": true\n    },\n    \"@vitejs/devtools\": {\n      \"optional\": true\n    },\n    \"esbuild\": {\n      \"optional\": true\n    },\n    \"jiti\": {\n      \"optional\": true\n    },\n    \"sass\": {\n      \"optional\": true\n    },\n    \"sass-embedded\": {\n      \"optional\": true\n    },\n    \"stylus\": {\n      \"optional\": true\n    },\n    \"less\": {\n      \"optional\": true\n    },\n    \"sugarss\": {\n      \"optional\": true\n    },\n    \"terser\": {\n      \"optional\": true\n    },\n    \"tsx\": {\n      \"optional\": true\n    },\n    \"yaml\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/rolldown.config.ts",
    "content": "import { readFileSync, writeFileSync } from 'node:fs'\nimport path from 'node:path'\nimport MagicString from 'magic-string'\nimport type { Plugin } from 'rolldown'\nimport { defineConfig } from 'rolldown'\nimport { init, parse } from 'es-module-lexer'\nimport licensePlugin from './rollupLicensePlugin'\n\n// eslint-disable-next-line n/no-unsupported-features/node-builtins\nconst dirname = import.meta.dirname\nconst pkg = JSON.parse(\n  readFileSync(new URL('./package.json', import.meta.url)).toString(),\n)\nconst disableSourceMap = !!process.env.DEBUG_DISABLE_SOURCE_MAP\n\nconst envConfig = defineConfig({\n  input: path.resolve(dirname, 'src/client/env.ts'),\n  platform: 'browser',\n  transform: {\n    target: 'es2020',\n  },\n  output: {\n    dir: path.resolve(dirname, 'dist'),\n    entryFileNames: 'client/env.mjs',\n  },\n})\n\nconst clientConfig = defineConfig({\n  input: path.resolve(dirname, 'src/client/client.ts'),\n  platform: 'browser',\n  transform: {\n    target: 'es2020',\n  },\n  external: ['@vite/env'],\n  output: {\n    dir: path.resolve(dirname, 'dist'),\n    entryFileNames: 'client/client.mjs',\n  },\n})\n\nconst sharedNodeOptions = defineConfig({\n  platform: 'node',\n  treeshake: {\n    moduleSideEffects: [\n      {\n        test: /acorn|astring|escape-html/,\n        sideEffects: false,\n      },\n      {\n        external: true,\n        sideEffects: false,\n      },\n    ],\n    propertyReadSideEffects: false,\n  },\n  output: {\n    dir: './dist',\n    entryFileNames: `node/[name].js`,\n    chunkFileNames: 'node/chunks/[name].js',\n    exports: 'named',\n    format: 'esm',\n    externalLiveBindings: false,\n  },\n  onwarn(warning, warn) {\n    if (warning.message.includes('Circular dependency')) {\n      return\n    }\n    warn(warning)\n  },\n})\n\nconst nodeConfig = defineConfig({\n  ...sharedNodeOptions,\n  input: {\n    index: path.resolve(dirname, 'src/node/index.ts'),\n    cli: path.resolve(dirname, 'src/node/cli.ts'),\n    internal: path.resolve(dirname, 'src/node/internalIndex.ts'),\n  },\n  external: [\n    /^vite\\//,\n    'fsevents',\n    /^rolldown\\//,\n    /^tsx\\//,\n    /^@vitejs\\/devtools\\//,\n    /^#/,\n    'sugarss', // postcss-import -> sugarss\n    'supports-color',\n    'utf-8-validate', // ws\n    'bufferutil', // ws\n    ...Object.keys(pkg.dependencies),\n    ...Object.keys(pkg.peerDependencies),\n  ],\n  plugins: [\n    shimDepsPlugin({\n      'postcss-load-config/src/req.js': [\n        {\n          src: \"const { pathToFileURL } = require('node:url')\",\n          replacement: `const { fileURLToPath, pathToFileURL } = require('node:url')`,\n        },\n        {\n          src: '__filename',\n          replacement: 'fileURLToPath(import.meta.url)',\n        },\n      ],\n      // postcss-import uses the `resolve` dep if the `resolve` option is not passed.\n      // However, we always pass the `resolve` option. It also uses `read-cache` if\n      // the `load` option is not passed, but we also always pass the `load` option.\n      // Remove these two imports to avoid bundling them.\n      'postcss-import/index.js': [\n        {\n          src: 'const resolveId = require(\"./lib/resolve-id\")',\n          replacement: 'const resolveId = (id) => id',\n        },\n        {\n          src: 'const loadContent = require(\"./lib/load-content\")',\n          replacement: 'const loadContent = () => \"\"',\n        },\n      ],\n      'postcss-import/lib/parse-styles.js': [\n        {\n          src: 'const resolveId = require(\"./resolve-id\")',\n          replacement: 'const resolveId = (id) => id',\n        },\n      ],\n    }),\n    buildTimeImportMetaUrlPlugin(),\n    licensePlugin(\n      path.resolve(dirname, 'LICENSE.md'),\n      'Vite core license',\n      'Vite',\n    ),\n    writeTypesPlugin(),\n    enableSourceMapsInWatchModePlugin(),\n    externalizeDepsInWatchPlugin(),\n  ],\n})\n\nconst moduleRunnerConfig = defineConfig({\n  ...sharedNodeOptions,\n  input: {\n    'module-runner': path.resolve(dirname, 'src/module-runner/index.ts'),\n  },\n  external: [\n    'fsevents',\n    'lightningcss',\n    /^rolldown\\//,\n    '@vitejs/devtools/cli-commands',\n    ...Object.keys(pkg.dependencies),\n  ],\n  plugins: [bundleSizeLimit(54), enableSourceMapsInWatchModePlugin()],\n  output: {\n    ...sharedNodeOptions.output,\n    minify: {\n      compress: true,\n      mangle: false,\n      codegen: false,\n    },\n  },\n})\n\nexport default defineConfig([\n  envConfig,\n  clientConfig,\n  nodeConfig,\n  moduleRunnerConfig,\n])\n\n// #region Plugins\n\nfunction enableSourceMapsInWatchModePlugin(): Plugin {\n  return {\n    name: 'enable-source-maps',\n    outputOptions(options) {\n      if (this.meta.watchMode && !disableSourceMap) {\n        options.sourcemap = 'inline'\n      }\n    },\n  }\n}\n\nfunction writeTypesPlugin(): Plugin {\n  return {\n    name: 'write-types',\n    async writeBundle() {\n      if (this.meta.watchMode) {\n        writeFileSync(\n          'dist/node/index.d.ts',\n          \"export * from '../../src/node/index.ts'\",\n        )\n        writeFileSync(\n          'dist/node/module-runner.d.ts',\n          \"export * from '../../src/module-runner/index.ts'\",\n        )\n      }\n    },\n  }\n}\n\nfunction externalizeDepsInWatchPlugin(): Plugin {\n  return {\n    name: 'externalize-deps-in-watch',\n    options(options) {\n      if (this.meta.watchMode) {\n        options.external ||= []\n        if (!Array.isArray(options.external))\n          throw new Error('external must be an array')\n        options.external = options.external.concat(\n          Object.keys(pkg.devDependencies),\n        )\n      }\n    },\n  }\n}\n\ninterface ShimOptions {\n  src?: string\n  replacement: string\n  pattern?: RegExp\n}\n\nfunction shimDepsPlugin(deps: Record<string, ShimOptions[]>): Plugin {\n  const transformed: Record<string, boolean> = {}\n\n  return {\n    name: 'shim-deps',\n    transform: {\n      filter: {\n        id: new RegExp(`(?:${Object.keys(deps).join('|')})$`),\n      },\n      handler(code, id) {\n        const file = Object.keys(deps).find((file) =>\n          id.replace(/\\\\/g, '/').endsWith(file),\n        )\n        if (!file) return\n\n        for (const { src, replacement, pattern } of deps[file]) {\n          const magicString = new MagicString(code)\n\n          if (src) {\n            const pos = code.indexOf(src)\n            if (pos < 0) {\n              this.error(\n                `Could not find expected src \"${src}\" in file \"${file}\"`,\n              )\n            }\n            transformed[file] = true\n            magicString.overwrite(pos, pos + src.length, replacement)\n          }\n\n          if (pattern) {\n            let match\n            while ((match = pattern.exec(code))) {\n              transformed[file] = true\n              const start = match.index\n              const end = start + match[0].length\n              let _replacement = replacement\n              for (let i = 1; i <= match.length; i++) {\n                _replacement = _replacement.replace(`$${i}`, match[i] || '')\n              }\n              magicString.overwrite(start, end, _replacement)\n            }\n            if (!transformed[file]) {\n              this.error(\n                `Could not find expected pattern \"${pattern}\" in file \"${file}\"`,\n              )\n            }\n          }\n\n          code = magicString.toString()\n        }\n\n        console.log(`shimmed: ${file}`)\n\n        return code\n      },\n    },\n    buildEnd(err) {\n      if (this.meta.watchMode) return\n\n      if (!err) {\n        for (const file in deps) {\n          if (!transformed[file]) {\n            this.error(\n              `Did not find \"${file}\" which is supposed to be shimmed, was the file renamed?`,\n            )\n          }\n        }\n      }\n    },\n  }\n}\n\nfunction buildTimeImportMetaUrlPlugin(): Plugin {\n  const idMap: Record<string, number> = {}\n  let lastIndex = 0\n\n  const prefix = `__vite_buildTimeImportMetaUrl_`\n  const keepCommentRE = /\\/\\*\\*\\s*[#@]__KEEP__\\s*\\*\\/\\s*$/\n\n  return {\n    name: 'import-meta-current-dirname',\n    transform: {\n      filter: {\n        code: 'import.meta.url',\n      },\n      async handler(code, id) {\n        const relativeId = path.relative(dirname, id).replaceAll('\\\\', '/')\n        // only replace import.meta.url in src/\n        if (!relativeId.startsWith('src/')) return\n\n        let index: number\n        if (idMap[id]) {\n          index = idMap[id]\n        } else {\n          index = idMap[id] = lastIndex\n          lastIndex++\n        }\n\n        await init\n\n        const s = new MagicString(code)\n        const [imports] = parse(code)\n        for (const { t, ss, se } of imports) {\n          if (t === 3 && code.slice(se, se + 4) === '.url') {\n            // ignore import.meta.url with /** #__KEEP__ */ comment\n            if (keepCommentRE.test(code.slice(0, ss))) {\n              keepCommentRE.lastIndex = 0\n              continue\n            }\n\n            // import.meta.url\n            s.overwrite(ss, se + 4, `${prefix}${index}`)\n          }\n        }\n        return s.hasChanged() ? s.toString() : undefined\n      },\n    },\n    renderChunk(code, chunk, outputOptions) {\n      if (!code.includes(prefix)) return\n\n      return code.replace(\n        /__vite_buildTimeImportMetaUrl_(\\d+)/g,\n        (_, index) => {\n          const originalFile = Object.keys(idMap).find(\n            (key) => idMap[key] === +index,\n          )\n          if (!originalFile) {\n            throw new Error(\n              `Could not find original file for ${prefix}${index} in ${chunk.fileName}`,\n            )\n          }\n          const outputFile = path.resolve(outputOptions.dir!, chunk.fileName)\n          const relativePath = path\n            .relative(path.dirname(outputFile), originalFile)\n            .replaceAll('\\\\', '/')\n\n          if (outputOptions.format === 'es') {\n            return `new URL(${JSON.stringify(relativePath)}, import.meta.url)`\n          } else if (outputOptions.format === 'cjs') {\n            return `new URL(${JSON.stringify(\n              relativePath,\n            )}, require('node:url').pathToFileURL(__filename))`\n          } else {\n            throw new Error(`Unsupported output format ${outputOptions.format}`)\n          }\n        },\n      )\n    },\n  }\n}\n\n/**\n * Guard the bundle size\n *\n * @param limit size in kB\n */\nfunction bundleSizeLimit(limit: number): Plugin {\n  let size = 0\n\n  return {\n    name: 'bundle-limit',\n    generateBundle(_, bundle) {\n      if (this.meta.watchMode) return\n\n      size = Buffer.byteLength(\n        Object.values(bundle)\n          .map((i) => ('code' in i ? i.code : ''))\n          .join(''),\n        'utf-8',\n      )\n    },\n    closeBundle() {\n      if (this.meta.watchMode) return\n\n      const kb = size / 1000\n      if (kb > limit) {\n        this.error(\n          `Bundle size exceeded ${limit} kB, current size is ${kb.toFixed(\n            2,\n          )}kb.`,\n        )\n      }\n    },\n  }\n}\n\n// #endregion\n"
  },
  {
    "path": "packages/vite/rolldown.dts.config.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { builtinModules } from 'node:module'\nimport { defineConfig } from 'rolldown'\nimport type {\n  OutputChunk,\n  Plugin,\n  PluginContext,\n  RenderedChunk,\n} from 'rolldown'\nimport type { ESTree } from 'rolldown/utils'\nimport { parseAst } from 'rolldown/parseAst'\nimport { dts } from 'rolldown-plugin-dts'\nimport { parse as parseWithBabel } from '@babel/parser'\nimport { walk } from 'estree-walker'\nimport MagicString from 'magic-string'\n\ntype Directive = ESTree.Directive\ntype ModuleExportName = ESTree.ModuleExportName\ntype Program = ESTree.Program\ntype Statement = ESTree.Statement\n\nconst pkg = JSON.parse(\n  readFileSync(new URL('./package.json', import.meta.url)).toString(),\n)\n\nconst external = [\n  /^node:*/,\n  /^vite\\//,\n  /^rolldown\\//,\n  /^#types\\//,\n  ...Object.keys(pkg.dependencies),\n  ...Object.keys(pkg.peerDependencies),\n]\n\nexport default defineConfig({\n  input: {\n    index: './src/node/index.ts',\n    'module-runner': './src/module-runner/index.ts',\n    internal: './src/node/internalIndex.ts',\n  },\n  output: {\n    dir: './dist/node',\n    chunkFileNames: 'chunks/[name].d.ts',\n    format: 'esm',\n  },\n  treeshake: {\n    moduleSideEffects: 'no-external',\n  },\n  external,\n  plugins: [\n    patchTypes(),\n    addNodePrefix(),\n    dts({\n      tsconfig: './tsconfig.base.json',\n      compilerOptions: {\n        noEmit: false,\n        skipLibCheck: true, // lib check is done on final types\n        stripInternal: true,\n        paths: {\n          'vite/module-runner': ['./src/module-runner'],\n        },\n      },\n      emitDtsOnly: true,\n    }),\n  ],\n})\n\n// Taken from https://stackoverflow.com/a/36328890\nconst multilineCommentsRE = /\\/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*\\//g\nconst licenseCommentsRE = /MIT License|MIT license|BSD license/\nconst consecutiveNewlinesRE = /\\n{2,}/g\nconst identifierWithTrailingDollarRE = /\\b(\\w+)\\$\\d+\\b/g\n\n/**\n * Replace specific identifiers with a more readable name, grouped by\n * the module that imports the identifier as a named import alias\n */\nconst identifierReplacements: Record<string, Record<string, string>> = {\n  'vite/module-runner': {\n    FetchResult$1: 'moduleRunner_FetchResult',\n  },\n  rolldown: {\n    Plugin$1: 'Rolldown.Plugin',\n    TransformResult$1: 'Rolldown.TransformResult',\n  },\n  'rolldown/utils': {\n    TransformOptions$1: 'rolldown_utils_TransformOptions',\n    TransformResult$2: 'rolldown_utils_TransformResult',\n  },\n  'node:http': {\n    Server$1: 'http.Server',\n    IncomingMessage$1: 'http.IncomingMessage',\n  },\n  'node:https': {\n    Server$2: 'HttpsServer',\n    ServerOptions$2: 'HttpsServerOptions',\n  },\n  'node:url': {\n    URL$1: 'url_URL',\n  },\n  '#types/hmrPayload': {\n    CustomPayload$1: 'hmrPayload_CustomPayload',\n    HotPayload$1: 'hmrPayload_HotPayload',\n  },\n  '#types/customEvent': {\n    InferCustomEventPayload$1: 'hmrPayload_InferCustomEventPayload',\n  },\n  '#types/internal/esbuildOptions': {\n    EsbuildTransformOptions$1: 'esbuildOptions_EsbuildTransformOptions',\n  },\n  '#types/internal/lightningcssOptions': {\n    LightningCSSOptions$1: 'lightningcssOptions_LightningCSSOptions',\n  },\n}\n\nconst ignoreConfusingTypeNames = [\n  // type names that are declared\n  'MinimalPluginContext$1',\n  'ServerOptions$1',\n  'ServerOptions$3',\n  // temporary variables for types\n  'parseAst$1',\n  'parseAstAsync$1',\n]\n\n/**\n * Patch the types files before passing to dts plugin\n * 1. Validate unallowed dependency imports\n * 2. Replace confusing type names\n * 3. Strip leftover internal types\n * 4. Clean unnecessary comments\n */\nfunction patchTypes(): Plugin {\n  return {\n    name: 'patch-types',\n    generateBundle: {\n      order: 'post',\n      handler(_opts, bundle) {\n        for (const chunk of Object.values(bundle)) {\n          if (chunk.type !== 'chunk') continue\n\n          const ast = parseAst(chunk.code, { lang: 'ts', sourceType: 'module' })\n          const importBindings = getAllImportBindings(ast)\n          if (\n            chunk.fileName.startsWith('module-runner') ||\n            // index and moduleRunner have a common chunk\n            chunk.fileName.startsWith('chunks/') ||\n            chunk.fileName.startsWith('types.d-')\n          ) {\n            validateRunnerChunk.call(this, chunk, importBindings)\n          } else {\n            validateChunkImports.call(this, chunk, importBindings)\n            replaceConfusingTypeNames.call(this, chunk, importBindings)\n            stripInternalTypes.call(this, chunk)\n            cleanUnnecessaryComments(chunk)\n          }\n        }\n      },\n    },\n  }\n}\n\nfunction stringifyModuleExportName(node: ModuleExportName): string {\n  if (node.type === 'Identifier') {\n    return node.name\n  }\n  return node.value\n}\n\ntype ImportBindings = { id: string; bindings: string[]; locals: string[] }\n\nfunction getImportBindings(\n  node: Directive | Statement,\n): ImportBindings | undefined {\n  if (node.type === 'ImportDeclaration') {\n    return {\n      id: node.source.value,\n      bindings: node.specifiers.map((s) =>\n        s.type === 'ImportDefaultSpecifier'\n          ? 'default'\n          : s.type === 'ImportNamespaceSpecifier'\n            ? '*'\n            : stringifyModuleExportName(s.imported),\n      ),\n      locals: node.specifiers.map((s) => s.local.name),\n    }\n  }\n  if (node.type === 'ExportNamedDeclaration') {\n    if (!node.source) return undefined\n    return {\n      id: node.source.value,\n      bindings: node.specifiers.map((s) => stringifyModuleExportName(s.local)),\n      locals: [],\n    }\n  }\n  if (node.type === 'ExportAllDeclaration') {\n    if (!node.source) return undefined\n    return { id: node.source.value, bindings: ['*'], locals: [] }\n  }\n}\n\nfunction getAllImportBindings(ast: Program): ImportBindings[] {\n  return ast.body.flatMap((node) => getImportBindings(node) ?? [])\n}\n\n/**\n * Runner chunk should only import local dependencies to stay lightweight\n */\nfunction validateRunnerChunk(\n  this: PluginContext,\n  chunk: RenderedChunk,\n  importBindings: ImportBindings[],\n) {\n  for (const { id, bindings } of importBindings) {\n    if (\n      !id.startsWith('./') &&\n      !id.startsWith('../') &&\n      !id.startsWith('#') &&\n      // index and moduleRunner have a common chunk\n      !id.startsWith('chunks/') &&\n      !id.startsWith('types.d')\n    ) {\n      this.warn(\n        `${chunk.fileName} imports \"${bindings.join(', ')}\" from \"${id}\" which is not allowed`,\n      )\n      process.exitCode = 1\n    }\n  }\n}\n\n/**\n * Validate that chunk imports do not import dev deps\n */\nfunction validateChunkImports(\n  this: PluginContext,\n  chunk: RenderedChunk,\n  importBindings: ImportBindings[],\n) {\n  const deps = Object.keys(pkg.dependencies)\n  for (const { id, bindings } of importBindings) {\n    if (\n      !id.startsWith('./') &&\n      !id.startsWith('../') &&\n      !id.startsWith('#') &&\n      !id.startsWith('node:') &&\n      !id.startsWith('types.d') &&\n      !id.startsWith('vite/') &&\n      // index and moduleRunner have a common chunk\n      !id.startsWith('chunks/') &&\n      !deps.includes(id) &&\n      !deps.some((name) => id.startsWith(name + '/'))\n    ) {\n      // If validation failed, only warn and set exit code 1 so that files\n      // are written to disk for inspection, but the build will fail\n      this.warn(\n        `${chunk.fileName} imports \"${bindings.join(', ')}\" from \"${id}\" which is not allowed`,\n      )\n      process.exitCode = 1\n    }\n  }\n}\n\n/**\n * Rollup deduplicate type names with a trailing `$1` or `$2`, which can be\n * confusing when showed in autocompletions. Try to replace with a better name\n */\nfunction replaceConfusingTypeNames(\n  this: PluginContext,\n  chunk: OutputChunk,\n  importBindings: ImportBindings[],\n) {\n  const isInternalEntry = chunk.fileName.startsWith('internal.')\n  if (!isInternalEntry) {\n    for (const modName in identifierReplacements) {\n      const imp = importBindings.filter((imp) => imp.id === modName)\n      // Validate that `identifierReplacements` is not outdated if there's no match\n      if (imp.length === 0) {\n        this.warn(\n          `${chunk.fileName} does not import \"${modName}\" for replacement`,\n        )\n        process.exitCode = 1\n        continue\n      }\n\n      const replacements = identifierReplacements[modName]\n      for (const id in replacements) {\n        // Validate that `identifierReplacements` is not outdated if there's no match\n        if (!imp.some((i) => i.locals.includes(id))) {\n          this.warn(\n            `${chunk.fileName} does not import \"${id}\" from \"${modName}\" for replacement`,\n          )\n          process.exitCode = 1\n          continue\n        }\n\n        const betterId = replacements[id]\n        const regexEscapedId = escapeRegex(id)\n        // If the better id accesses a namespace, the existing `Foo as Foo$1`\n        // named import cannot be replaced with `Foo as Namespace.Foo`, so we\n        // pre-emptively remove the whole named import\n        if (betterId.includes('.')) {\n          chunk.code = chunk.code.replace(\n            new RegExp(`\\\\b\\\\w+\\\\b as ${regexEscapedId},?\\\\s?`),\n            '',\n          )\n        }\n        chunk.code = chunk.code.replace(\n          new RegExp(`\\\\b${regexEscapedId}\\\\b`, 'g'),\n          betterId,\n        )\n      }\n    }\n  }\n\n  const identifiers = unique(\n    Array.from(\n      chunk.code.matchAll(identifierWithTrailingDollarRE),\n      (m) => m[0],\n    ),\n  )\n  const unreplacedIds = identifiers.filter(\n    (id) => !ignoreConfusingTypeNames.includes(id),\n  )\n  if (unreplacedIds.length) {\n    const unreplacedStr = unreplacedIds.map((id) => `\\n- ${id}`).join('')\n    this.warn(\n      `${chunk.fileName} contains confusing identifier names${unreplacedStr}`,\n    )\n    process.exitCode = 1\n  }\n\n  if (!isInternalEntry) {\n    const notUsedConfusingTypeNames = ignoreConfusingTypeNames.filter(\n      (id) => !identifiers.includes(id),\n    )\n    // Validate that `identifierReplacements` is not outdated if there's no match\n    if (notUsedConfusingTypeNames.length) {\n      const notUsedStr = notUsedConfusingTypeNames\n        .map((id) => `\\n- ${id}`)\n        .join('')\n      this.warn(\n        `${chunk.fileName} contains unused identifier names${notUsedStr}`,\n      )\n      process.exitCode = 1\n    }\n  }\n}\n\n/**\n * While we already enable `compilerOptions.stripInternal`, some internal comments\n * like internal parameters are still not stripped by TypeScript, so we run another\n * pass here.\n */\nfunction stripInternalTypes(this: PluginContext, chunk: OutputChunk) {\n  if (chunk.code.includes('@internal')) {\n    const s = new MagicString(chunk.code)\n    // need to parse with babel to get the comments\n    const ast = parseWithBabel(chunk.code, {\n      plugins: ['typescript'],\n      sourceType: 'module',\n    })\n\n    walk(ast as any, {\n      enter(node: any) {\n        if (removeInternal(s, node)) {\n          this.skip()\n        }\n      },\n    })\n\n    chunk.code = s.toString()\n\n    if (chunk.code.includes('@internal')) {\n      this.warn(`${chunk.fileName} has unhandled @internal declarations`)\n      process.exitCode = 1\n    }\n  }\n}\n\n/**\n * Remove `@internal` comments not handled by `compilerOptions.stripInternal`\n * Reference: https://github.com/vuejs/core/blob/main/rollup.dts.config.js\n */\nfunction removeInternal(s: MagicString, node: any): boolean {\n  if (\n    node.leadingComments &&\n    node.leadingComments.some((c: any) => {\n      return c.type === 'CommentBlock' && c.value.includes('@internal')\n    })\n  ) {\n    // Examples:\n    // function a(foo: string, /* @internal */ bar: number, baz: boolean)\n    //                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n    // type Enum = Foo | /* @internal */ Bar | Baz\n    //                   ^^^^^^^^^^^^^^^^^^^^^\n    // strip trailing comma or pipe\n    const trailingRe = /\\s*[,|]/y\n    trailingRe.lastIndex = node.end\n    const trailingStr = trailingRe.exec(s.original)?.[0] ?? ''\n    s.remove(node.leadingComments[0].start, node.end + trailingStr.length)\n    return true\n  }\n  return false\n}\n\nfunction cleanUnnecessaryComments(chunk: OutputChunk) {\n  chunk.code = chunk.code\n    .replace(multilineCommentsRE, (m) => {\n      return licenseCommentsRE.test(m) ? '' : m\n    })\n    .replace(consecutiveNewlinesRE, '\\n\\n')\n}\n\nconst escapeRegexRE = /[-/\\\\^$*+?.()|[\\]{}]/g\nfunction escapeRegex(str: string): string {\n  return str.replace(escapeRegexRE, '\\\\$&')\n}\n\nfunction unique<T>(arr: T[]): T[] {\n  return Array.from(new Set(arr))\n}\n\nfunction addNodePrefix(): Plugin {\n  return {\n    name: 'add-node-prefix',\n    resolveId: {\n      order: 'pre',\n      filter: {\n        id: new RegExp(`^(?:${builtinModules.join('|')})$`),\n      },\n      handler(id) {\n        return { id: `node:${id}`, external: true }\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/rollupLicensePlugin.ts",
    "content": "import fs from 'node:fs'\nimport license from 'rollup-plugin-license'\nimport type { Dependency } from 'rollup-plugin-license'\nimport colors from 'picocolors'\nimport type { Plugin, PluginContext } from 'rollup'\n\nexport default function licensePlugin(\n  licenseFilePath: string,\n  licenseTitle: string,\n  packageName: string,\n  additionalSection?: string,\n): Plugin {\n  const originalPlugin = license({\n    thirdParty(dependencies) {\n      // https://github.com/rollup/rollup/blob/master/build-plugins/generate-license-file.js\n      // MIT Licensed https://github.com/rollup/rollup/blob/master/LICENSE-CORE.md\n      const coreLicense = fs.readFileSync(\n        new URL('../../LICENSE', import.meta.url),\n      )\n\n      const deps = sortDependencies(dependencies)\n      const licenses = sortLicenses(\n        new Set(\n          dependencies.map((dep) => dep.license).filter(Boolean) as string[],\n        ),\n      )\n\n      let dependencyLicenseTexts = ''\n      for (let i = 0; i < deps.length; i++) {\n        // Find dependencies with the same license text so it can be shared\n        const licenseText = deps[i].licenseText\n        const sameDeps = [deps[i]]\n        if (licenseText) {\n          for (let j = i + 1; j < deps.length; j++) {\n            if (licenseText === deps[j].licenseText) {\n              sameDeps.push(...deps.splice(j, 1))\n              j--\n            }\n          }\n        }\n\n        let text = `## ${sameDeps.map((d) => d.name).join(', ')}\\n`\n        const depInfos = sameDeps.map((d) => getDependencyInformation(d))\n\n        // If all same dependencies have the same license and contributor names, show them only once\n        if (\n          depInfos.length > 1 &&\n          depInfos.every(\n            (info) =>\n              info.license === depInfos[0].license &&\n              info.names === depInfos[0].names,\n          )\n        ) {\n          const { license, names } = depInfos[0]\n          const repositoryText = depInfos\n            .map((info) => info.repository)\n            .filter(Boolean)\n            .join(', ')\n\n          if (license) text += `License: ${license}\\n`\n          if (names) text += `By: ${names}\\n`\n          if (repositoryText) text += `Repositories: ${repositoryText}\\n`\n        }\n        // Else show each dependency separately\n        else {\n          for (let j = 0; j < depInfos.length; j++) {\n            const { license, names, repository } = depInfos[j]\n\n            if (license) text += `License: ${license}\\n`\n            if (names) text += `By: ${names}\\n`\n            if (repository) text += `Repository: ${repository}\\n`\n            if (j !== depInfos.length - 1) text += '\\n'\n          }\n        }\n\n        if (licenseText) {\n          text +=\n            '\\n' +\n            licenseText\n              .trim()\n              .replace(/\\r\\n|\\r/g, '\\n')\n              .split('\\n')\n              .map((line) => `> ${line}`)\n              .join('\\n') +\n            '\\n'\n        }\n\n        if (i !== deps.length - 1) {\n          text += '\\n---------------------------------------\\n\\n'\n        }\n\n        dependencyLicenseTexts += text\n      }\n\n      const licenseText =\n        `# ${licenseTitle}\\n` +\n        `${packageName} is released under the MIT license:\\n\\n` +\n        coreLicense +\n        `\\n` +\n        (additionalSection || '') +\n        `# Licenses of bundled dependencies\\n` +\n        `The published ${packageName} artifact additionally contains code with the following licenses:\\n` +\n        `${licenses.join(', ')}\\n\\n` +\n        `# Bundled dependencies:\\n` +\n        dependencyLicenseTexts\n\n      const existingLicenseText = fs.readFileSync(licenseFilePath, 'utf-8')\n      if (existingLicenseText !== licenseText) {\n        fs.writeFileSync(licenseFilePath, licenseText)\n        console.warn(\n          colors.yellow(\n            '\\nLICENSE.md updated. You should commit the updated file.\\n',\n          ),\n        )\n      }\n    },\n  })\n  // skip for watch mode\n  for (const hook of ['renderChunk', 'generateBundle'] as const) {\n    const originalHook = originalPlugin[hook]!\n    originalPlugin[hook] = function (this: PluginContext, ...args: unknown[]) {\n      if (this.meta.watchMode) return\n      return (originalHook as Function).apply(this, args)\n    }\n  }\n  return originalPlugin\n}\n\nfunction sortDependencies(dependencies: Dependency[]) {\n  return dependencies.sort(({ name: nameA }, { name: nameB }) => {\n    return nameA! > nameB! ? 1 : nameB! > nameA! ? -1 : 0\n  })\n}\n\nfunction sortLicenses(licenses: Set<string>) {\n  let withParenthesis: string[] = []\n  let noParenthesis: string[] = []\n  licenses.forEach((license) => {\n    if (license[0] === '(') {\n      withParenthesis.push(license)\n    } else {\n      noParenthesis.push(license)\n    }\n  })\n  withParenthesis = withParenthesis.sort()\n  noParenthesis = noParenthesis.sort()\n  return [...noParenthesis, ...withParenthesis]\n}\n\ninterface DependencyInfo {\n  license?: string\n  names?: string\n  repository?: string\n}\n\nfunction getDependencyInformation(dep: Dependency): DependencyInfo {\n  const info: DependencyInfo = {}\n  const { license, author, maintainers, contributors, repository } = dep\n\n  if (license) {\n    info.license = license\n  }\n\n  const names = new Set<string>()\n  for (const person of [author, ...maintainers, ...contributors]) {\n    const name = typeof person === 'string' ? person : person?.name\n    if (name) {\n      names.add(name)\n    }\n  }\n  if (names.size > 0) {\n    info.names = Array.from(names).join(', ')\n  }\n\n  if (repository) {\n    info.repository = normalizeGitUrl(\n      typeof repository === 'string' ? repository : repository.url,\n    )\n  }\n\n  return info\n}\n\nfunction normalizeGitUrl(url: string): string {\n  url = url\n    .replace(/^git\\+/, '')\n    .replace(/\\.git$/, '')\n    .replace(/(^|\\/)[^/]+?@/, '$1') // remove \"user@\" from \"ssh://user@host.com:...\"\n    .replace(/(\\.[^.]+?):/, '$1/') // change \".com:\" to \".com/\" from \"ssh://user@host.com:...\"\n    .replace(/^git:\\/\\//, 'https://')\n    .replace(/^ssh:\\/\\//, 'https://')\n  if (url.startsWith('github:')) {\n    return `https://github.com/${url.slice(7)}`\n  } else if (url.startsWith('gitlab:')) {\n    return `https://gitlab.com/${url.slice(7)}`\n  } else if (url.startsWith('bitbucket:')) {\n    return `https://bitbucket.org/${url.slice(10)}`\n  } else if (!url.includes(':') && url.split('/').length === 2) {\n    return `https://github.com/${url}`\n  } else {\n    return url.includes('://') ? url : `https://${url}`\n  }\n}\n"
  },
  {
    "path": "packages/vite/scripts/benchCircularImport.ts",
    "content": "/**\n * Benchmark for the ModuleRunner\n *\n * Creates synthetic module graphs at various scales and measures the\n * total time to evaluate all modules.\n *\n * Usage:\n *   node packages/vite/scripts/benchCircularImport.ts\n *\n * With CPU profiling:\n *   node --cpu-prof --cpu-prof-dir=./profiles packages/vite/scripts/benchCircularImport.ts\n */\n\nimport { createServer, createServerModuleRunner } from 'vite'\n\n// ---------------------------------------------------------------------------\n// Graph generation\n// ---------------------------------------------------------------------------\n\ninterface GraphConfig {\n  /** Number of modules */\n  moduleCount: number\n  /** Average imports per module */\n  avgImports: number\n  /** Fraction of modules involved in cycles (0..1) */\n  cycleFraction: number\n}\n\ninterface SyntheticGraph {\n  /** Map of module id -> list of dependency ids */\n  edges: Map<string, string[]>\n  /** The entry module id */\n  entry: string\n}\n\nfunction moduleId(i: number): string {\n  return `/bench/mod_${i}.js`\n}\n\n/**\n * Generate a synthetic module graph with configurable size, density, and cycles.\n *\n * Strategy:\n * 1. Create a chain: mod_0 -> mod_1 -> ... -> mod_{n-1} (ensures all reachable)\n * 2. Add random cross-edges to reach target avg imports\n * 3. Add back-edges to create cycles for cycleFraction of modules\n */\nfunction generateGraph(config: GraphConfig): SyntheticGraph {\n  const { moduleCount, avgImports, cycleFraction } = config\n  const edges = new Map<string, string[]>()\n\n  // Initialize all modules\n  for (let i = 0; i < moduleCount; i++) {\n    edges.set(moduleId(i), [])\n  }\n\n  // 1. Chain: each module imports the next (ensures all reachable from entry)\n  for (let i = 0; i < moduleCount - 1; i++) {\n    edges.get(moduleId(i))!.push(moduleId(i + 1))\n  }\n\n  // 2. Random edges to reach target density (may include back-edges)\n  const targetTotalEdges = moduleCount * avgImports\n  const currentEdges = moduleCount - 1\n  const extraEdges = Math.max(0, targetTotalEdges - currentEdges)\n\n  // Use seeded PRNG for reproducibility\n  let seed = 42\n  const rand = () => {\n    seed = (seed * 1664525 + 1013904223) & 0x7fffffff\n    return seed / 0x7fffffff\n  }\n\n  for (let e = 0; e < extraEdges; e++) {\n    const from = Math.floor(rand() * moduleCount)\n    const to = Math.floor(rand() * moduleCount)\n    if (from !== to) {\n      const deps = edges.get(moduleId(from))!\n      const target = moduleId(to)\n      if (!deps.includes(target)) {\n        deps.push(target)\n      }\n    }\n  }\n\n  // 3. Add cycles: back-edges from later modules to earlier ones\n  const cycleModules = Math.floor(moduleCount * cycleFraction)\n  for (let c = 0; c < cycleModules; c++) {\n    // Pick a module in the later half, add back-edge to earlier half\n    const from = Math.floor(moduleCount * 0.5 + rand() * moduleCount * 0.5)\n    const to = Math.floor(rand() * moduleCount * 0.5)\n    if (from < moduleCount && to < moduleCount && from !== to) {\n      const deps = edges.get(moduleId(from))!\n      const target = moduleId(to)\n      if (!deps.includes(target)) {\n        deps.push(target)\n      }\n    }\n  }\n\n  return { edges, entry: moduleId(0) }\n}\n\n// ---------------------------------------------------------------------------\n// Benchmark plugin (resolveId + load)\n// ---------------------------------------------------------------------------\n\nconst BENCH_PREFIX = '/bench/'\n\nfunction createBenchPlugin(graph: SyntheticGraph) {\n  return {\n    name: 'bench-circular-import',\n\n    resolveId(id: string) {\n      if (id.startsWith(BENCH_PREFIX)) {\n        // Return a virtual module id (null-byte prefix prevents fs lookup)\n        return `\\0${id}`\n      }\n    },\n\n    load(id: string) {\n      if (id.startsWith(`\\0${BENCH_PREFIX}`)) {\n        const realId = id.slice(1)\n        const deps = graph.edges.get(realId)\n        if (deps) {\n          const lines = deps.map(\n            (dep, i) => `import { value as __dep_${i}__ } from \"${dep}\";`,\n          )\n          lines.push(`export const value = ${deps.length};`)\n          return lines.join('\\n')\n        }\n      }\n    },\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Benchmark runner\n// ---------------------------------------------------------------------------\n\ninterface BenchResult {\n  moduleCount: number\n  edgeCount: number\n  timeMs: number\n}\n\nasync function runBenchmark(config: GraphConfig): Promise<BenchResult> {\n  const graph = generateGraph(config)\n\n  let edgeCount = 0\n  for (const deps of graph.edges.values()) {\n    edgeCount += deps.length\n  }\n\n  const server = await createServer({\n    configFile: false,\n    // eslint-disable-next-line n/no-unsupported-features/node-builtins\n    root: import.meta.dirname,\n    logLevel: 'error',\n    server: {\n      middlewareMode: true,\n      ws: false,\n    },\n    optimizeDeps: {\n      noDiscovery: true,\n      include: [],\n    },\n    plugins: [createBenchPlugin(graph)],\n  })\n\n  const runner = createServerModuleRunner(server.environments.ssr, {\n    hmr: false,\n    sourcemapInterceptor: false,\n  })\n\n  const start = performance.now()\n  await runner.import(graph.entry)\n  const timeMs = performance.now() - start\n\n  await runner.close()\n  await server.close()\n\n  return {\n    moduleCount: config.moduleCount,\n    edgeCount,\n    timeMs,\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Main\n// ---------------------------------------------------------------------------\n\nasync function main() {\n  console.log('=== Vite isCircularImport Benchmark ===\\n')\n\n  const scales = [100, 500, 1000, 2000, 5000]\n  const results: BenchResult[] = []\n\n  // Warmup: single small run to trigger JIT compilation\n  await runBenchmark({ moduleCount: 100, avgImports: 3, cycleFraction: 0.05 })\n\n  for (const n of scales) {\n    const result = await runBenchmark({\n      moduleCount: n,\n      avgImports: 3,\n      cycleFraction: 0.05,\n    })\n    results.push(result)\n\n    console.log(`N=${n}:`)\n    console.log(`  modules: ${result.moduleCount}, edges: ${result.edgeCount}`)\n    console.log(`  time: ${result.timeMs.toFixed(1)}ms`)\n    console.log()\n  }\n}\n\nmain().catch(console.error)\n"
  },
  {
    "path": "packages/vite/scripts/generateTarget.ts",
    "content": "import { getCompatibleVersions } from 'baseline-browser-mapping'\n\n// Update on each major release\nconst targetDate = '2026-01-01'\n\n// https://esbuild.github.io/api/#target\nconst baselineToEsbuildTargetMap: Record<string, string> = {\n  chrome: 'chrome',\n  edge: 'edge',\n  firefox: 'firefox',\n  safari: 'safari',\n  safari_ios: 'ios',\n}\n\nconst esbuildSupportedBrowsers = new Set([\n  'chrome',\n  'edge',\n  'firefox',\n  'safari',\n  'ios',\n])\n\nconst results = getCompatibleVersions({\n  widelyAvailableOnDate: targetDate,\n})\n\nconst esbuildTargets = results\n  .map((target) => {\n    return {\n      browser: baselineToEsbuildTargetMap[target.browser],\n      version: target.version,\n    }\n  })\n  .filter((target) => esbuildSupportedBrowsers.has(target.browser))\n  .map((target) => `${target.browser}${target.version}`)\n\nconsole.log('ESBuild Targets:', esbuildTargets)\n"
  },
  {
    "path": "packages/vite/src/client/client.ts",
    "content": "import type {\n  DevRuntime as DevRuntimeType,\n  Messenger,\n} from 'rolldown/experimental/runtime-types'\nimport type { ErrorPayload, HotPayload } from '#types/hmrPayload'\nimport type { ViteHotContext } from '#types/hot'\nimport { HMRClient, HMRContext } from '../shared/hmr'\nimport {\n  createWebSocketModuleRunnerTransport,\n  normalizeModuleRunnerTransport,\n} from '../shared/moduleRunnerTransport'\nimport { createHMRHandler } from '../shared/hmrHandler'\nimport { setupForwardConsoleHandler } from '../shared/forwardConsole'\nimport { ErrorOverlay, cspNonce, overlayId } from './overlay'\nimport '@vite/env'\n\n// injected by the hmr plugin when served\ndeclare const __BASE__: string\ndeclare const __SERVER_HOST__: string\ndeclare const __HMR_PROTOCOL__: string | null\ndeclare const __HMR_HOSTNAME__: string | null\ndeclare const __HMR_PORT__: number | null\ndeclare const __HMR_DIRECT_TARGET__: string\ndeclare const __HMR_BASE__: string\ndeclare const __HMR_TIMEOUT__: number\ndeclare const __HMR_ENABLE_OVERLAY__: boolean\ndeclare const __WS_TOKEN__: string\ndeclare const __SERVER_FORWARD_CONSOLE__: any\ndeclare const __BUNDLED_DEV__: boolean\n\nconsole.debug('[vite] connecting...')\n\nconst importMetaUrl = new URL(import.meta.url)\n\n// use server configuration, then fallback to inference\nconst serverHost = __SERVER_HOST__\nconst socketProtocol =\n  __HMR_PROTOCOL__ || (importMetaUrl.protocol === 'https:' ? 'wss' : 'ws')\nconst hmrPort = __HMR_PORT__\nconst socketHost = `${__HMR_HOSTNAME__ || importMetaUrl.hostname}:${\n  hmrPort || importMetaUrl.port\n}${__HMR_BASE__}`\nconst directSocketHost = __HMR_DIRECT_TARGET__\nconst base = __BASE__ || '/'\nconst hmrTimeout = __HMR_TIMEOUT__\nconst wsToken = __WS_TOKEN__\nconst isBundleMode = __BUNDLED_DEV__\nconst forwardConsole = __SERVER_FORWARD_CONSOLE__\n\nconst transport = normalizeModuleRunnerTransport(\n  (() => {\n    let wsTransport = createWebSocketModuleRunnerTransport({\n      createConnection: () =>\n        new WebSocket(\n          `${socketProtocol}://${socketHost}?token=${wsToken}`,\n          'vite-hmr',\n        ),\n      pingInterval: hmrTimeout,\n    })\n\n    return {\n      async connect(handlers) {\n        try {\n          await wsTransport.connect(handlers)\n        } catch (e) {\n          // only use fallback when port is inferred and was not connected before to prevent confusion\n          if (!hmrPort) {\n            wsTransport = createWebSocketModuleRunnerTransport({\n              createConnection: () =>\n                new WebSocket(\n                  `${socketProtocol}://${directSocketHost}?token=${wsToken}`,\n                  'vite-hmr',\n                ),\n              pingInterval: hmrTimeout,\n            })\n            try {\n              await wsTransport.connect(handlers)\n              console.info(\n                '[vite] Direct websocket connection fallback. Check out https://vite.dev/config/server-options.html#server-hmr to remove the previous connection error.',\n              )\n            } catch (e) {\n              if (\n                e instanceof Error &&\n                e.message.includes('WebSocket closed without opened.')\n              ) {\n                const currentScriptHostURL = new URL(import.meta.url)\n                const currentScriptHost =\n                  currentScriptHostURL.host +\n                  currentScriptHostURL.pathname.replace(/@vite\\/client$/, '')\n                console.error(\n                  '[vite] failed to connect to websocket.\\n' +\n                    'your current setup:\\n' +\n                    `  (browser) ${currentScriptHost} <--[HTTP]--> ${serverHost} (server)\\n` +\n                    `  (browser) ${socketHost} <--[WebSocket (failing)]--> ${directSocketHost} (server)\\n` +\n                    'Check out your Vite / network configuration and https://vite.dev/config/server-options.html#server-hmr .',\n                )\n              }\n            }\n            return\n          }\n          console.error(`[vite] failed to connect to websocket (${e}). `)\n          throw e\n        }\n      },\n      async disconnect() {\n        await wsTransport.disconnect()\n      },\n      send(data) {\n        wsTransport.send(data)\n      },\n    }\n  })(),\n)\n\nlet willUnload = false\nif (typeof window !== 'undefined') {\n  // window can be misleadingly defined in a worker if using define (see #19307)\n  window.addEventListener?.('beforeunload', () => {\n    willUnload = true\n  })\n}\n\nfunction cleanUrl(pathname: string): string {\n  const url = new URL(pathname, 'http://vite.dev')\n  url.searchParams.delete('direct')\n  return url.pathname + url.search\n}\n\nlet isFirstUpdate = true\nconst outdatedLinkTags = new WeakSet<HTMLLinkElement>()\n\nconst debounceReload = (time: number) => {\n  let timer: ReturnType<typeof setTimeout> | null\n  return () => {\n    if (timer) {\n      clearTimeout(timer)\n      timer = null\n    }\n    timer = setTimeout(() => {\n      location.reload()\n    }, time)\n  }\n}\nconst pageReload = debounceReload(20)\n\nconst hmrClient = new HMRClient(\n  {\n    error: (err) => console.error('[vite]', err),\n    debug: (...msg) => console.debug('[vite]', ...msg),\n  },\n  transport,\n  isBundleMode\n    ? async function importUpdatedModule({\n        url,\n        acceptedPath,\n        isWithinCircularImport,\n      }) {\n        const importPromise = import(base + url!).then(() =>\n          // @ts-expect-error globalThis.__rolldown_runtime__\n          globalThis.__rolldown_runtime__.loadExports(acceptedPath),\n        )\n        if (isWithinCircularImport) {\n          importPromise.catch(() => {\n            console.info(\n              `[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. ` +\n                `To debug and break the circular import, you can run \\`vite --debug hmr\\` to log the circular dependency path if a file change triggered it.`,\n            )\n            pageReload()\n          })\n        }\n        return await importPromise\n      }\n    : async function importUpdatedModule({\n        acceptedPath,\n        timestamp,\n        explicitImportRequired,\n        isWithinCircularImport,\n      }) {\n        const [acceptedPathWithoutQuery, query] = acceptedPath.split(`?`)\n        const importPromise = import(\n          /* @vite-ignore */\n          base +\n            acceptedPathWithoutQuery.slice(1) +\n            `?${explicitImportRequired ? 'import&' : ''}t=${timestamp}${\n              query ? `&${query}` : ''\n            }`\n        )\n        if (isWithinCircularImport) {\n          importPromise.catch(() => {\n            console.info(\n              `[hmr] ${acceptedPath} failed to apply HMR as it's within a circular import. Reloading page to reset the execution order. ` +\n                `To debug and break the circular import, you can run \\`vite --debug hmr\\` to log the circular dependency path if a file change triggered it.`,\n            )\n            pageReload()\n          })\n        }\n        return await importPromise\n      },\n)\ntransport.connect!(createHMRHandler(handleMessage))\n\nsetupForwardConsoleHandler(transport, forwardConsole)\n\nasync function handleMessage(payload: HotPayload) {\n  switch (payload.type) {\n    case 'connected':\n      console.debug(`[vite] connected.`)\n      break\n    case 'update':\n      await hmrClient.notifyListeners('vite:beforeUpdate', payload)\n      if (hasDocument) {\n        // if this is the first update and there's already an error overlay, it\n        // means the page opened with existing server compile error and the whole\n        // module script failed to load (since one of the nested imports is 500).\n        // in this case a normal update won't work and a full reload is needed.\n        if (isFirstUpdate && hasErrorOverlay()) {\n          location.reload()\n          return\n        } else {\n          if (enableOverlay) {\n            clearErrorOverlay()\n          }\n          isFirstUpdate = false\n        }\n      }\n      await Promise.all(\n        payload.updates.map(async (update): Promise<void> => {\n          if (update.type === 'js-update') {\n            return hmrClient.queueUpdate(update)\n          }\n\n          // css-update\n          // this is only sent when a css file referenced with <link> is updated\n          const { path, timestamp } = update\n          const searchUrl = cleanUrl(path)\n          // can't use querySelector with `[href*=]` here since the link may be\n          // using relative paths so we need to use link.href to grab the full\n          // URL for the include check.\n          const el = Array.from(\n            document.querySelectorAll<HTMLLinkElement>('link'),\n          ).find(\n            (e) =>\n              !outdatedLinkTags.has(e) && cleanUrl(e.href).includes(searchUrl),\n          )\n\n          if (!el) {\n            return\n          }\n\n          const newPath = `${base}${searchUrl.slice(1)}${\n            searchUrl.includes('?') ? '&' : '?'\n          }t=${timestamp}`\n\n          // rather than swapping the href on the existing tag, we will\n          // create a new link tag. Once the new stylesheet has loaded we\n          // will remove the existing link tag. This removes a Flash Of\n          // Unstyled Content that can occur when swapping out the tag href\n          // directly, as the new stylesheet has not yet been loaded.\n          return new Promise((resolve) => {\n            const newLinkTag = el.cloneNode() as HTMLLinkElement\n            newLinkTag.href = new URL(newPath, el.href).href\n            const removeOldEl = () => {\n              el.remove()\n              console.debug(`[vite] css hot updated: ${searchUrl}`)\n              resolve()\n            }\n            newLinkTag.addEventListener('load', removeOldEl)\n            newLinkTag.addEventListener('error', removeOldEl)\n            outdatedLinkTags.add(el)\n            el.after(newLinkTag)\n          })\n        }),\n      )\n      await hmrClient.notifyListeners('vite:afterUpdate', payload)\n      break\n    case 'custom': {\n      await hmrClient.notifyListeners(payload.event, payload.data)\n      if (payload.event === 'vite:ws:disconnect') {\n        if (hasDocument && !willUnload) {\n          console.log(`[vite] server connection lost. Polling for restart...`)\n          const socket = payload.data.webSocket as WebSocket\n          const url = new URL(socket.url)\n          url.search = '' // remove query string including `token`\n          await waitForSuccessfulPing(url.href)\n          location.reload()\n        }\n      }\n      break\n    }\n    case 'full-reload':\n      await hmrClient.notifyListeners('vite:beforeFullReload', payload)\n      if (hasDocument) {\n        if (payload.path && payload.path.endsWith('.html')) {\n          // if html file is edited, only reload the page if the browser is\n          // currently on that page.\n          const pagePath = decodeURI(location.pathname)\n          const payloadPath = base + payload.path.slice(1)\n          if (\n            pagePath === payloadPath ||\n            payload.path === '/index.html' ||\n            (pagePath.endsWith('/') && pagePath + 'index.html' === payloadPath)\n          ) {\n            pageReload()\n          }\n          return\n        } else {\n          pageReload()\n        }\n      }\n      break\n    case 'prune':\n      await hmrClient.notifyListeners('vite:beforePrune', payload)\n      await hmrClient.prunePaths(payload.paths)\n      break\n    case 'error': {\n      await hmrClient.notifyListeners('vite:error', payload)\n      if (hasDocument) {\n        const err = payload.err\n        if (enableOverlay) {\n          createErrorOverlay(err)\n        } else {\n          console.error(\n            `[vite] Internal Server Error\\n${err.message}\\n${err.stack}`,\n          )\n        }\n      }\n      break\n    }\n    case 'ping': // noop\n      break\n    default: {\n      const check: never = payload\n      return check\n    }\n  }\n}\n\nconst enableOverlay = __HMR_ENABLE_OVERLAY__\nconst hasDocument = 'document' in globalThis\n\nfunction createErrorOverlay(err: ErrorPayload['err']) {\n  clearErrorOverlay()\n  const { customElements } = globalThis\n  if (customElements) {\n    const ErrorOverlayConstructor = customElements.get(overlayId)!\n    document.body.appendChild(new ErrorOverlayConstructor(err))\n  }\n}\n\nfunction clearErrorOverlay() {\n  document.querySelectorAll<ErrorOverlay>(overlayId).forEach((n) => n.close())\n}\n\nfunction hasErrorOverlay() {\n  return document.querySelectorAll(overlayId).length\n}\n\nfunction waitForSuccessfulPing(socketUrl: string) {\n  if (typeof SharedWorker === 'undefined') {\n    const visibilityManager: VisibilityManager = {\n      currentState: document.visibilityState,\n      listeners: new Set(),\n    }\n    const onVisibilityChange = () => {\n      visibilityManager.currentState = document.visibilityState\n      for (const listener of visibilityManager.listeners) {\n        listener(visibilityManager.currentState)\n      }\n    }\n    document.addEventListener('visibilitychange', onVisibilityChange)\n    return waitForSuccessfulPingInternal(socketUrl, visibilityManager)\n  }\n\n  // needs to be inlined to\n  //   - load the worker after the server is closed\n  //   - make it work with backend integrations\n  const blob = new Blob(\n    [\n      '\"use strict\";',\n      `const waitForSuccessfulPingInternal = ${waitForSuccessfulPingInternal.toString()};`,\n      `const fn = ${pingWorkerContentMain.toString()};`,\n      `fn(${JSON.stringify(socketUrl)})`,\n    ],\n    { type: 'application/javascript' },\n  )\n  const objURL = URL.createObjectURL(blob)\n  const sharedWorker = new SharedWorker(objURL)\n  return new Promise<void>((resolve, reject) => {\n    const onVisibilityChange = () => {\n      sharedWorker.port.postMessage({ visibility: document.visibilityState })\n    }\n    document.addEventListener('visibilitychange', onVisibilityChange)\n\n    sharedWorker.port.addEventListener('message', (event) => {\n      document.removeEventListener('visibilitychange', onVisibilityChange)\n      sharedWorker.port.close()\n\n      const data: { type: 'success' } | { type: 'error'; error: unknown } =\n        event.data\n      if (data.type === 'error') {\n        reject(data.error)\n        return\n      }\n      resolve()\n    })\n\n    onVisibilityChange()\n    sharedWorker.port.start()\n  })\n}\n\ntype VisibilityManager = {\n  currentState: DocumentVisibilityState\n  listeners: Set<(newVisibility: DocumentVisibilityState) => void>\n}\n\nfunction pingWorkerContentMain(socketUrl: string) {\n  self.addEventListener('connect', (_event) => {\n    const event = _event as MessageEvent\n    const port = event.ports[0]\n\n    if (!socketUrl) {\n      port.postMessage({\n        type: 'error',\n        error: new Error('socketUrl not found'),\n      })\n      return\n    }\n\n    const visibilityManager: VisibilityManager = {\n      currentState: 'visible',\n      listeners: new Set(),\n    }\n    port.addEventListener('message', (event) => {\n      const { visibility } = event.data\n      visibilityManager.currentState = visibility\n      console.debug('[vite] new window visibility', visibility)\n      for (const listener of visibilityManager.listeners) {\n        listener(visibility)\n      }\n    })\n    port.start()\n\n    console.debug('[vite] connected from window')\n    waitForSuccessfulPingInternal(socketUrl, visibilityManager).then(\n      () => {\n        console.debug('[vite] ping successful')\n        try {\n          port.postMessage({ type: 'success' })\n        } catch (error) {\n          port.postMessage({ type: 'error', error })\n        }\n      },\n      (error) => {\n        console.debug('[vite] error happened', error)\n        try {\n          port.postMessage({ type: 'error', error })\n        } catch (error) {\n          port.postMessage({ type: 'error', error })\n        }\n      },\n    )\n  })\n}\n\nasync function waitForSuccessfulPingInternal(\n  socketUrl: string,\n  visibilityManager: VisibilityManager,\n  ms = 1000,\n) {\n  function wait(ms: number) {\n    return new Promise((resolve) => setTimeout(resolve, ms))\n  }\n\n  async function ping() {\n    try {\n      const socket = new WebSocket(socketUrl, 'vite-ping')\n      return new Promise<boolean>((resolve) => {\n        function onOpen() {\n          resolve(true)\n          close()\n        }\n        function onError() {\n          resolve(false)\n          close()\n        }\n        function close() {\n          socket.removeEventListener('open', onOpen)\n          socket.removeEventListener('error', onError)\n          socket.close()\n        }\n        socket.addEventListener('open', onOpen)\n        socket.addEventListener('error', onError)\n      })\n    } catch {\n      return false\n    }\n  }\n\n  function waitForWindowShow(visibilityManager: VisibilityManager) {\n    return new Promise<void>((resolve) => {\n      const onChange = (newVisibility: DocumentVisibilityState) => {\n        if (newVisibility === 'visible') {\n          resolve()\n          visibilityManager.listeners.delete(onChange)\n        }\n      }\n      visibilityManager.listeners.add(onChange)\n    })\n  }\n\n  if (await ping()) {\n    return\n  }\n  await wait(ms)\n\n  while (true) {\n    if (visibilityManager.currentState === 'visible') {\n      if (await ping()) {\n        break\n      }\n      await wait(ms)\n    } else {\n      await waitForWindowShow(visibilityManager)\n    }\n  }\n}\n\nconst sheetsMap = new Map<string, HTMLStyleElement>()\nconst linkSheetsMap = new Map<string, HTMLLinkElement>()\n\n// collect existing style elements that may have been inserted during SSR\n// to avoid FOUC or duplicate styles\nif ('document' in globalThis) {\n  document\n    .querySelectorAll<HTMLStyleElement>('style[data-vite-dev-id]')\n    .forEach((el) => {\n      sheetsMap.set(el.getAttribute('data-vite-dev-id')!, el)\n    })\n  document\n    .querySelectorAll<HTMLLinkElement>(\n      'link[rel=\"stylesheet\"][data-vite-dev-id]',\n    )\n    .forEach((el) => {\n      linkSheetsMap.set(el.getAttribute('data-vite-dev-id')!, el)\n    })\n}\n\n// all css imports should be inserted at the same position\n// because after build it will be a single css file\nlet lastInsertedStyle: HTMLStyleElement | undefined\n\nexport function updateStyle(id: string, content: string): void {\n  if (linkSheetsMap.has(id)) return\n\n  let style = sheetsMap.get(id)\n  if (!style) {\n    style = document.createElement('style')\n    style.setAttribute('type', 'text/css')\n    style.setAttribute('data-vite-dev-id', id)\n    style.textContent = content\n    if (cspNonce) {\n      style.setAttribute('nonce', cspNonce)\n    }\n\n    if (!lastInsertedStyle) {\n      document.head.appendChild(style)\n\n      // reset lastInsertedStyle after async\n      // because dynamically imported css will be split into a different file\n      setTimeout(() => {\n        lastInsertedStyle = undefined\n      }, 0)\n    } else {\n      lastInsertedStyle.insertAdjacentElement('afterend', style)\n    }\n    lastInsertedStyle = style\n  } else {\n    style.textContent = content\n  }\n  sheetsMap.set(id, style)\n}\n\nexport function removeStyle(id: string): void {\n  if (linkSheetsMap.has(id)) {\n    // re-select elements since HMR can replace links\n    document\n      .querySelectorAll<HTMLLinkElement>(\n        `link[rel=\"stylesheet\"][data-vite-dev-id]`,\n      )\n      .forEach((el) => {\n        if (el.getAttribute('data-vite-dev-id') === id) {\n          el.remove()\n        }\n      })\n    linkSheetsMap.delete(id)\n  }\n  const style = sheetsMap.get(id)\n  if (style) {\n    document.head.removeChild(style)\n    sheetsMap.delete(id)\n  }\n}\n\nexport function createHotContext(ownerPath: string): ViteHotContext {\n  return new HMRContext(hmrClient, ownerPath)\n}\n\n/**\n * urls here are dynamic import() urls that couldn't be statically analyzed\n */\nexport function injectQuery(url: string, queryToInject: string): string {\n  // skip urls that won't be handled by vite\n  if (url[0] !== '.' && url[0] !== '/') {\n    return url\n  }\n\n  // can't use pathname from URL since it may be relative like ../\n  const pathname = url.replace(/[?#].*$/, '')\n  const { search, hash } = new URL(url, 'http://vite.dev')\n\n  return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${\n    hash || ''\n  }`\n}\n\nexport { ErrorOverlay }\n\ndeclare const DevRuntime: typeof DevRuntimeType\n\nif (isBundleMode && typeof DevRuntime !== 'undefined') {\n  class ViteDevRuntime extends DevRuntime {\n    override createModuleHotContext(moduleId: string) {\n      const ctx = createHotContext(moduleId)\n      // @ts-expect-error TODO: support CSS properly\n      ctx._internal = { updateStyle, removeStyle }\n      return ctx\n    }\n\n    override applyUpdates(_boundaries: [string, string][]): void {\n      // noop, handled in the HMR client\n    }\n  }\n\n  const wrappedSocket: Messenger = {\n    send(message) {\n      switch (message.type) {\n        case 'hmr:module-registered': {\n          transport.send({\n            type: 'custom',\n            event: 'vite:module-loaded',\n            // clone array as the runtime reuses the array instance\n            data: { modules: message.modules.slice() },\n          })\n          break\n        }\n        default:\n          throw new Error(`Unknown message type: ${JSON.stringify(message)}`)\n      }\n    },\n  }\n  ;(globalThis as any).__rolldown_runtime__ ??= new ViteDevRuntime(\n    wrappedSocket,\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/client/env.ts",
    "content": "declare const __DEFINES__: Record<string, any>\n\nconst context = (() => {\n  if (typeof globalThis !== 'undefined') {\n    return globalThis\n  } else if (typeof self !== 'undefined') {\n    return self\n  } else if (typeof window !== 'undefined') {\n    return window\n  } else {\n    return Function('return this')()\n  }\n})()\n\n// assign defines\nconst defines = __DEFINES__\nObject.keys(defines).forEach((key) => {\n  const segments = key.split('.')\n  let target = context\n  for (let i = 0; i < segments.length; i++) {\n    const segment = segments[i]\n    if (i === segments.length - 1) {\n      target[segment] = defines[key]\n    } else {\n      target = target[segment] || (target[segment] = {})\n    }\n  }\n})\n"
  },
  {
    "path": "packages/vite/src/client/overlay.ts",
    "content": "import type { ErrorPayload } from '#types/hmrPayload'\n\n// injected by the hmr plugin when served\ndeclare const __BASE__: string\ndeclare const __HMR_CONFIG_NAME__: string\n\nconst hmrConfigName = __HMR_CONFIG_NAME__\nconst base = __BASE__ || '/'\n\nexport const cspNonce =\n  'document' in globalThis\n    ? document.querySelector<HTMLMetaElement>('meta[property=csp-nonce]')?.nonce\n    : undefined\n\n// Create an element with provided attributes and optional children\nfunction h(\n  e: string,\n  attrs: Record<string, string | undefined> = {},\n  ...children: (string | Node)[]\n) {\n  const elem = document.createElement(e)\n  for (const [k, v] of Object.entries(attrs)) {\n    if (v !== undefined) {\n      elem.setAttribute(k, v)\n    }\n  }\n  elem.append(...children)\n  return elem\n}\n\n// set :host styles to make playwright detect the element as visible\nconst templateStyle = /*css*/ `\n:host {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 99999;\n  --monospace: 'SFMono-Regular', Consolas,\n  'Liberation Mono', Menlo, Courier, monospace;\n  --red: #ff5555;\n  --yellow: #e2aa53;\n  --purple: #cfa4ff;\n  --cyan: #2dd9da;\n  --dim: #c9c9c9;\n\n  --window-background: #181818;\n  --window-color: #d8d8d8;\n}\n\n.backdrop {\n  position: fixed;\n  z-index: 99999;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  overflow-y: scroll;\n  margin: 0;\n  background: rgba(0, 0, 0, 0.66);\n}\n\n.window {\n  font-family: var(--monospace);\n  line-height: 1.5;\n  max-width: 80vw;\n  color: var(--window-color);\n  box-sizing: border-box;\n  margin: 30px auto;\n  padding: 2.5vh 4vw;\n  position: relative;\n  background: var(--window-background);\n  border-radius: 6px 6px 8px 8px;\n  box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);\n  overflow: hidden;\n  border-top: 8px solid var(--red);\n  direction: ltr;\n  text-align: left;\n}\n\npre {\n  font-family: var(--monospace);\n  font-size: 16px;\n  margin-top: 0;\n  margin-bottom: 1em;\n  overflow-x: scroll;\n  scrollbar-width: none;\n}\n\npre::-webkit-scrollbar {\n  display: none;\n}\n\npre.frame::-webkit-scrollbar {\n  display: block;\n  height: 5px;\n}\n\npre.frame::-webkit-scrollbar-thumb {\n  background: #999;\n  border-radius: 5px;\n}\n\npre.frame {\n  scrollbar-width: thin;\n}\n\n.message {\n  line-height: 1.3;\n  font-weight: 600;\n  white-space: pre-wrap;\n}\n\n.message-body {\n  color: var(--red);\n}\n\n.plugin {\n  color: var(--purple);\n}\n\n.file {\n  color: var(--cyan);\n  margin-bottom: 0;\n  white-space: pre-wrap;\n  word-break: break-all;\n}\n\n.frame {\n  color: var(--yellow);\n}\n\n.stack {\n  font-size: 13px;\n  color: var(--dim);\n}\n\n.tip {\n  font-size: 13px;\n  color: #999;\n  border-top: 1px dotted #999;\n  padding-top: 13px;\n  line-height: 1.8;\n}\n\ncode {\n  font-size: 13px;\n  font-family: var(--monospace);\n  color: var(--yellow);\n}\n\n.file-link {\n  text-decoration: underline;\n  cursor: pointer;\n}\n\nkbd {\n  line-height: 1.5;\n  font-family: ui-monospace, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n  font-size: 0.75rem;\n  font-weight: 700;\n  background-color: rgb(38, 40, 44);\n  color: rgb(166, 167, 171);\n  padding: 0.15rem 0.3rem;\n  border-radius: 0.25rem;\n  border-width: 0.0625rem 0.0625rem 0.1875rem;\n  border-style: solid;\n  border-color: rgb(54, 57, 64);\n  border-image: initial;\n}\n`\n\n// Error Template\nconst createTemplate = () =>\n  h(\n    'div',\n    { class: 'backdrop', part: 'backdrop' },\n    h(\n      'div',\n      { class: 'window', part: 'window' },\n      h(\n        'pre',\n        { class: 'message', part: 'message' },\n        h('span', { class: 'plugin', part: 'plugin' }),\n        h('span', { class: 'message-body', part: 'message-body' }),\n      ),\n      h('pre', { class: 'file', part: 'file' }),\n      h('pre', { class: 'frame', part: 'frame' }),\n      h('pre', { class: 'stack', part: 'stack' }),\n      h(\n        'div',\n        { class: 'tip', part: 'tip' },\n        'Click outside, press ',\n        h('kbd', {}, 'Esc'),\n        ' key, or fix the code to dismiss.',\n        h('br'),\n        'You can also disable this overlay by setting ',\n        h('code', { part: 'config-option-name' }, 'server.hmr.overlay'),\n        ' to ',\n        h('code', { part: 'config-option-value' }, 'false'),\n        ' in ',\n        h('code', { part: 'config-file-name' }, hmrConfigName),\n        '.',\n      ),\n    ),\n    h('style', { nonce: cspNonce }, templateStyle),\n  )\n\nconst fileRE = /(?:file:\\/\\/)?(?:[a-zA-Z]:\\\\|\\/).*?:\\d+:\\d+/g\nconst codeframeRE = /^(?:>?\\s*\\d+\\s+\\|.*|\\s+\\|\\s*\\^.*)\\r?\\n/gm\n\n// Allow `ErrorOverlay` to extend `HTMLElement` even in environments where\n// `HTMLElement` was not originally defined.\nconst { HTMLElement = class {} as typeof globalThis.HTMLElement } = globalThis\nexport class ErrorOverlay extends HTMLElement {\n  root: ShadowRoot\n  closeOnEsc: (e: KeyboardEvent) => void\n\n  constructor(err: ErrorPayload['err'], links = true) {\n    super()\n    this.root = this.attachShadow({ mode: 'open' })\n    this.root.appendChild(createTemplate())\n\n    codeframeRE.lastIndex = 0\n    const hasFrame = err.frame && codeframeRE.test(err.frame)\n    const message = hasFrame\n      ? err.message.replace(codeframeRE, '')\n      : err.message\n    if (err.plugin) {\n      this.text('.plugin', `[plugin:${err.plugin}] `)\n    }\n    this.text('.message-body', message.trim())\n\n    const [file] = (err.loc?.file || err.id || 'unknown file').split(`?`)\n    if (err.loc) {\n      this.text('.file', `${file}:${err.loc.line}:${err.loc.column}`, links)\n    } else if (err.id) {\n      this.text('.file', file)\n    }\n\n    if (hasFrame) {\n      this.text('.frame', err.frame!.trim())\n    }\n    this.text('.stack', err.stack, links)\n\n    this.root.querySelector('.window')!.addEventListener('click', (e) => {\n      e.stopPropagation()\n    })\n\n    this.addEventListener('click', () => {\n      this.close()\n    })\n\n    this.closeOnEsc = (e: KeyboardEvent) => {\n      if (e.key === 'Escape' || e.code === 'Escape') {\n        this.close()\n      }\n    }\n\n    document.addEventListener('keydown', this.closeOnEsc)\n  }\n\n  text(selector: string, text: string, linkFiles = false): void {\n    const el = this.root.querySelector(selector)!\n    if (!linkFiles) {\n      el.textContent = text\n    } else {\n      let curIndex = 0\n      let match: RegExpExecArray | null\n      fileRE.lastIndex = 0\n      while ((match = fileRE.exec(text))) {\n        const { 0: file, index } = match\n        const frag = text.slice(curIndex, index)\n        el.appendChild(document.createTextNode(frag))\n        const link = document.createElement('a')\n        link.textContent = file\n        link.className = 'file-link'\n        link.onclick = () => {\n          fetch(\n            new URL(\n              `${base}__open-in-editor?file=${encodeURIComponent(file)}`,\n              import.meta.url,\n            ),\n          )\n        }\n        el.appendChild(link)\n        curIndex += frag.length + file.length\n      }\n      if (curIndex < text.length) {\n        el.appendChild(document.createTextNode(text.slice(curIndex)))\n      }\n    }\n  }\n  close(): void {\n    this.parentNode?.removeChild(this)\n    document.removeEventListener('keydown', this.closeOnEsc)\n  }\n}\n\nexport const overlayId = 'vite-error-overlay'\nconst { customElements } = globalThis // Ensure `customElements` is defined before the next line.\nif (customElements && !customElements.get(overlayId)) {\n  customElements.define(overlayId, ErrorOverlay)\n}\n"
  },
  {
    "path": "packages/vite/src/client/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"include\": [\"./\", \"../types\"],\n  \"compilerOptions\": {\n    \"types\": [],\n    \"target\": \"ES2020\",\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"isolatedDeclarations\": false,\n    \"declaration\": false\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/__tests_dts__/importMeta.ts",
    "content": "/**\n * Type test to verify ModuleRunnerImportMeta is structurally compatible\n * with ImportMeta (including @types/node augmentations).\n *\n * This replaces `extends ImportMeta` in the interface declaration with a\n * test-only assignability check that won't cause TS2717 \"subsequent property\n * declarations must have the same type\" errors in consumer projects using\n * skipLibCheck: false with augmented ImportMeta.\n */\n\nimport type { ExpectExtends, ExpectTrue } from '@type-challenges/utils'\nimport type { ModuleRunnerImportMeta } from '../types'\n\nexport type cases = [\n  // Ensure ModuleRunnerImportMeta is assignable to ImportMeta\n  // (which includes @types/node augmentations: dirname, filename, url, resolve, main)\n  ExpectTrue<ExpectExtends<Omit<ImportMeta, 'main'>, ModuleRunnerImportMeta>>,\n]\n\nexport {}\n"
  },
  {
    "path": "packages/vite/src/module-runner/__tests_dts__/tsconfig.json",
    "content": "{\n  \"extends\": \"../../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"isolatedDeclarations\": false,\n    \"declaration\": false\n  },\n  \"include\": [\"../\", \"../../types\"],\n  \"exclude\": [\"../**/__tests__\"]\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/constants.ts",
    "content": "// they are exported from ssrTransform plugin, but we can't import from there for performance reasons\nexport const ssrModuleExportsKey = `__vite_ssr_exports__`\nexport const ssrImportKey = `__vite_ssr_import__`\nexport const ssrDynamicImportKey = `__vite_ssr_dynamic_import__`\nexport const ssrExportAllKey = `__vite_ssr_exportAll__`\nexport const ssrExportNameKey = `__vite_ssr_exportName__`\nexport const ssrImportMetaKey = `__vite_ssr_import_meta__`\n"
  },
  {
    "path": "packages/vite/src/module-runner/createImportMeta.ts",
    "content": "import { isWindows } from '../shared/utils'\nimport { createImportMetaResolver } from './importMetaResolver'\nimport type { ModuleRunnerImportMeta } from './types'\nimport { posixDirname, posixPathToFileHref, toWindowsPath } from './utils'\n\nconst envProxy = new Proxy({} as any, {\n  get(_, p) {\n    throw new Error(\n      `[module runner] Dynamic access of \"import.meta.env\" is not supported. Please, use \"import.meta.env.${String(p)}\" instead.`,\n    )\n  },\n})\n\nexport function createDefaultImportMeta(\n  modulePath: string,\n): ModuleRunnerImportMeta {\n  const href = posixPathToFileHref(modulePath)\n  const filename = modulePath\n  const dirname = posixDirname(modulePath)\n  return {\n    filename: isWindows ? toWindowsPath(filename) : filename,\n    dirname: isWindows ? toWindowsPath(dirname) : dirname,\n    url: href,\n    env: envProxy,\n    resolve(_id: string, _parent?: string) {\n      throw new Error('[module runner] \"import.meta.resolve\" is not supported.')\n    },\n    // should be replaced during transformation\n    glob() {\n      throw new Error(\n        `[module runner] \"import.meta.glob\" is statically replaced during ` +\n          `file transformation. Make sure to reference it by the full name.`,\n      )\n    },\n  }\n}\n\n/**\n * Create import.meta object for Node.js.\n */\nexport function createNodeImportMeta(\n  modulePath: string,\n): ModuleRunnerImportMeta {\n  const defaultMeta = createDefaultImportMeta(modulePath)\n  const href = defaultMeta.url\n\n  const importMetaResolver = createImportMetaResolver()\n\n  return {\n    ...defaultMeta,\n    main: false,\n    resolve(id: string, parent?: string) {\n      const resolver = importMetaResolver ?? defaultMeta.resolve\n      return resolver(id, parent ?? href)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/esmEvaluator.ts",
    "content": "import {\n  AsyncFunction,\n  getAsyncFunctionDeclarationPaddingLineCount,\n} from '../shared/utils'\nimport {\n  ssrDynamicImportKey,\n  ssrExportAllKey,\n  ssrExportNameKey,\n  ssrImportKey,\n  ssrImportMetaKey,\n  ssrModuleExportsKey,\n} from './constants'\nimport type { ModuleEvaluator, ModuleRunnerContext } from './types'\n\nexport class ESModulesEvaluator implements ModuleEvaluator {\n  public readonly startOffset: number =\n    getAsyncFunctionDeclarationPaddingLineCount()\n\n  async runInlinedModule(\n    context: ModuleRunnerContext,\n    code: string,\n  ): Promise<any> {\n    // use AsyncFunction instead of vm module to support broader array of environments out of the box\n    const initModule = new AsyncFunction(\n      ssrModuleExportsKey,\n      ssrImportMetaKey,\n      ssrImportKey,\n      ssrDynamicImportKey,\n      ssrExportAllKey,\n      ssrExportNameKey,\n      // source map should already be inlined by Vite\n      '\"use strict\";' + code,\n    )\n\n    await initModule(\n      context[ssrModuleExportsKey],\n      context[ssrImportMetaKey],\n      context[ssrImportKey],\n      context[ssrDynamicImportKey],\n      context[ssrExportAllKey],\n      context[ssrExportNameKey],\n    )\n\n    Object.seal(context[ssrModuleExportsKey])\n  }\n\n  runExternalModule(filepath: string): Promise<any> {\n    return import(filepath)\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/evaluatedModules.ts",
    "content": "import { cleanUrl, isWindows, slash, unwrapId } from '../shared/utils'\nimport { SOURCEMAPPING_URL } from '../shared/constants'\nimport { decodeBase64 } from './utils'\nimport { DecodedMap } from './sourcemap/decoder'\nimport type { ResolvedResult } from './types'\n\nconst MODULE_RUNNER_SOURCEMAPPING_REGEXP = new RegExp(\n  `//# ${SOURCEMAPPING_URL}=data:application/json;base64,(.+)`,\n)\n\nexport class EvaluatedModuleNode {\n  public importers: Set<string> = new Set()\n  public imports: Set<string> = new Set()\n  public evaluated = false\n  public meta: ResolvedResult | undefined\n  public promise: Promise<any> | undefined\n  public exports: any | undefined\n  public file: string\n  public map: DecodedMap | undefined\n\n  constructor(\n    public id: string,\n    public url: string,\n  ) {\n    this.file = cleanUrl(id)\n  }\n}\n\nexport class EvaluatedModules {\n  public readonly idToModuleMap: Map<string, EvaluatedModuleNode> = new Map()\n  public readonly fileToModulesMap: Map<string, Set<EvaluatedModuleNode>> =\n    new Map()\n  public readonly urlToIdModuleMap: Map<string, EvaluatedModuleNode> = new Map()\n\n  /**\n   * Returns the module node by the resolved module ID. Usually, module ID is\n   * the file system path with query and/or hash. It can also be a virtual module.\n   *\n   * Module runner graph will have 1 to 1 mapping with the server module graph.\n   * @param id Resolved module ID\n   */\n  public getModuleById(id: string): EvaluatedModuleNode | undefined {\n    return this.idToModuleMap.get(id)\n  }\n\n  /**\n   * Returns all modules related to the file system path. Different modules\n   * might have different query parameters or hash, so it's possible to have\n   * multiple modules for the same file.\n   * @param file The file system path of the module\n   */\n  public getModulesByFile(file: string): Set<EvaluatedModuleNode> | undefined {\n    return this.fileToModulesMap.get(file)\n  }\n\n  /**\n   * Returns the module node by the URL that was used in the import statement.\n   * Unlike module graph on the server, the URL is not resolved and is used as is.\n   * @param url Server URL that was used in the import statement\n   */\n  public getModuleByUrl(url: string): EvaluatedModuleNode | undefined {\n    return this.urlToIdModuleMap.get(unwrapId(url))\n  }\n\n  /**\n   * Ensure that module is in the graph. If the module is already in the graph,\n   * it will return the existing module node. Otherwise, it will create a new\n   * module node and add it to the graph.\n   * @param id Resolved module ID\n   * @param url URL that was used in the import statement\n   */\n  public ensureModule(id: string, url: string): EvaluatedModuleNode {\n    id = normalizeModuleId(id)\n    if (this.idToModuleMap.has(id)) {\n      const moduleNode = this.idToModuleMap.get(id)!\n      this.urlToIdModuleMap.set(url, moduleNode)\n      return moduleNode\n    }\n    const moduleNode = new EvaluatedModuleNode(id, url)\n    this.idToModuleMap.set(id, moduleNode)\n    this.urlToIdModuleMap.set(url, moduleNode)\n\n    const fileModules = this.fileToModulesMap.get(moduleNode.file) || new Set()\n    fileModules.add(moduleNode)\n    this.fileToModulesMap.set(moduleNode.file, fileModules)\n    return moduleNode\n  }\n\n  public invalidateModule(node: EvaluatedModuleNode): void {\n    node.evaluated = false\n    node.meta = undefined\n    node.map = undefined\n    node.promise = undefined\n    node.exports = undefined\n    // remove imports in case they are changed,\n    // don't remove the importers because otherwise it will be empty after evaluation\n    // this can create a bug when file was removed but it still triggers full-reload\n    // we are fine with the bug for now because it's not a common case\n    node.imports.clear()\n  }\n\n  /**\n   * Extracts the inlined source map from the module code and returns the decoded\n   * source map. If the source map is not inlined, it will return null.\n   * @param id Resolved module ID\n   */\n  getModuleSourceMapById(id: string): DecodedMap | null {\n    const mod = this.getModuleById(id)\n    if (!mod) return null\n    if (mod.map) return mod.map\n    if (!mod.meta || !('code' in mod.meta)) return null\n\n    const pattern = `//# ${SOURCEMAPPING_URL}=data:application/json;base64,`\n    const lastIndex = mod.meta.code.lastIndexOf(pattern)\n    if (lastIndex === -1) return null\n\n    const mapString = MODULE_RUNNER_SOURCEMAPPING_REGEXP.exec(\n      mod.meta.code.slice(lastIndex),\n    )?.[1]\n    if (!mapString) return null\n    mod.map = new DecodedMap(JSON.parse(decodeBase64(mapString)), mod.file)\n    return mod.map\n  }\n\n  public clear(): void {\n    this.idToModuleMap.clear()\n    this.fileToModulesMap.clear()\n    this.urlToIdModuleMap.clear()\n  }\n}\n\n// unique id that is not available as \"$bare_import\" like \"test\"\n// https://nodejs.org/api/modules.html#built-in-modules-with-mandatory-node-prefix\nconst prefixedBuiltins = new Set([\n  'node:sea',\n  'node:sqlite',\n  'node:test',\n  'node:test/reporters',\n])\n\n// transform file url to id\n// virtual:custom -> virtual:custom\n// \\0custom -> \\0custom\n// node:fs -> fs\n// /@fs/C:/root/id.js => C:/root/id.js\n// file:///C:/root/id.js -> C:/root/id.js\nexport function normalizeModuleId(file: string): string {\n  if (prefixedBuiltins.has(file)) return file\n\n  // unix style, but Windows path still starts with the drive letter to check the root\n  const unixFile = slash(file)\n    .replace(/^\\/@fs\\//, isWindows ? '' : '/')\n    .replace(/^node:/, '')\n    .replace(/^\\/+/, '/')\n\n  // if it's not in the root, keep it as a path, not a URL\n  return unixFile.replace(/^file:\\/+/, isWindows ? '' : '/')\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/hmrHandler.ts",
    "content": "import type { HotPayload } from '#types/hmrPayload'\nimport { slash, unwrapId } from '../shared/utils'\nimport { ERR_OUTDATED_OPTIMIZED_DEP } from '../shared/constants'\nimport { createHMRHandler } from '../shared/hmrHandler'\nimport type { ModuleRunner } from './runner'\n\nexport function createHMRHandlerForRunner(\n  runner: ModuleRunner,\n): (payload: HotPayload) => Promise<void> {\n  return createHMRHandler(async (payload) => {\n    const hmrClient = runner.hmrClient\n    if (!hmrClient || runner.isClosed()) return\n    switch (payload.type) {\n      case 'connected':\n        hmrClient.logger.debug(`connected.`)\n        break\n      case 'update':\n        await hmrClient.notifyListeners('vite:beforeUpdate', payload)\n        await Promise.all(\n          payload.updates.map(async (update): Promise<void> => {\n            if (update.type === 'js-update') {\n              // runner always caches modules by their full path without /@id/ prefix\n              update.acceptedPath = unwrapId(update.acceptedPath)\n              update.path = unwrapId(update.path)\n              return hmrClient.queueUpdate(update)\n            }\n\n            hmrClient.logger.error('css hmr is not supported in runner mode.')\n          }),\n        )\n        await hmrClient.notifyListeners('vite:afterUpdate', payload)\n        break\n      case 'custom': {\n        await hmrClient.notifyListeners(payload.event, payload.data)\n        break\n      }\n      case 'full-reload': {\n        const { triggeredBy } = payload\n        const clearEntrypointUrls = triggeredBy\n          ? getModulesEntrypoints(\n              runner,\n              getModulesByFile(runner, slash(triggeredBy)),\n            )\n          : findAllEntrypoints(runner)\n\n        if (!clearEntrypointUrls.size) break\n\n        hmrClient.logger.debug(`program reload`)\n        await hmrClient.notifyListeners('vite:beforeFullReload', payload)\n        runner.evaluatedModules.clear()\n\n        for (const url of clearEntrypointUrls) {\n          try {\n            await runner.import(url)\n          } catch (err) {\n            if (err.code !== ERR_OUTDATED_OPTIMIZED_DEP) {\n              hmrClient.logger.error(\n                `An error happened during full reload\\n${err.message}\\n${err.stack}`,\n              )\n            }\n          }\n        }\n        break\n      }\n      case 'prune':\n        await hmrClient.notifyListeners('vite:beforePrune', payload)\n        await hmrClient.prunePaths(payload.paths)\n        break\n      case 'error': {\n        await hmrClient.notifyListeners('vite:error', payload)\n        const err = payload.err\n        hmrClient.logger.error(\n          `Internal Server Error\\n${err.message}\\n${err.stack}`,\n        )\n        break\n      }\n      case 'ping': // noop\n        break\n      default: {\n        const check: never = payload\n        return check\n      }\n    }\n  })\n}\n\nfunction getModulesByFile(runner: ModuleRunner, file: string): string[] {\n  const nodes = runner.evaluatedModules.getModulesByFile(file)\n  if (!nodes) {\n    return []\n  }\n  return [...nodes].map((node) => node.id)\n}\n\nfunction getModulesEntrypoints(\n  runner: ModuleRunner,\n  modules: string[],\n  visited = new Set<string>(),\n  entrypoints = new Set<string>(),\n) {\n  for (const moduleId of modules) {\n    if (visited.has(moduleId)) continue\n    visited.add(moduleId)\n    const module = runner.evaluatedModules.getModuleById(moduleId)\n    if (!module) {\n      continue\n    }\n    if (!module.importers.size) {\n      entrypoints.add(module.url)\n      continue\n    }\n    for (const importer of module.importers) {\n      getModulesEntrypoints(runner, [importer], visited, entrypoints)\n    }\n  }\n  return entrypoints\n}\n\nfunction findAllEntrypoints(\n  runner: ModuleRunner,\n  entrypoints = new Set<string>(),\n): Set<string> {\n  for (const mod of runner.evaluatedModules.idToModuleMap.values()) {\n    if (!mod.importers.size) {\n      entrypoints.add(mod.url)\n    }\n  }\n  return entrypoints\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/hmrLogger.ts",
    "content": "import type { HMRLogger } from '../shared/hmr'\n\nconst noop = (): void => {}\n\nexport const silentConsole: HMRLogger = {\n  debug: noop,\n  error: noop,\n}\n\nexport const hmrLogger: HMRLogger = {\n  debug: (...msg) => console.log('[vite]', ...msg),\n  error: (error) => console.log('[vite]', error),\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/importMetaResolver.ts",
    "content": "import type { ResolveFnOutput, ResolveHookContext } from 'node:module'\n\nexport type ImportMetaResolver = (specifier: string, importer: string) => string\n\nconst customizationHookNamespace = 'vite-module-runner:import-meta-resolve/v1/'\nconst customizationHooksModule = /* js */ `\n\nexport async function resolve(specifier, context, nextResolve) {\n  if (specifier.startsWith(${JSON.stringify(customizationHookNamespace)})) {\n    const data = specifier.slice(${JSON.stringify(customizationHookNamespace)}.length)\n    const [parsedSpecifier, parsedImporter] = JSON.parse(data)\n    specifier = parsedSpecifier\n    context.parentURL = parsedImporter\n  }\n  return nextResolve(specifier, context)\n}\n\n`\nfunction customizationHookResolve(\n  specifier: string,\n  context: ResolveHookContext,\n  nextResolve: (\n    specifier: string,\n    context: ResolveHookContext,\n  ) => ResolveFnOutput,\n): ResolveFnOutput {\n  if (specifier.startsWith(customizationHookNamespace)) {\n    const data = specifier.slice(customizationHookNamespace.length)\n    const [parsedSpecifier, parsedImporter] = JSON.parse(data)\n    specifier = parsedSpecifier\n    context.parentURL = parsedImporter\n  }\n  return nextResolve(specifier, context)\n}\n\n// Ensure that we only register the hook once\n// Otherwise, a hook will be registered for each createImportMetaResolver call\n// and eventually cause \"Maximum call stack size exceeded\" errors\nlet isHookRegistered = false\n\nexport function createImportMetaResolver(): ImportMetaResolver | undefined {\n  if (isHookRegistered) {\n    return importMetaResolveWithCustomHook\n  }\n\n  let module: typeof import('node:module') | undefined\n  try {\n    module =\n      typeof process !== 'undefined'\n        ? process.getBuiltinModule('node:module').Module\n        : undefined\n  } catch {\n    return\n  }\n  // `module.Module` may be `undefined` when `node:module` is mocked\n  if (!module) {\n    return\n  }\n\n  // Use registerHooks if available as it's more performant\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins -- we check the existence\n  if (module.registerHooks) {\n    // eslint-disable-next-line n/no-unsupported-features/node-builtins -- we checked the existence\n    module.registerHooks({ resolve: customizationHookResolve })\n    isHookRegistered = true\n    return importMetaResolveWithCustomHook\n  }\n\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins -- we check the existence\n  if (!module.register) {\n    return\n  }\n\n  try {\n    const hookModuleContent = `data:text/javascript,${encodeURI(customizationHooksModule)}`\n    // eslint-disable-next-line n/no-unsupported-features/node-builtins -- we checked the existence\n    module.register(hookModuleContent)\n  } catch (e) {\n    // For `--experimental-network-imports` flag that exists in Node before v22\n    if ('code' in e && e.code === 'ERR_NETWORK_IMPORT_DISALLOWED') {\n      return\n    }\n    throw e\n  }\n\n  isHookRegistered = true\n  return importMetaResolveWithCustomHook\n}\n\nfunction importMetaResolveWithCustomHook(\n  specifier: string,\n  importer: string,\n): string {\n  return import.meta.resolve(\n    `${customizationHookNamespace}${JSON.stringify([specifier, importer])}`,\n  )\n}\n\n// NOTE: use computed string to avoid `define` replacing `import.meta.resolve` when bundled\nexport const importMetaResolveWithCustomHookString: string = /* js */ `\n\n  (() => {\n    const resolve = 'resolve'\n    return (specifier, importer) =>\n      import.meta[resolve](\n        \\`${customizationHookNamespace}\\${JSON.stringify([specifier, importer])}\\`,\n      )\n  })()\n\n`\n"
  },
  {
    "path": "packages/vite/src/module-runner/index.ts",
    "content": "// this file should re-export only things that don't rely on Node.js or other runner features\n\nexport {\n  EvaluatedModules,\n  normalizeModuleId,\n  type EvaluatedModuleNode,\n} from './evaluatedModules'\nexport { ModuleRunner } from './runner'\nexport { ESModulesEvaluator } from './esmEvaluator'\nexport {\n  createDefaultImportMeta,\n  createNodeImportMeta,\n} from './createImportMeta'\n\nexport { createWebSocketModuleRunnerTransport } from '../shared/moduleRunnerTransport'\n\nexport type { FetchFunctionOptions, FetchResult } from '../shared/invokeMethods'\nexport type {\n  ModuleRunnerTransportHandlers,\n  ModuleRunnerTransport,\n} from '../shared/moduleRunnerTransport'\nexport type { HMRLogger } from '../shared/hmr'\nexport type {\n  ModuleEvaluator,\n  ModuleRunnerContext,\n  FetchFunction,\n  ResolvedResult,\n  SSRImportMetadata,\n  ModuleRunnerImportMeta,\n  ModuleRunnerOptions,\n  ModuleRunnerHmr,\n} from './types'\nexport {\n  ssrDynamicImportKey,\n  ssrExportAllKey,\n  ssrExportNameKey,\n  ssrImportKey,\n  ssrImportMetaKey,\n  ssrModuleExportsKey,\n} from './constants'\nexport type { InterceptorOptions } from './sourcemap/interceptor'\n"
  },
  {
    "path": "packages/vite/src/module-runner/runner.ts",
    "content": "import type { ViteHotContext } from '#types/hot'\nimport { HMRClient, HMRContext, type HMRLogger } from '../shared/hmr'\nimport { cleanUrl, isPrimitive } from '../shared/utils'\nimport { analyzeImportedModDifference } from '../shared/ssrTransform'\nimport {\n  type NormalizedModuleRunnerTransport,\n  normalizeModuleRunnerTransport,\n} from '../shared/moduleRunnerTransport'\nimport { createIsBuiltin } from '../shared/builtin'\nimport type { EvaluatedModuleNode } from './evaluatedModules'\nimport { EvaluatedModules } from './evaluatedModules'\nimport type {\n  ModuleEvaluator,\n  ModuleRunnerContext,\n  ModuleRunnerOptions,\n  ResolvedResult,\n  SSRImportMetadata,\n} from './types'\nimport { posixDirname, posixPathToFileHref, posixResolve } from './utils'\nimport {\n  ssrDynamicImportKey,\n  ssrExportAllKey,\n  ssrExportNameKey,\n  ssrImportKey,\n  ssrImportMetaKey,\n  ssrModuleExportsKey,\n} from './constants'\nimport { hmrLogger, silentConsole } from './hmrLogger'\nimport { createHMRHandlerForRunner } from './hmrHandler'\nimport { enableSourceMapSupport } from './sourcemap/index'\nimport { ESModulesEvaluator } from './esmEvaluator'\nimport { createDefaultImportMeta } from './createImportMeta'\n\ninterface ModuleRunnerDebugger {\n  (formatter: unknown, ...args: unknown[]): void\n}\n\nexport class ModuleRunner {\n  public evaluatedModules: EvaluatedModules\n  public hmrClient?: HMRClient\n\n  private readonly transport: NormalizedModuleRunnerTransport\n  private readonly resetSourceMapSupport?: () => void\n  private readonly concurrentModuleNodePromises = new Map<\n    string,\n    Promise<EvaluatedModuleNode>\n  >()\n  private isBuiltin?: (id: string) => boolean\n  private builtinsPromise?: Promise<void>\n\n  private closed = false\n\n  constructor(\n    public options: ModuleRunnerOptions,\n    public evaluator: ModuleEvaluator = new ESModulesEvaluator(),\n    private debug?: ModuleRunnerDebugger | undefined,\n  ) {\n    this.evaluatedModules = options.evaluatedModules ?? new EvaluatedModules()\n    this.transport = normalizeModuleRunnerTransport(options.transport)\n    if (options.hmr !== false) {\n      const optionsHmr = options.hmr ?? true\n      const resolvedHmrLogger: HMRLogger =\n        optionsHmr === true || optionsHmr.logger === undefined\n          ? hmrLogger\n          : optionsHmr.logger === false\n            ? silentConsole\n            : optionsHmr.logger\n      this.hmrClient = new HMRClient(\n        resolvedHmrLogger,\n        this.transport,\n        ({ acceptedPath }) => this.import(acceptedPath),\n      )\n      if (!this.transport.connect) {\n        throw new Error(\n          'HMR is not supported by this runner transport, but `hmr` option was set to true',\n        )\n      }\n      this.transport.connect(createHMRHandlerForRunner(this))\n    } else {\n      this.transport.connect?.()\n    }\n    if (options.sourcemapInterceptor !== false) {\n      this.resetSourceMapSupport = enableSourceMapSupport(this)\n    }\n  }\n\n  /**\n   * URL to execute. Accepts file path, server path or id relative to the root.\n   */\n  public async import<T = any>(url: string): Promise<T> {\n    const fetchedModule = await this.cachedModule(url)\n    return await this.cachedRequest(url, fetchedModule)\n  }\n\n  /**\n   * Clear all caches including HMR listeners.\n   */\n  public clearCache(): void {\n    this.evaluatedModules.clear()\n    this.hmrClient?.clear()\n  }\n\n  /**\n   * Clears all caches, removes all HMR listeners, and resets source map support.\n   * This method doesn't stop the HMR connection.\n   */\n  public async close(): Promise<void> {\n    this.resetSourceMapSupport?.()\n    this.clearCache()\n    this.hmrClient = undefined\n    this.closed = true\n    await this.transport.disconnect?.()\n  }\n\n  /**\n   * Returns `true` if the runtime has been closed by calling `close()` method.\n   */\n  public isClosed(): boolean {\n    return this.closed\n  }\n\n  private processImport(\n    exports: Record<string, any>,\n    fetchResult: ResolvedResult,\n    metadata?: SSRImportMetadata,\n  ) {\n    if (!('externalize' in fetchResult)) {\n      return exports\n    }\n    const { url, type } = fetchResult\n    if (type !== 'module' && type !== 'commonjs') return exports\n    analyzeImportedModDifference(exports, url, type, metadata)\n    return exports\n  }\n\n  private isCircularModule(mod: EvaluatedModuleNode) {\n    for (const importedFile of mod.imports) {\n      if (mod.importers.has(importedFile)) {\n        return true\n      }\n    }\n    return false\n  }\n\n  private isCircularImport(\n    importers: Set<string>,\n    moduleUrl: string,\n    visited = new Set<string>(),\n  ) {\n    for (const importer of importers) {\n      if (visited.has(importer)) {\n        continue\n      }\n      visited.add(importer)\n      if (importer === moduleUrl) {\n        return true\n      }\n      const mod = this.evaluatedModules.getModuleById(importer)\n      if (\n        mod &&\n        mod.importers.size &&\n        this.isCircularImport(mod.importers, moduleUrl, visited)\n      ) {\n        return true\n      }\n    }\n    return false\n  }\n\n  private async cachedRequest(\n    url: string,\n    mod: EvaluatedModuleNode,\n    callstack: string[] = [],\n    metadata?: SSRImportMetadata,\n  ): Promise<any> {\n    const meta = mod.meta!\n    const moduleId = meta.id\n\n    const { importers } = mod\n\n    const importee = callstack[callstack.length - 1]\n\n    if (importee) importers.add(importee)\n\n    // fast path: already evaluated modules can't deadlock\n    if (mod.evaluated && mod.promise) {\n      return this.processImport(await mod.promise, meta, metadata)\n    }\n\n    // check circular dependency (only for modules still being evaluated)\n    if (\n      callstack.includes(moduleId) ||\n      this.isCircularModule(mod) ||\n      this.isCircularImport(importers, moduleId)\n    ) {\n      if (mod.exports) return this.processImport(mod.exports, meta, metadata)\n    }\n\n    let debugTimer: any\n    if (this.debug) {\n      debugTimer = setTimeout(() => {\n        const getStack = () =>\n          `stack:\\n${[...callstack, moduleId]\n            .reverse()\n            .map((p) => `  - ${p}`)\n            .join('\\n')}`\n\n        this.debug!(\n          `[module runner] module ${moduleId} takes over 2s to load.\\n${getStack()}`,\n        )\n      }, 2000)\n    }\n\n    try {\n      // cached module (in-progress, not yet evaluated)\n      if (mod.promise)\n        return this.processImport(await mod.promise, meta, metadata)\n\n      const promise = this.directRequest(url, mod, callstack)\n      mod.promise = promise\n      mod.evaluated = false\n      return this.processImport(await promise, meta, metadata)\n    } finally {\n      mod.evaluated = true\n      if (debugTimer) clearTimeout(debugTimer)\n    }\n  }\n\n  private async cachedModule(\n    url: string,\n    importer?: string,\n  ): Promise<EvaluatedModuleNode> {\n    let cached = this.concurrentModuleNodePromises.get(url)\n    if (!cached) {\n      const cachedModule = this.evaluatedModules.getModuleByUrl(url)\n      cached = this.getModuleInformation(url, importer, cachedModule).finally(\n        () => {\n          this.concurrentModuleNodePromises.delete(url)\n        },\n      )\n      this.concurrentModuleNodePromises.set(url, cached)\n    } else {\n      this.debug?.('[module runner] using cached module info for', url)\n    }\n\n    return cached\n  }\n\n  private ensureBuiltins(): Promise<void> | undefined {\n    if (this.isBuiltin) return\n\n    this.builtinsPromise ??= (async () => {\n      try {\n        this.debug?.('[module runner] fetching builtins from server')\n        const serializedBuiltins = await this.transport.invoke(\n          'getBuiltins',\n          [],\n        )\n        const builtins = serializedBuiltins.map((builtin) =>\n          typeof builtin === 'object' && builtin && 'type' in builtin\n            ? builtin.type === 'string'\n              ? builtin.value\n              : new RegExp(builtin.source, builtin.flags)\n            : // NOTE: Vitest returns raw values instead of serialized ones\n              builtin,\n        )\n        this.isBuiltin = createIsBuiltin(builtins)\n        this.debug?.('[module runner] builtins loaded:', builtins)\n      } finally {\n        this.builtinsPromise = undefined\n      }\n    })()\n\n    return this.builtinsPromise\n  }\n\n  private async getModuleInformation(\n    url: string,\n    importer: string | undefined,\n    cachedModule: EvaluatedModuleNode | undefined,\n  ): Promise<EvaluatedModuleNode> {\n    if (this.closed) {\n      throw new Error(`Vite module runner has been closed.`)\n    }\n\n    await this.ensureBuiltins()\n\n    this.debug?.('[module runner] fetching', url)\n\n    const isCached = !!(typeof cachedModule === 'object' && cachedModule.meta)\n\n    const fetchedModule = // fast return for established externalized pattern\n      (\n        url.startsWith('data:') || this.isBuiltin?.(url)\n          ? { externalize: url, type: 'builtin' }\n          : await this.transport.invoke('fetchModule', [\n              url,\n              importer,\n              {\n                cached: isCached,\n                startOffset: this.evaluator.startOffset,\n              },\n            ])\n      ) as ResolvedResult\n\n    if ('cache' in fetchedModule) {\n      if (!cachedModule || !cachedModule.meta) {\n        throw new Error(\n          `Module \"${url}\" was mistakenly invalidated during fetch phase.`,\n        )\n      }\n      return cachedModule\n    }\n\n    const moduleId =\n      'externalize' in fetchedModule\n        ? fetchedModule.externalize\n        : fetchedModule.id\n    const moduleUrl = 'url' in fetchedModule ? fetchedModule.url : url\n    const module = this.evaluatedModules.ensureModule(moduleId, moduleUrl)\n\n    if ('invalidate' in fetchedModule && fetchedModule.invalidate) {\n      this.evaluatedModules.invalidateModule(module)\n    }\n\n    fetchedModule.url = moduleUrl\n    fetchedModule.id = moduleId\n    module.meta = fetchedModule\n\n    return module\n  }\n\n  // override is allowed, consider this a public API\n  protected async directRequest(\n    url: string,\n    mod: EvaluatedModuleNode,\n    _callstack: string[],\n  ): Promise<any> {\n    const fetchResult = mod.meta!\n    const moduleId = fetchResult.id\n    const callstack = [..._callstack, moduleId]\n\n    const request = async (dep: string, metadata?: SSRImportMetadata) => {\n      const importer = ('file' in fetchResult && fetchResult.file) || moduleId\n      const depMod = await this.cachedModule(dep, importer)\n      depMod.importers.add(moduleId)\n      mod.imports.add(depMod.id)\n\n      return this.cachedRequest(dep, depMod, callstack, metadata)\n    }\n\n    const dynamicRequest = async (dep: string) => {\n      // it's possible to provide an object with toString() method inside import()\n      dep = String(dep)\n      if (dep[0] === '.') {\n        dep = posixResolve(posixDirname(url), dep)\n      }\n      return request(dep, { isDynamicImport: true })\n    }\n\n    if ('externalize' in fetchResult) {\n      const { externalize } = fetchResult\n      this.debug?.('[module runner] externalizing', externalize)\n      const exports = await this.evaluator.runExternalModule(externalize)\n      mod.exports = exports\n      return exports\n    }\n\n    const { code, file } = fetchResult\n\n    if (code == null) {\n      const importer = callstack[callstack.length - 2]\n      throw new Error(\n        `[module runner] Failed to load \"${url}\"${\n          importer ? ` imported from ${importer}` : ''\n        }`,\n      )\n    }\n\n    const createImportMeta =\n      this.options.createImportMeta ?? createDefaultImportMeta\n\n    const modulePath = cleanUrl(file || moduleId)\n    // disambiguate the `<UNIT>:/` on windows: see nodejs/node#31710\n    const href = posixPathToFileHref(modulePath)\n    const meta = await createImportMeta(modulePath)\n    const exports = Object.create(null)\n    Object.defineProperty(exports, Symbol.toStringTag, {\n      value: 'Module',\n      enumerable: false,\n      configurable: false,\n    })\n\n    mod.exports = exports\n\n    let hotContext: ViteHotContext | undefined\n    if (this.hmrClient) {\n      Object.defineProperty(meta, 'hot', {\n        enumerable: true,\n        get: () => {\n          if (!this.hmrClient) {\n            throw new Error(`[module runner] HMR client was closed.`)\n          }\n          this.debug?.('[module runner] creating hmr context for', mod.url)\n          hotContext ||= new HMRContext(this.hmrClient, mod.url)\n          return hotContext\n        },\n        set: (value) => {\n          hotContext = value\n        },\n      })\n    }\n\n    const context: ModuleRunnerContext = {\n      [ssrImportKey]: request,\n      [ssrDynamicImportKey]: dynamicRequest,\n      [ssrModuleExportsKey]: exports,\n      [ssrExportAllKey]: (obj: any) => exportAll(exports, obj),\n      [ssrExportNameKey]: (name, getter) =>\n        Object.defineProperty(exports, name, {\n          enumerable: true,\n          configurable: true,\n          get: getter,\n        }),\n      [ssrImportMetaKey]: meta,\n    }\n\n    this.debug?.('[module runner] executing', href)\n\n    await this.evaluator.runInlinedModule(context, code, mod)\n\n    return exports\n  }\n}\n\nfunction exportAll(exports: any, sourceModule: any) {\n  // when a module exports itself it causes\n  // call stack error\n  if (exports === sourceModule) return\n\n  if (\n    isPrimitive(sourceModule) ||\n    Array.isArray(sourceModule) ||\n    sourceModule instanceof Promise\n  )\n    return\n\n  for (const key in sourceModule) {\n    if (key !== 'default' && key !== '__esModule' && !(key in exports)) {\n      try {\n        Object.defineProperty(exports, key, {\n          enumerable: true,\n          configurable: true,\n          get: () => sourceModule[key],\n        })\n      } catch {}\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/sourcemap/decoder.ts",
    "content": "import type { OriginalMapping } from '@jridgewell/trace-mapping'\nimport { originalPositionFor } from '@jridgewell/trace-mapping'\nimport { posixDirname, posixResolve } from '../utils'\n\ninterface SourceMapLike {\n  version: number\n  mappings?: string\n  names?: string[]\n  sources?: string[]\n  sourcesContent?: string[]\n}\n\ntype Needle = {\n  line: number\n  column: number\n}\n\nexport class DecodedMap {\n  _encoded: string\n  _decoded: undefined | number[][][]\n  _decodedMemo: Stats\n  url: string\n  file: string\n  version: number\n  names: string[] = []\n  resolvedSources: string[]\n\n  constructor(\n    public map: SourceMapLike,\n    from: string,\n  ) {\n    const { mappings, names, sources } = map\n    this.version = map.version\n    this.names = names || []\n    this._encoded = mappings || ''\n    this._decodedMemo = memoizedState()\n    this.url = from\n    this.file = from\n    const originDir = posixDirname(from)\n    this.resolvedSources = (sources || []).map((s) =>\n      posixResolve(originDir, s || ''),\n    )\n  }\n}\n\ninterface Stats {\n  lastKey: number\n  lastNeedle: number\n  lastIndex: number\n}\nfunction memoizedState(): Stats {\n  return {\n    lastKey: -1,\n    lastNeedle: -1,\n    lastIndex: -1,\n  }\n}\nexport function getOriginalPosition(\n  map: DecodedMap,\n  needle: Needle,\n): OriginalMapping | null {\n  const result = originalPositionFor(map as any, needle)\n  if (result.column == null) {\n    return null\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/sourcemap/index.ts",
    "content": "import type { ModuleRunner } from '../runner'\nimport { interceptStackTrace } from './interceptor'\n\nexport function enableSourceMapSupport(runner: ModuleRunner): () => void {\n  if (runner.options.sourcemapInterceptor === 'node') {\n    if (typeof process === 'undefined') {\n      throw new TypeError(\n        `Cannot use \"sourcemapInterceptor: 'node'\" because global \"process\" variable is not available.`,\n      )\n    }\n    /* eslint-disable n/no-unsupported-features/node-builtins -- process.setSourceMapsEnabled and process.sourceMapsEnabled */\n    if (typeof process.setSourceMapsEnabled !== 'function') {\n      throw new TypeError(\n        `Cannot use \"sourcemapInterceptor: 'node'\" because \"process.setSourceMapsEnabled\" function is not available. Please use Node >= 16.6.0.`,\n      )\n    }\n    const isEnabledAlready = process.sourceMapsEnabled ?? false\n    process.setSourceMapsEnabled(true)\n    return () => !isEnabledAlready && process.setSourceMapsEnabled(false)\n    /* eslint-enable n/no-unsupported-features/node-builtins */\n  }\n  return interceptStackTrace(\n    runner,\n    typeof runner.options.sourcemapInterceptor === 'object'\n      ? runner.options.sourcemapInterceptor\n      : undefined,\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/sourcemap/interceptor.ts",
    "content": "import type { OriginalMapping } from '@jridgewell/trace-mapping'\nimport type { ModuleRunner } from '../runner'\nimport { posixDirname, posixResolve } from '../utils'\nimport type { EvaluatedModules } from '../evaluatedModules'\nimport { slash } from '../../shared/utils'\nimport { DecodedMap, getOriginalPosition } from './decoder'\n\ninterface RetrieveFileHandler {\n  (path: string): string | null | undefined | false\n}\n\ninterface RetrieveSourceMapHandler {\n  (path: string): null | { url: string; map: any }\n}\n\nexport interface InterceptorOptions {\n  retrieveFile?: RetrieveFileHandler\n  retrieveSourceMap?: RetrieveSourceMapHandler\n}\n\nconst sourceMapCache: Record<string, CachedMapEntry> = {}\nconst fileContentsCache: Record<string, string> = {}\n\nconst evaluatedModulesCache = new Set<EvaluatedModules>()\nconst retrieveFileHandlers = new Set<RetrieveFileHandler>()\nconst retrieveSourceMapHandlers = new Set<RetrieveSourceMapHandler>()\n\nconst createExecHandlers = <T extends (...args: any) => any>(\n  handlers: Set<T>,\n) => {\n  return ((...args: Parameters<T>) => {\n    for (const handler of handlers) {\n      const result = handler(...args)\n      if (result) return result\n    }\n    return null\n  }) as T\n}\n\nconst retrieveFileFromHandlers = createExecHandlers(retrieveFileHandlers)\nconst retrieveSourceMapFromHandlers = createExecHandlers(\n  retrieveSourceMapHandlers,\n)\n\nlet overridden = false\nconst originalPrepare = Error.prepareStackTrace\n\nfunction resetInterceptor(runner: ModuleRunner, options: InterceptorOptions) {\n  evaluatedModulesCache.delete(runner.evaluatedModules)\n  if (options.retrieveFile) retrieveFileHandlers.delete(options.retrieveFile)\n  if (options.retrieveSourceMap)\n    retrieveSourceMapHandlers.delete(options.retrieveSourceMap)\n  if (evaluatedModulesCache.size === 0) {\n    Error.prepareStackTrace = originalPrepare\n    overridden = false\n  }\n}\n\nexport function interceptStackTrace(\n  runner: ModuleRunner,\n  options: InterceptorOptions = {},\n): () => void {\n  if (!overridden) {\n    Error.prepareStackTrace = prepareStackTrace\n    overridden = true\n  }\n  evaluatedModulesCache.add(runner.evaluatedModules)\n  if (options.retrieveFile) retrieveFileHandlers.add(options.retrieveFile)\n  if (options.retrieveSourceMap)\n    retrieveSourceMapHandlers.add(options.retrieveSourceMap)\n  return () => resetInterceptor(runner, options)\n}\n\ninterface CallSite extends NodeJS.CallSite {\n  getScriptNameOrSourceURL(): string\n}\n\ninterface State {\n  nextPosition: null | OriginalMapping\n  curPosition: null | OriginalMapping\n}\n\ninterface CachedMapEntry {\n  url: string | null\n  map: DecodedMap | null\n  vite?: boolean\n}\n\n// Support URLs relative to a directory, but be careful about a protocol prefix\nfunction supportRelativeURL(file: string, url: string) {\n  if (!file) return url\n  const dir = posixDirname(slash(file))\n  const match = /^\\w+:\\/\\/[^/]*/.exec(dir)\n  let protocol = match ? match[0] : ''\n  const startPath = dir.slice(protocol.length)\n  if (protocol && /^\\/\\w:/.test(startPath)) {\n    // handle file:///C:/ paths\n    protocol += '/'\n    return protocol + slash(posixResolve(startPath, url))\n  }\n  return protocol + posixResolve(startPath, url)\n}\n\nfunction getRunnerSourceMap(position: OriginalMapping): CachedMapEntry | null {\n  for (const moduleGraph of evaluatedModulesCache) {\n    const sourceMap = moduleGraph.getModuleSourceMapById(position.source!)\n    if (sourceMap) {\n      return {\n        url: position.source,\n        map: sourceMap,\n        vite: true,\n      }\n    }\n  }\n  return null\n}\n\nfunction retrieveFile(path: string): string | null | undefined | false {\n  if (path in fileContentsCache) return fileContentsCache[path]\n  const content = retrieveFileFromHandlers(path)\n  if (typeof content === 'string') {\n    fileContentsCache[path] = content\n    return content\n  }\n  return null\n}\n\nfunction retrieveSourceMapURL(source: string) {\n  // Get the URL of the source map\n  const fileData = retrieveFile(source)\n  if (!fileData) return null\n  const re =\n    /\\/\\/[@#]\\s*sourceMappingURL=([^\\s'\"]+)\\s*$|\\/\\*[@#]\\s*sourceMappingURL=[^\\s*'\"]+\\s*\\*\\/\\s*$/gm\n  // Keep executing the search to find the *last* sourceMappingURL to avoid\n  // picking up sourceMappingURLs from comments, strings, etc.\n  let lastMatch, match\n\n  while ((match = re.exec(fileData))) lastMatch = match\n  if (!lastMatch) return null\n  return lastMatch[1]\n}\n\nconst reSourceMap = /^data:application\\/json[^,]+base64,/\n\nfunction retrieveSourceMap(source: string) {\n  const urlAndMap = retrieveSourceMapFromHandlers(source)\n  if (urlAndMap) return urlAndMap\n\n  let sourceMappingURL = retrieveSourceMapURL(source)\n  if (!sourceMappingURL) return null\n\n  // Read the contents of the source map\n  let sourceMapData\n  if (reSourceMap.test(sourceMappingURL)) {\n    // Support source map URL as a data url\n    const rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1)\n    sourceMapData = Buffer.from(rawData, 'base64').toString()\n    sourceMappingURL = source\n  } else {\n    // Support source map URLs relative to the source URL\n    sourceMappingURL = supportRelativeURL(source, sourceMappingURL)\n    sourceMapData = retrieveFile(sourceMappingURL)\n  }\n\n  if (!sourceMapData) return null\n\n  return {\n    url: sourceMappingURL,\n    map: sourceMapData,\n  }\n}\n\nfunction mapSourcePosition(position: OriginalMapping) {\n  if (!position.source) return position\n  let sourceMap = getRunnerSourceMap(position)\n  if (!sourceMap) sourceMap = sourceMapCache[position.source]\n  if (!sourceMap) {\n    // Call the (overridable) retrieveSourceMap function to get the source map.\n    const urlAndMap = retrieveSourceMap(position.source)\n    if (urlAndMap && urlAndMap.map) {\n      const url = urlAndMap.url\n      sourceMap = sourceMapCache[position.source] = {\n        url,\n        map: new DecodedMap(\n          typeof urlAndMap.map === 'string'\n            ? JSON.parse(urlAndMap.map)\n            : urlAndMap.map,\n          url,\n        ),\n      }\n\n      const contents = sourceMap.map?.map.sourcesContent\n      // Load all sources stored inline with the source map into the file cache\n      // to pretend like they are already loaded. They may not exist on disk.\n      if (sourceMap.map && contents) {\n        sourceMap.map.resolvedSources.forEach((source, i) => {\n          const content = contents[i]\n          if (content && source && url) {\n            const contentUrl = supportRelativeURL(url, source)\n            fileContentsCache[contentUrl] = content\n          }\n        })\n      }\n    } else {\n      sourceMap = sourceMapCache[position.source] = {\n        url: null,\n        map: null,\n      }\n    }\n  }\n\n  // Resolve the source URL relative to the URL of the source map\n  if (sourceMap.map && sourceMap.url) {\n    const originalPosition = getOriginalPosition(sourceMap.map, position)\n\n    // Only return the original position if a matching line was found. If no\n    // matching line is found then we return position instead, which will cause\n    // the stack trace to print the path and line for the compiled file. It is\n    // better to give a precise location in the compiled file than a vague\n    // location in the original file.\n    if (originalPosition && originalPosition.source != null) {\n      originalPosition.source = supportRelativeURL(\n        sourceMap.url,\n        originalPosition.source,\n      )\n      if (sourceMap.vite) {\n        // @ts-expect-error vite is not defined\n        originalPosition._vite = true\n      }\n      return originalPosition\n    }\n  }\n\n  return position\n}\n\n// Parses code generated by FormatEvalOrigin(), a function inside V8:\n// https://code.google.com/p/v8/source/browse/trunk/src/messages.js\nfunction mapEvalOrigin(origin: string): string {\n  // Most eval() calls are in this format\n  let match = /^eval at ([^(]+) \\((.+):(\\d+):(\\d+)\\)$/.exec(origin)\n  if (match) {\n    const position = mapSourcePosition({\n      name: null,\n      source: match[2],\n      line: +match[3],\n      column: +match[4] - 1,\n    })\n    return `eval at ${match[1]} (${position.source}:${position.line}:${position.column + 1})`\n  }\n\n  // Parse nested eval() calls using recursion\n  match = /^eval at ([^(]+) \\((.+)\\)$/.exec(origin)\n  if (match) return `eval at ${match[1]} (${mapEvalOrigin(match[2])})`\n\n  // Make sure we still return useful information if we didn't find anything\n  return origin\n}\n\n// This is copied almost verbatim from the V8 source code at\n// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The\n// implementation of wrapCallSite() used to just forward to the actual source\n// code of CallSite.prototype.toString but unfortunately a new release of V8\n// did something to the prototype chain and broke the shim. The only fix I\n// could find was copy/paste.\nfunction CallSiteToString(this: CallSite) {\n  let fileName\n  let fileLocation = ''\n  if (this.isNative()) {\n    fileLocation = 'native'\n  } else {\n    fileName = this.getScriptNameOrSourceURL()\n    if (!fileName && this.isEval()) {\n      fileLocation = this.getEvalOrigin() as string\n      fileLocation += ', ' // Expecting source position to follow.\n    }\n\n    if (fileName) {\n      fileLocation += fileName\n    } else {\n      // Source code does not originate from a file and is not native, but we\n      // can still get the source position inside the source string, e.g. in\n      // an eval string.\n      fileLocation += '<anonymous>'\n    }\n    const lineNumber = this.getLineNumber()\n    if (lineNumber != null) {\n      fileLocation += `:${lineNumber}`\n      const columnNumber = this.getColumnNumber()\n      if (columnNumber) fileLocation += `:${columnNumber}`\n    }\n  }\n\n  let line = ''\n  const functionName = this.getFunctionName()\n  let addSuffix = true\n  const isConstructor = this.isConstructor()\n  const isMethodCall = !(this.isToplevel() || isConstructor)\n  if (isMethodCall) {\n    let typeName = this.getTypeName()\n    // Fixes shim to be backward compatible with Node v0 to v4\n    if (typeName === '[object Object]') typeName = 'null'\n\n    const methodName = this.getMethodName()\n    if (functionName) {\n      if (typeName && functionName.indexOf(typeName) !== 0)\n        line += `${typeName}.`\n\n      line += functionName\n      if (\n        methodName &&\n        functionName.indexOf(`.${methodName}`) !==\n          functionName.length - methodName.length - 1\n      )\n        line += ` [as ${methodName}]`\n    } else {\n      line += `${typeName}.${methodName || '<anonymous>'}`\n    }\n  } else if (isConstructor) {\n    line += `new ${functionName || '<anonymous>'}`\n  } else if (functionName) {\n    line += functionName\n  } else {\n    line += fileLocation\n    addSuffix = false\n  }\n  if (addSuffix) line += ` (${fileLocation})`\n\n  return line\n}\n\nfunction cloneCallSite(frame: CallSite) {\n  const object = {} as CallSite\n  Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach((name) => {\n    const key = name as keyof CallSite\n    // @ts-expect-error difficult to type\n    object[key] = /^(?:is|get)/.test(name)\n      ? function () {\n          return frame[key].call(frame)\n        }\n      : frame[key]\n  })\n  object.toString = CallSiteToString\n  return object\n}\n\nfunction wrapCallSite(frame: CallSite, state: State) {\n  // provides interface backward compatibility\n  if (state === undefined) state = { nextPosition: null, curPosition: null }\n\n  if (frame.isNative()) {\n    state.curPosition = null\n    return frame\n  }\n\n  // Most call sites will return the source file from getFileName(), but code\n  // passed to eval() ending in \"//# sourceURL=...\" will return the source file\n  // from getScriptNameOrSourceURL() instead\n  const source = frame.getFileName() || frame.getScriptNameOrSourceURL()\n  if (source) {\n    const line = frame.getLineNumber() ?? 0\n    const column = (frame.getColumnNumber() ?? 1) - 1\n\n    const position = mapSourcePosition({\n      name: null,\n      source,\n      line,\n      column,\n    })\n    state.curPosition = position\n    frame = cloneCallSite(frame)\n    const originalFunctionName = frame.getFunctionName\n    frame.getFunctionName = function () {\n      const name = (() => {\n        if (state.nextPosition == null) return originalFunctionName()\n\n        return state.nextPosition.name || originalFunctionName()\n      })()\n      return name === 'eval' && '_vite' in position ? null : name\n    }\n    frame.getFileName = function () {\n      return position.source ?? null\n    }\n    frame.getLineNumber = function () {\n      return position.line\n    }\n    frame.getColumnNumber = function () {\n      return position.column + 1\n    }\n    frame.getScriptNameOrSourceURL = function () {\n      return position.source as string\n    }\n    return frame\n  }\n\n  // Code called using eval() needs special handling\n  let origin = frame.isEval() && frame.getEvalOrigin()\n  if (origin) {\n    origin = mapEvalOrigin(origin)\n    frame = cloneCallSite(frame)\n    frame.getEvalOrigin = function () {\n      return origin || undefined\n    }\n    return frame\n  }\n\n  // If we get here then we were unable to change the source position\n  return frame\n}\n\nfunction prepareStackTrace(error: Error, stack: CallSite[]) {\n  const name = error.name || 'Error'\n  const message = error.message || ''\n  const errorString = `${name}: ${message}`\n\n  const state = { nextPosition: null, curPosition: null }\n  const processedStack = []\n  for (let i = stack.length - 1; i >= 0; i--) {\n    processedStack.push(`\\n    at ${wrapCallSite(stack[i], state)}`)\n    state.nextPosition = state.curPosition\n  }\n  state.curPosition = state.nextPosition = null\n  return errorString + processedStack.reverse().join('')\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"include\": [\"./\", \"../node\", \"../types\"],\n  \"exclude\": [\"../**/__tests__\", \"../**/__tests_dts__\"],\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"stripInternal\": true\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/types.ts",
    "content": "import type { ViteHotContext } from '#types/hot'\nimport type { HMRLogger } from '../shared/hmr'\nimport type {\n  DefineImportMetadata,\n  SSRImportMetadata,\n} from '../shared/ssrTransform'\nimport type {\n  ExternalFetchResult,\n  FetchFunctionOptions,\n  FetchResult,\n  ViteFetchResult,\n} from '../shared/invokeMethods'\nimport type { ModuleRunnerTransport } from '../shared/moduleRunnerTransport'\nimport type { EvaluatedModuleNode, EvaluatedModules } from './evaluatedModules'\nimport type {\n  ssrDynamicImportKey,\n  ssrExportAllKey,\n  ssrExportNameKey,\n  ssrImportKey,\n  ssrImportMetaKey,\n  ssrModuleExportsKey,\n} from './constants'\nimport type { InterceptorOptions } from './sourcemap/interceptor'\n\nexport type { DefineImportMetadata, SSRImportMetadata }\n\nexport interface ModuleRunnerImportMeta {\n  url: string\n  env: ImportMetaEnv\n  hot?: ViteHotContext\n  dirname: string\n  filename: string\n  glob: (...args: any[]) => any\n  resolve(specifier: string, parent?: string): string\n  [key: string]: any\n}\n\nexport interface ModuleRunnerContext {\n  [ssrModuleExportsKey]: Record<string, any>\n  [ssrImportKey]: (id: string, metadata?: DefineImportMetadata) => Promise<any>\n  [ssrDynamicImportKey]: (\n    id: string,\n    options?: ImportCallOptions,\n  ) => Promise<any>\n  [ssrExportAllKey]: (obj: any) => void\n  [ssrExportNameKey]: (name: string, getter: () => unknown) => void\n  [ssrImportMetaKey]: ModuleRunnerImportMeta\n}\n\nexport interface ModuleEvaluator {\n  /**\n   * Number of prefixed lines in the transformed code.\n   */\n  startOffset?: number\n  /**\n   * Run code that was transformed by Vite.\n   * @param context Function context\n   * @param code Transformed code\n   * @param module The module node\n   */\n  runInlinedModule(\n    context: ModuleRunnerContext,\n    code: string,\n    module: Readonly<EvaluatedModuleNode>,\n  ): Promise<any>\n  /**\n   * Run externalized module.\n   * @param file File URL to the external module\n   */\n  runExternalModule(file: string): Promise<any>\n}\n\nexport type ResolvedResult = (ExternalFetchResult | ViteFetchResult) & {\n  url: string\n  id: string\n}\n\nexport type FetchFunction = (\n  id: string,\n  importer?: string,\n  options?: FetchFunctionOptions,\n) => Promise<FetchResult>\n\nexport interface ModuleRunnerHmr {\n  /**\n   * Configure HMR logger.\n   */\n  logger?: false | HMRLogger\n}\n\nexport interface ModuleRunnerOptions {\n  /**\n   * A set of methods to communicate with the server.\n   */\n  transport: ModuleRunnerTransport\n  /**\n   * Configure how source maps are resolved. Prefers `node` if `process.setSourceMapsEnabled` is available.\n   * Otherwise it will use `prepareStackTrace` by default which overrides `Error.prepareStackTrace` method.\n   * You can provide an object to configure how file contents and source maps are resolved for files that were not processed by Vite.\n   */\n  sourcemapInterceptor?:\n    | false\n    | 'node'\n    | 'prepareStackTrace'\n    | InterceptorOptions\n  /**\n   * Disable HMR or configure HMR options.\n   *\n   * @default true\n   */\n  hmr?: boolean | ModuleRunnerHmr\n  /**\n   * Create import.meta object for the module.\n   *\n   * @default createDefaultImportMeta\n   */\n  createImportMeta?: (\n    modulePath: string,\n  ) => ModuleRunnerImportMeta | Promise<ModuleRunnerImportMeta>\n  /**\n   * Custom module cache. If not provided, creates a separate module cache for each ModuleRunner instance.\n   */\n  evaluatedModules?: EvaluatedModules\n}\n\nexport interface ImportMetaEnv {\n  [key: string]: any\n  BASE_URL: string\n  MODE: string\n  DEV: boolean\n  PROD: boolean\n  SSR: boolean\n}\n"
  },
  {
    "path": "packages/vite/src/module-runner/utils.ts",
    "content": "import * as pathe from 'pathe'\nimport { isWindows } from '../shared/utils'\n\nexport const decodeBase64: typeof atob =\n  typeof atob !== 'undefined'\n    ? atob\n    : (str: string) => Buffer.from(str, 'base64').toString('utf-8')\n\nconst CHAR_FORWARD_SLASH = 47\nconst CHAR_BACKWARD_SLASH = 92\n\nconst percentRegEx = /%/g\nconst backslashRegEx = /\\\\/g\nconst newlineRegEx = /\\n/g\nconst carriageReturnRegEx = /\\r/g\nconst tabRegEx = /\\t/g\nconst questionRegex = /\\?/g\nconst hashRegex = /#/g\n\nfunction encodePathChars(filepath: string) {\n  if (filepath.indexOf('%') !== -1)\n    filepath = filepath.replace(percentRegEx, '%25')\n  // In posix, backslash is a valid character in paths:\n  if (!isWindows && filepath.indexOf('\\\\') !== -1)\n    filepath = filepath.replace(backslashRegEx, '%5C')\n  if (filepath.indexOf('\\n') !== -1)\n    filepath = filepath.replace(newlineRegEx, '%0A')\n  if (filepath.indexOf('\\r') !== -1)\n    filepath = filepath.replace(carriageReturnRegEx, '%0D')\n  if (filepath.indexOf('\\t') !== -1)\n    filepath = filepath.replace(tabRegEx, '%09')\n  return filepath\n}\n\nexport const posixDirname: (path: string) => string = pathe.dirname\nexport const posixResolve: (...paths: string[]) => string = pathe.resolve\n\nexport function posixPathToFileHref(posixPath: string): string {\n  let resolved = posixResolve(posixPath)\n  // path.resolve strips trailing slashes so we must add them back\n  const filePathLast = posixPath.charCodeAt(posixPath.length - 1)\n  if (\n    (filePathLast === CHAR_FORWARD_SLASH ||\n      (isWindows && filePathLast === CHAR_BACKWARD_SLASH)) &&\n    resolved[resolved.length - 1] !== '/'\n  )\n    resolved += '/'\n\n  // Call encodePathChars first to avoid encoding % again for ? and #.\n  resolved = encodePathChars(resolved)\n\n  // Question and hash character should be included in pathname.\n  // Therefore, encoding is required to eliminate parsing them in different states.\n  // This is done as an optimization to not creating a URL instance and\n  // later triggering pathname setter, which impacts performance\n  if (resolved.indexOf('?') !== -1)\n    resolved = resolved.replace(questionRegex, '%3F')\n  if (resolved.indexOf('#') !== -1)\n    resolved = resolved.replace(hashRegex, '%23')\n  return new URL(`file://${resolved}`).href\n}\n\nexport function toWindowsPath(path: string): string {\n  return path.replace(/\\//g, '\\\\')\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/__snapshots__/utils.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`generateCodeFrames > end 1`] = `\n\"\n1  |  import foo from './foo'\n   |  ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > end 2`] = `\n\"\n1  |  import foo from './foo'\n   |  ^^^^^^^^^^^^^^^^^^^^^^^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > end 3`] = `\n\"\n1  |  import foo from './foo'\n   |  ^^^^^^^^^^^^^^^^^^^^^^^\n2  |  foo()\n   |  ^^^^^\n\"\n`;\n\nexports[`generateCodeFrames > end 4`] = `\n\"\n1  |  import foo from './foo'\n   |  ^^^^^^^^^^^^^^^^^^^^^^^\n2  |  foo()\n   |  ^^^^^\n\"\n`;\n\nexports[`generateCodeFrames > end 5`] = `\n\"\n1  |  import foo from './foo'\n   |  ^^^^^^^^^^^^^^^^^^^^^^^\n2  |  foo()\n   |  ^^^^^\n\"\n`;\n\nexports[`generateCodeFrames > end 6`] = `\n\"\n1  |  import foo from './foo'\n   |  ^^^^^^^^^^^^^^^^^^^^^^^\n2  |  foo()\n   |  ^^^^^\n\"\n`;\n\nexports[`generateCodeFrames > invalid start > end 1`] = `\n\"\n1  |  import foo from './foo'\n   |    ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > long line (center) 1`] = `\n\"\n1  |  ...aaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccc...\n   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2  |  short line\n3  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n\"\n`;\n\nexports[`generateCodeFrames > long line (end) 1`] = `\n\"\n1  |  ...bbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2  |  short line\n3  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n\"\n`;\n\nexports[`generateCodeFrames > long line (multiline 1) 1`] = `\n\"\n1  |  ...bbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\n   |                                                            ^^^^^^^^^^\n2  |  short line\n   |  ^^^^^^\n3  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n\"\n`;\n\nexports[`generateCodeFrames > long line (multiline 2) 1`] = `\n\"\n1  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n2  |  short line\n   |       ^^^^^\n3  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\"\n`;\n\nexports[`generateCodeFrames > long line (start) 1`] = `\n\"\n1  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2  |  short line\n3  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n\"\n`;\n\nexports[`generateCodeFrames > long line (whole) 1`] = `\n\"\n1  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n   |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n2  |  short line\n3  |  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...\n\"\n`;\n\nexports[`generateCodeFrames > range 1`] = `\n\"\n1  |  import foo from './foo'\n2  |  \n3  |  foo()\n   |  ^\n4  |  // 1\n5  |  // 2\n\"\n`;\n\nexports[`generateCodeFrames > range 2`] = `\n\"\n1  |  import foo from './foo'\n2  |  \n3  |  foo()\n   |  ^^^^^\n4  |  // 1\n   |  ^\n5  |  // 2\n\"\n`;\n\nexports[`generateCodeFrames > start with number 1`] = `\n\"\n1  |  import foo from './foo'\n   |  ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > start with number 2`] = `\n\"\n1  |  import foo from './foo'\n   |  ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > start with number 3`] = `\n\"\n1  |  import foo from './foo'\n   |   ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > start with number 4`] = `\n\"\n1  |  import foo from './foo'\n2  |  foo()\n   |  ^\n\"\n`;\n\nexports[`generateCodeFrames > start with position 1`] = `\n\"\n1  |  import foo from './foo'\n   |  ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > start with position 2`] = `\n\"\n1  |  import foo from './foo'\n   |   ^\n2  |  foo()\n\"\n`;\n\nexports[`generateCodeFrames > start with position 3`] = `\n\"\n1  |  import foo from './foo'\n2  |  foo()\n   |  ^\n\"\n`;\n\nexports[`generateCodeFrames > supports more than 1000 lines 1`] = `\n\"\n1198 |  // 1197\n1199 |  // 1198\n1200 |  // 1199\n     |  ^\n1201 |  // 1200\n1202 |  // 1201\n\"\n`;\n\nexports[`generateCodeFrames > works with CRLF 1`] = `\n\"\n1  |  import foo from './foo'\n2  |  foo()\n   |  ^\n\"\n`;\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/assetSource.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { type DefaultTreeAdapterMap, parseFragment } from 'parse5'\nimport { getNodeAssetAttributes } from '../assetSource'\n\ndescribe('getNodeAssetAttributes', () => {\n  const getNode = (html: string) => {\n    const ast = parseFragment(html, { sourceCodeLocationInfo: true })\n    return ast.childNodes[0] as DefaultTreeAdapterMap['element']\n  }\n\n  test('handles img src', () => {\n    const node = getNode('<img src=\"foo.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(1)\n    expect(attrs[0]).toHaveProperty('type', 'src')\n    expect(attrs[0]).toHaveProperty('key', 'src')\n    expect(attrs[0]).toHaveProperty('value', 'foo.jpg')\n    expect(attrs[0].attributes).toEqual({ src: 'foo.jpg' })\n    expect(attrs[0].location).toHaveProperty('startOffset', 5)\n    expect(attrs[0].location).toHaveProperty('endOffset', 18)\n  })\n\n  test('handles source srcset', () => {\n    const node = getNode('<source srcset=\"foo.jpg 1x, bar.jpg 2x\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(1)\n    expect(attrs[0]).toHaveProperty('type', 'srcset')\n    expect(attrs[0]).toHaveProperty('key', 'srcset')\n    expect(attrs[0]).toHaveProperty('value', 'foo.jpg 1x, bar.jpg 2x')\n    expect(attrs[0].attributes).toEqual({ srcset: 'foo.jpg 1x, bar.jpg 2x' })\n  })\n\n  test('handles video src and poster', () => {\n    const node = getNode('<video src=\"video.mp4\" poster=\"poster.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(2)\n    expect(attrs[0]).toHaveProperty('type', 'src')\n    expect(attrs[0]).toHaveProperty('key', 'src')\n    expect(attrs[0]).toHaveProperty('value', 'video.mp4')\n    expect(attrs[0].attributes).toEqual({\n      src: 'video.mp4',\n      poster: 'poster.jpg',\n    })\n    expect(attrs[1]).toHaveProperty('type', 'src')\n    expect(attrs[1]).toHaveProperty('key', 'poster')\n    expect(attrs[1]).toHaveProperty('value', 'poster.jpg')\n  })\n\n  test('handles link with allowed rel', () => {\n    const node = getNode('<link rel=\"stylesheet\" href=\"style.css\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(1)\n    expect(attrs[0]).toHaveProperty('type', 'src')\n    expect(attrs[0]).toHaveProperty('key', 'href')\n    expect(attrs[0]).toHaveProperty('value', 'style.css')\n    expect(attrs[0].attributes).toEqual({\n      rel: 'stylesheet',\n      href: 'style.css',\n    })\n  })\n\n  test('handles meta with allowed name', () => {\n    const node = getNode('<meta name=\"twitter:image\" content=\"image.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(1)\n    expect(attrs[0]).toHaveProperty('type', 'src')\n    expect(attrs[0]).toHaveProperty('key', 'content')\n    expect(attrs[0]).toHaveProperty('value', 'image.jpg')\n  })\n\n  test('handles meta with allowed property', () => {\n    const node = getNode('<meta property=\"og:image\" content=\"image.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(1)\n    expect(attrs[0]).toHaveProperty('type', 'src')\n    expect(attrs[0]).toHaveProperty('key', 'content')\n    expect(attrs[0]).toHaveProperty('value', 'image.jpg')\n  })\n\n  test('does not handle meta with unknown name', () => {\n    const node = getNode('<meta name=\"unknown\" content=\"image.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(0)\n  })\n\n  test('does not handle meta with unknown property', () => {\n    const node = getNode('<meta property=\"unknown\" content=\"image.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(0)\n  })\n\n  test('does not handle meta with no known properties', () => {\n    const node = getNode('<meta foo=\"bar\" content=\"image.jpg\">')\n    const attrs = getNodeAssetAttributes(node)\n    expect(attrs).toHaveLength(0)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/build.spec.ts",
    "content": "import { basename, resolve } from 'node:path'\nimport { stripVTControlCharacters } from 'node:util'\nimport fsp from 'node:fs/promises'\nimport colors from 'picocolors'\nimport { afterEach, describe, expect, test, vi } from 'vitest'\nimport type {\n  LogLevel,\n  OutputChunk,\n  OutputOptions,\n  RolldownOptions,\n  RolldownOutput,\n  RollupLog,\n} from 'rolldown'\nimport type { LibraryFormats, LibraryOptions } from '../build'\nimport {\n  build,\n  createBuilder,\n  onRollupLog,\n  resolveBuildOutputs,\n  resolveLibFilename,\n} from '../build'\nimport type { Logger } from '../logger'\nimport { createLogger } from '../logger'\nimport { BuildEnvironment, resolveConfig } from '..'\n\nconst dirname = import.meta.dirname\n\ntype FormatsToFileNames = [LibraryFormats, string][]\n\ndescribe('build', () => {\n  test('file hash should change when css changes for dynamic entries', async () => {\n    const buildProject = async (cssColor: string) => {\n      return (await build({\n        root: resolve(dirname, 'packages/build-project'),\n        logLevel: 'silent',\n        build: {\n          write: false,\n        },\n        plugins: [\n          {\n            name: 'test',\n            resolveId(id) {\n              if (\n                id === 'entry.js' ||\n                id === 'subentry.js' ||\n                id === 'foo.css'\n              ) {\n                return '\\0' + id\n              }\n            },\n            load(id) {\n              if (id === '\\0entry.js') {\n                return `window.addEventListener('click', () => { import('subentry.js') });`\n              }\n              if (id === '\\0subentry.js') {\n                return `import 'foo.css'`\n              }\n              if (id === '\\0foo.css') {\n                return `.foo { color: ${cssColor} }`\n              }\n            },\n          },\n        ],\n      })) as RolldownOutput\n    }\n    const result = await Promise.all([\n      buildProject('red'),\n      buildProject('blue'),\n    ])\n    expect(getOutputHashChanges(result[0], result[1])).toMatchInlineSnapshot(`\n      {\n        \"changed\": [\n          \"index\",\n          \"_subentry.css\",\n        ],\n        \"unchanged\": [\n          \"undefined\",\n        ],\n      }\n    `)\n    assertOutputHashContentChange(result[0], result[1])\n  })\n\n  test('file hash should change when pure css chunk changes', async () => {\n    const buildProject = async (cssColor: string) => {\n      return (await build({\n        root: resolve(dirname, 'packages/build-project'),\n        logLevel: 'silent',\n        build: {\n          write: false,\n        },\n        plugins: [\n          {\n            name: 'test',\n            resolveId(id) {\n              if (\n                id === 'entry.js' ||\n                id === 'foo.js' ||\n                id === 'bar.js' ||\n                id === 'baz.js' ||\n                id === 'foo.css' ||\n                id === 'bar.css' ||\n                id === 'baz.css'\n              ) {\n                return '\\0' + id\n              }\n            },\n            load(id) {\n              if (id === '\\0entry.js') {\n                return `\n                  window.addEventListener('click', () => { import('foo.js') });\n                  window.addEventListener('click', () => { import('bar.js') });`\n              }\n              if (id === '\\0foo.js') return `import 'foo.css'; import 'baz.js'`\n              if (id === '\\0bar.js') return `import 'bar.css'; import 'baz.js'`\n              if (id === '\\0baz.js') return `import 'baz.css'`\n              if (id === '\\0foo.css') return `.foo { color: red }`\n              if (id === '\\0bar.css') return `.foo { color: green }`\n              if (id === '\\0baz.css') return `.foo { color: ${cssColor} }`\n            },\n          },\n        ],\n      })) as RolldownOutput\n    }\n    const result = await Promise.all([\n      buildProject('yellow'),\n      buildProject('blue'),\n    ])\n    expect(getOutputHashChanges(result[0], result[1])).toMatchInlineSnapshot(`\n      {\n        \"changed\": [\n          \"index\",\n          \"_bar\",\n          \"_foo\",\n          \"_baz.css\",\n        ],\n        \"unchanged\": [\n          \"_bar.css\",\n          \"_foo.css\",\n          \"undefined\",\n        ],\n      }\n    `)\n    assertOutputHashContentChange(result[0], result[1])\n  })\n\n  test.for([\n    [true, true],\n    [true, false],\n    [false, true],\n    [false, false],\n    ['auto', true],\n    ['auto', false],\n  ] as const)(\n    'large json object files should have tree-shaking (json.stringify: %s, json.namedExports: %s)',\n    async ([stringify, namedExports]) => {\n      const esBundle = (await build({\n        mode: 'development',\n        root: resolve(dirname, 'packages/build-project'),\n        logLevel: 'silent',\n        json: { stringify, namedExports },\n        build: {\n          minify: false,\n          modulePreload: { polyfill: false },\n          write: false,\n        },\n        plugins: [\n          {\n            name: 'test',\n            resolveId(id) {\n              if (\n                id === 'entry.js' ||\n                id === 'object.json' ||\n                id === 'array.json'\n              ) {\n                return '\\0' + id\n              }\n            },\n            load(id) {\n              if (id === '\\0entry.js') {\n                return `\n                  import object from 'object.json';\n                  import array from 'array.json';\n                  console.log();\n                `\n              }\n              if (id === '\\0object.json') {\n                return `\n                  {\"value\": {\"${stringify}_${namedExports}\":\"JSON_OBJ${'_'.repeat(10_000)}\"}}\n                `\n              }\n              if (id === '\\0array.json') {\n                return `\n                  [\"${stringify}_${namedExports}\",\"JSON_ARR${'_'.repeat(10_000)}\"]\n                `\n              }\n            },\n          },\n        ],\n      })) as RolldownOutput\n\n      const foo = esBundle.output.find(\n        (chunk) => chunk.type === 'chunk' && chunk.isEntry,\n      ) as OutputChunk\n      expect(foo.code).not.contains('JSON_ARR')\n      expect(foo.code).not.contains('JSON_OBJ')\n    },\n  )\n\n  test('external modules should not be hoisted in library build', async () => {\n    const [esBundle] = (await build({\n      logLevel: 'silent',\n      build: {\n        lib: {\n          entry: ['foo.js', 'bar.js'],\n          formats: ['es'],\n        },\n        rollupOptions: {\n          external: 'external',\n        },\n        write: false,\n      },\n      plugins: [\n        {\n          name: 'test',\n          resolveId(id) {\n            const name = basename(id)\n            if (name === 'foo.js' || name === 'bar.js') {\n              return name\n            }\n          },\n          load(id) {\n            if (id === 'foo.js') {\n              return `\n                  import bar from 'bar.js'\n                  export default bar()\n                `\n            }\n            if (id === 'bar.js') {\n              return `\n                  import ext from 'external';\n                  export default ext();`\n            }\n          },\n        },\n      ],\n    })) as RolldownOutput[]\n\n    const foo = esBundle.output.find(\n      (chunk) => chunk.fileName === 'foo.js',\n    ) as OutputChunk\n    expect(foo.code).not.contains('import \"external\"')\n  })\n})\n\nconst baseLibOptions: LibraryOptions = {\n  fileName: 'my-lib',\n  entry: 'mylib.js',\n}\n\ndescribe('resolveBuildOutputs', () => {\n  test('resolves outputs correctly', () => {\n    const logger = createLogger()\n    const libOptions: LibraryOptions = { ...baseLibOptions }\n    const outputs: OutputOptions[] = [{ format: 'es' }]\n    const resolvedOutputs = resolveBuildOutputs(outputs, libOptions, logger)\n\n    expect(resolvedOutputs).toEqual([\n      {\n        format: 'es',\n      },\n    ])\n  })\n\n  test('resolves outputs from lib options', () => {\n    const logger = createLogger()\n    const libOptions: LibraryOptions = { ...baseLibOptions, name: 'lib' }\n    const resolvedOutputs = resolveBuildOutputs(void 0, libOptions, logger)\n\n    expect(resolvedOutputs).toEqual([\n      {\n        format: 'es',\n      },\n      {\n        format: 'umd',\n      },\n    ])\n  })\n\n  test('does not change outputs when lib options are missing', () => {\n    const logger = createLogger()\n    const outputs: OutputOptions[] = [{ format: 'es' }]\n    const resolvedOutputs = resolveBuildOutputs(outputs, false, logger)\n\n    expect(resolvedOutputs).toEqual(outputs)\n  })\n\n  test('logs a warning when outputs is an array and formats are specified', () => {\n    const logger = createLogger()\n    const loggerSpy = vi.spyOn(logger, 'warn').mockImplementation(() => {})\n    const libOptions: LibraryOptions = {\n      ...baseLibOptions,\n      formats: ['iife'],\n    }\n    const outputs: OutputOptions[] = [{ format: 'es' }]\n\n    resolveBuildOutputs(outputs, libOptions, logger)\n\n    expect(loggerSpy).toHaveBeenCalledWith(\n      expect.stringContaining('\"build.lib.formats\" will be ignored because'),\n    )\n  })\n\n  test('throws an error when lib.name is missing on iife format', () => {\n    const logger = createLogger()\n    const libOptions: LibraryOptions = {\n      ...baseLibOptions,\n      formats: ['iife'],\n    }\n    const resolveBuild = () => resolveBuildOutputs(void 0, libOptions, logger)\n\n    expect(resolveBuild).toThrowError(/Option \"build\\.lib\\.name\" is required/)\n  })\n\n  test('throws an error when lib.name is missing on umd format', () => {\n    const logger = createLogger()\n    const libOptions: LibraryOptions = { ...baseLibOptions, formats: ['umd'] }\n    const resolveBuild = () => resolveBuildOutputs(void 0, libOptions, logger)\n\n    expect(resolveBuild).toThrowError(/Option \"build\\.lib\\.name\" is required/)\n  })\n\n  test('throws an error when output.name is missing on iife format', () => {\n    const logger = createLogger()\n    const libOptions: LibraryOptions = { ...baseLibOptions }\n    const outputs: OutputOptions[] = [{ format: 'iife' }]\n    const resolveBuild = () => resolveBuildOutputs(outputs, libOptions, logger)\n\n    expect(resolveBuild).toThrowError(\n      /Entries in \"build\\.rollupOptions\\.output\" must specify \"name\"/,\n    )\n  })\n\n  test('throws an error when output.name is missing on umd format', () => {\n    const logger = createLogger()\n    const libOptions: LibraryOptions = { ...baseLibOptions }\n    const outputs: OutputOptions[] = [{ format: 'umd' }]\n    const resolveBuild = () => resolveBuildOutputs(outputs, libOptions, logger)\n\n    expect(resolveBuild).toThrowError(\n      /Entries in \"build\\.rollupOptions\\.output\" must specify \"name\"/,\n    )\n  })\n})\n\ndescribe('resolveLibFilename', () => {\n  test('custom filename function', () => {\n    const filename = resolveLibFilename(\n      {\n        fileName: (format) => `custom-filename-function.${format}.js`,\n        entry: 'mylib.js',\n      },\n      'es',\n      'myLib',\n      resolve(dirname, 'packages/name'),\n    )\n\n    expect(filename).toBe('custom-filename-function.es.js')\n  })\n\n  test('custom filename string', () => {\n    const filename = resolveLibFilename(\n      {\n        fileName: 'custom-filename',\n        entry: 'mylib.js',\n      },\n      'es',\n      'myLib',\n      resolve(dirname, 'packages/name'),\n    )\n\n    expect(filename).toBe('custom-filename.mjs')\n  })\n\n  test('package name as filename', () => {\n    const filename = resolveLibFilename(\n      {\n        entry: 'mylib.js',\n      },\n      'es',\n      'myLib',\n      resolve(dirname, 'packages/name'),\n    )\n\n    expect(filename).toBe('mylib.mjs')\n  })\n\n  test('custom filename and no package name', () => {\n    const filename = resolveLibFilename(\n      {\n        fileName: 'custom-filename',\n        entry: 'mylib.js',\n      },\n      'es',\n      'myLib',\n      resolve(dirname, 'packages/noname'),\n    )\n\n    expect(filename).toBe('custom-filename.mjs')\n  })\n\n  test('missing filename', () => {\n    const filename = resolveLibFilename(\n      {\n        entry: 'mylib.js',\n      },\n      'es',\n      'myLib',\n      resolve(dirname, 'packages/noname'),\n    )\n    expect(filename).toBe('named-testing-package.mjs')\n  })\n\n  test('commonjs package extensions', () => {\n    const formatsToFilenames: FormatsToFileNames = [\n      ['es', 'my-lib.mjs'],\n      ['umd', 'my-lib.umd.js'],\n      ['cjs', 'my-lib.js'],\n      ['iife', 'my-lib.iife.js'],\n    ]\n\n    for (const [format, expectedFilename] of formatsToFilenames) {\n      const filename = resolveLibFilename(\n        baseLibOptions,\n        format,\n        'myLib',\n        resolve(dirname, 'packages/noname'),\n      )\n\n      expect(filename).toBe(expectedFilename)\n    }\n  })\n\n  test('module package extensions', () => {\n    const formatsToFilenames: FormatsToFileNames = [\n      ['es', 'my-lib.js'],\n      ['umd', 'my-lib.umd.cjs'],\n      ['cjs', 'my-lib.cjs'],\n      ['iife', 'my-lib.iife.js'],\n    ]\n\n    for (const [format, expectedFilename] of formatsToFilenames) {\n      const filename = resolveLibFilename(\n        baseLibOptions,\n        format,\n        'myLib',\n        resolve(dirname, 'packages/module'),\n      )\n\n      expect(expectedFilename).toBe(filename)\n    }\n  })\n\n  test('multiple entries with aliases', () => {\n    const libOptions: LibraryOptions = {\n      entry: {\n        entryA: 'entryA.js',\n        entryB: 'entryB.js',\n      },\n    }\n\n    const [fileName1, fileName2] = ['entryA', 'entryB'].map((entryAlias) =>\n      resolveLibFilename(\n        libOptions,\n        'es',\n        entryAlias,\n        resolve(dirname, 'packages/name'),\n      ),\n    )\n\n    expect(fileName1).toBe('entryA.mjs')\n    expect(fileName2).toBe('entryB.mjs')\n  })\n\n  test('multiple entries with aliases: custom filename function', () => {\n    const libOptions: LibraryOptions = {\n      entry: {\n        entryA: 'entryA.js',\n        entryB: 'entryB.js',\n      },\n      fileName: (format, entryAlias) =>\n        `custom-filename-function.${entryAlias}.${format}.js`,\n    }\n\n    const [fileName1, fileName2] = ['entryA', 'entryB'].map((entryAlias) =>\n      resolveLibFilename(\n        libOptions,\n        'es',\n        entryAlias,\n        resolve(dirname, 'packages/name'),\n      ),\n    )\n\n    expect(fileName1).toBe('custom-filename-function.entryA.es.js')\n    expect(fileName2).toBe('custom-filename-function.entryB.es.js')\n  })\n\n  test('multiple entries with aliases: custom filename string', () => {\n    const libOptions: LibraryOptions = {\n      entry: {\n        entryA: 'entryA.js',\n        entryB: 'entryB.js',\n      },\n      fileName: 'custom-filename',\n    }\n\n    const [fileName1, fileName2] = ['entryA', 'entryB'].map((entryAlias) =>\n      resolveLibFilename(\n        libOptions,\n        'es',\n        entryAlias,\n        resolve(dirname, 'packages/name'),\n      ),\n    )\n\n    expect(fileName1).toBe('custom-filename.mjs')\n    expect(fileName2).toBe('custom-filename.mjs')\n  })\n\n  test('multiple entries as array', () => {\n    const libOptions: LibraryOptions = {\n      entry: ['entryA.js', 'entryB.js'],\n    }\n\n    const [fileName1, fileName2] = ['entryA', 'entryB'].map((entryAlias) =>\n      resolveLibFilename(\n        libOptions,\n        'es',\n        entryAlias,\n        resolve(dirname, 'packages/name'),\n      ),\n    )\n\n    expect(fileName1).toBe('entryA.mjs')\n    expect(fileName2).toBe('entryB.mjs')\n  })\n\n  test('multiple entries as array: custom filename function', () => {\n    const libOptions: LibraryOptions = {\n      entry: ['entryA.js', 'entryB.js'],\n      fileName: (format, entryAlias) =>\n        `custom-filename-function.${entryAlias}.${format}.js`,\n    }\n\n    const [fileName1, fileName2] = ['entryA', 'entryB'].map((entryAlias) =>\n      resolveLibFilename(\n        libOptions,\n        'es',\n        entryAlias,\n        resolve(dirname, 'packages/name'),\n      ),\n    )\n\n    expect(fileName1).toBe('custom-filename-function.entryA.es.js')\n    expect(fileName2).toBe('custom-filename-function.entryB.es.js')\n  })\n\n  test('multiple entries as array: custom filename string', () => {\n    const libOptions: LibraryOptions = {\n      entry: ['entryA.js', 'entryB.js'],\n      fileName: 'custom-filename',\n    }\n\n    const [fileName1, fileName2] = ['entryA', 'entryB'].map((entryAlias) =>\n      resolveLibFilename(\n        libOptions,\n        'es',\n        entryAlias,\n        resolve(dirname, 'packages/name'),\n      ),\n    )\n\n    expect(fileName1).toBe('custom-filename.mjs')\n    expect(fileName2).toBe('custom-filename.mjs')\n  })\n})\n\ndescribe('resolveBuildOutputs', () => {\n  test('default format: one entry', () => {\n    const libOptions: LibraryOptions = {\n      entry: 'entryA.js',\n      name: 'entryA',\n    }\n\n    expect(resolveBuildOutputs(undefined, libOptions, {} as Logger)).toEqual([\n      { format: 'es' },\n      { format: 'umd' },\n    ])\n    expect(\n      resolveBuildOutputs({ name: 'A' }, libOptions, {} as Logger),\n    ).toEqual([\n      { format: 'es', name: 'A' },\n      { format: 'umd', name: 'A' },\n    ])\n    expect(\n      resolveBuildOutputs([{ name: 'A' }], libOptions, {} as Logger),\n    ).toEqual([{ name: 'A' }])\n  })\n\n  test('default format: multiple entries', () => {\n    const libOptions: LibraryOptions = {\n      entry: ['entryA.js', 'entryB.js'],\n    }\n\n    expect(resolveBuildOutputs(undefined, libOptions, {} as Logger)).toEqual([\n      { format: 'es' },\n      { format: 'cjs' },\n    ])\n    expect(\n      resolveBuildOutputs({ name: 'A' }, libOptions, {} as Logger),\n    ).toEqual([\n      { format: 'es', name: 'A' },\n      { format: 'cjs', name: 'A' },\n    ])\n    expect(\n      resolveBuildOutputs([{ name: 'A' }], libOptions, {} as Logger),\n    ).toEqual([{ name: 'A' }])\n  })\n\n  test('umd or iife: should not support multiple entries', () => {\n    ;['umd', 'iife'].forEach((format) => {\n      expect(() =>\n        resolveBuildOutputs(\n          undefined,\n          {\n            entry: ['entryA.js', 'entryB.js'],\n            formats: [format as LibraryFormats],\n          },\n          {} as Logger,\n        ),\n      ).toThrow(\n        `Multiple entry points are not supported when output formats include \"umd\" or \"iife\".`,\n      )\n    })\n  })\n\n  test('umd or iife: should define build.lib.name', () => {\n    ;['umd', 'iife'].forEach((format) => {\n      expect(() =>\n        resolveBuildOutputs(\n          undefined,\n          {\n            entry: 'entryA.js',\n            formats: [format as LibraryFormats],\n          },\n          {} as Logger,\n        ),\n      ).toThrow(\n        `Option \"build.lib.name\" is required when output formats include \"umd\" or \"iife\".`,\n      )\n    })\n  })\n\n  test('array outputs: should ignore build.lib.formats', () => {\n    const log = { warn: vi.fn() } as unknown as Logger\n    expect(\n      resolveBuildOutputs(\n        [{ name: 'A' }],\n        {\n          entry: 'entryA.js',\n          formats: ['es'],\n        },\n        log,\n      ),\n    ).toEqual([{ name: 'A' }])\n    expect(log.warn).toHaveBeenLastCalledWith(\n      colors.yellow(\n        `\"build.lib.formats\" will be ignored because \"build.rollupOptions.output\" is already an array format.`,\n      ),\n    )\n  })\n\n  test('ssrEmitAssets', async () => {\n    const result = await build({\n      root: resolve(dirname, 'fixtures/emit-assets'),\n      logLevel: 'silent',\n      build: {\n        ssr: true,\n        ssrEmitAssets: true,\n        rollupOptions: {\n          input: {\n            index: '/entry',\n          },\n        },\n      },\n    })\n    expect(result).toMatchObject({\n      output: [\n        {\n          fileName: 'index.mjs',\n        },\n        {\n          fileName: expect.stringMatching(/assets\\/index-[-\\w]{8}\\.css/),\n        },\n      ],\n    })\n  })\n\n  test('emitAssets', async () => {\n    const builder = await createBuilder({\n      root: resolve(dirname, 'fixtures/emit-assets'),\n      logLevel: 'warn',\n      environments: {\n        ssr: {\n          build: {\n            ssr: true,\n            emitAssets: true,\n            rollupOptions: {\n              input: {\n                index: '/entry',\n              },\n            },\n          },\n        },\n      },\n    })\n    const result = await builder.build(builder.environments.ssr)\n    expect(result).toMatchObject({\n      output: [\n        {\n          fileName: 'index.mjs',\n        },\n        {\n          fileName: expect.stringMatching(/assets\\/index-[-\\w]{8}\\.css/),\n        },\n      ],\n    })\n  })\n\n  test('ssr builtin', async () => {\n    const builder = await createBuilder({\n      root: resolve(dirname, 'fixtures/dynamic-import'),\n      logLevel: 'warn',\n      environments: {\n        ssr: {\n          build: {\n            ssr: true,\n            rollupOptions: {\n              input: {\n                index: '/entry',\n              },\n            },\n          },\n        },\n      },\n    })\n    const result = await builder.build(builder.environments.ssr)\n    expect((result as RolldownOutput).output[0].code).not.toContain('preload')\n  })\n\n  test('ssr custom', async () => {\n    const builder = await createBuilder({\n      root: resolve(dirname, 'fixtures/dynamic-import'),\n      logLevel: 'warn',\n      environments: {\n        custom: {\n          build: {\n            ssr: true,\n            rollupOptions: {\n              input: {\n                index: '/entry',\n              },\n            },\n          },\n        },\n      },\n    })\n    const result = await builder.build(builder.environments.custom)\n    expect((result as RolldownOutput).output[0].code).not.toContain('preload')\n  })\n})\n\ntest('default sharedConfigBuild true on build api', async () => {\n  let counter = 0\n  await build({\n    root: resolve(dirname, 'fixtures/emit-assets'),\n    logLevel: 'warn',\n    build: {\n      ssr: true,\n      rollupOptions: {\n        input: {\n          index: '/entry',\n        },\n      },\n    },\n    plugins: [\n      {\n        name: 'test-plugin',\n        config() {\n          counter++\n        },\n      },\n    ],\n  })\n  expect(counter).toBe(1)\n})\n\ntest.for([true, false])(\n  'minify per environment (builder.sharedPlugins: %s)',\n  async (sharedPlugins) => {\n    const root = resolve(dirname, 'fixtures/shared-plugins/minify')\n    const builder = await createBuilder({\n      root,\n      logLevel: 'warn',\n      environments: {\n        client: {\n          build: {\n            outDir: './dist/client',\n            rollupOptions: {\n              input: '/entry.js',\n            },\n          },\n        },\n        ssr: {\n          build: {\n            outDir: './dist/server',\n            rollupOptions: {\n              input: '/entry.js',\n            },\n          },\n        },\n        custom1: {\n          build: {\n            minify: true,\n            outDir: './dist/custom1',\n            rollupOptions: {\n              input: '/entry.js',\n            },\n          },\n        },\n        custom2: {\n          build: {\n            minify: false,\n            outDir: './dist/custom2',\n            rollupOptions: {\n              input: '/entry.js',\n            },\n          },\n        },\n      },\n      builder: {\n        sharedPlugins,\n      },\n    })\n    const client = await builder.build(builder.environments.client)\n    const ssr = await builder.build(builder.environments.ssr)\n    const custom1 = await builder.build(builder.environments.custom1)\n    const custom2 = await builder.build(builder.environments.custom2)\n    expect(\n      ([client, ssr, custom1, custom2] as RolldownOutput[]).map(\n        (o) => o.output[0].code.split('\\n').length,\n      ),\n    ).toEqual([1, 8, 1, 8])\n  },\n)\n\ntest('sharedConfigBuild and emitAssets', async () => {\n  const root = resolve(dirname, 'fixtures/shared-config-build/emitAssets')\n  const builder = await createBuilder({\n    root,\n    logLevel: 'warn',\n    configFile: false,\n    environments: {\n      client: {\n        build: {\n          outDir: './dist/client',\n          emitAssets: true,\n          rollupOptions: {\n            input: '/entry.js',\n          },\n        },\n      },\n      ssr: {\n        build: {\n          outDir: './dist/ssr',\n          emitAssets: true,\n          rollupOptions: {\n            input: '/entry.js',\n          },\n        },\n      },\n      custom: {\n        build: {\n          outDir: './dist/custom',\n          emitAssets: true,\n          rollupOptions: {\n            input: '/entry.js',\n          },\n        },\n      },\n    },\n    builder: {\n      sharedConfigBuild: true,\n    },\n  })\n\n  expect(\n    ['client', 'ssr', 'custom'].map(\n      (name) => builder.environments[name].config.build.emitAssets,\n    ),\n  ).toEqual([true, true, true])\n\n  await builder.buildApp()\n\n  expect(\n    await Promise.all(\n      ['client', 'ssr', 'custom'].map((name) =>\n        fsp.readdir(\n          resolve(\n            root,\n            builder.environments[name].config.build.outDir,\n            'assets',\n          ),\n        ),\n      ),\n    ),\n  ).toEqual([\n    expect.arrayContaining([expect.stringMatching(/\\.css$/)]),\n    expect.arrayContaining([expect.stringMatching(/\\.css$/)]),\n    expect.arrayContaining([expect.stringMatching(/\\.css$/)]),\n  ])\n})\n\ntest.skip('adjust worker build error for worker.format', async () => {\n  try {\n    await build({\n      root: resolve(dirname, 'fixtures/worker-dynamic'),\n      build: {\n        rollupOptions: {\n          input: {\n            index: '/main.js',\n          },\n        },\n      },\n      logLevel: 'silent',\n    })\n  } catch (e) {\n    expect(e.message).toContain('worker.format')\n    expect(e.message).not.toContain('output.format')\n    return\n  }\n  expect.unreachable()\n})\n\ndescribe('onRollupLog', () => {\n  const pluginName = 'rollup-plugin-test'\n  const msgInfo = 'This is the INFO message.'\n  const msgWarn = 'This is the WARN message.'\n  const buildProject = async (\n    level: LogLevel | 'error',\n    message: string | RollupLog,\n    logger: Logger,\n    options?: Pick<RolldownOptions, 'onLog' | 'onwarn'>,\n  ) => {\n    await build({\n      root: resolve(dirname, 'packages/build-project'),\n      logLevel: 'info',\n      build: {\n        write: false,\n        rollupOptions: {\n          ...options,\n          logLevel: 'debug',\n        },\n      },\n      customLogger: logger,\n      plugins: [\n        {\n          name: pluginName,\n          resolveId(id) {\n            this[level](message)\n            if (id === 'entry.js') {\n              return '\\0' + id\n            }\n          },\n          load(id) {\n            if (id === '\\0entry.js') {\n              return `export default \"This is test module\";`\n            }\n          },\n        },\n      ],\n    })\n  }\n\n  const callOnRollupLog = async (\n    logger: Logger,\n    level: LogLevel,\n    log: RollupLog,\n  ) => {\n    const config = await resolveConfig(\n      { customLogger: logger },\n      'build',\n      'production',\n      'production',\n    )\n    const buildEnvironment = new BuildEnvironment('client', config)\n    onRollupLog(level, log, buildEnvironment)\n  }\n\n  afterEach(() => {\n    vi.restoreAllMocks()\n  })\n\n  test('Rollup logs of info should be handled by vite', async () => {\n    const logger = createLogger()\n    const loggerSpy = vi.spyOn(logger, 'info').mockImplementation(() => {})\n\n    await buildProject('info', msgInfo, logger)\n    const logs = loggerSpy.mock.calls.map((args) =>\n      stripVTControlCharacters(args[0]),\n    )\n    expect(logs).contain(`[plugin ${pluginName}] ${msgInfo}`)\n  })\n\n  test('Rollup logs of warn should be handled by vite', async () => {\n    const logger = createLogger('silent')\n    const loggerSpy = vi.spyOn(logger, 'warn').mockImplementation(() => {})\n\n    await buildProject('warn', msgWarn, logger)\n    const logs = loggerSpy.mock.calls.map((args) =>\n      stripVTControlCharacters(args[0]),\n    )\n    expect(logs).contain(`[plugin ${pluginName}] ${msgWarn}`)\n  })\n\n  test('onLog passed by user is called', async () => {\n    const logger = createLogger('silent')\n\n    const onLogInfo = vi.fn((_log: RollupLog) => {})\n    await buildProject('info', msgInfo, logger, {\n      onLog(level, log) {\n        if (level === 'info') {\n          onLogInfo(log)\n        }\n      },\n    })\n    expect(onLogInfo).toBeCalledWith(\n      expect.objectContaining({ message: msgInfo, plugin: pluginName }),\n    )\n  })\n\n  test('onwarn passed by user is called', async () => {\n    const logger = createLogger('silent')\n\n    const onWarn = vi.fn((_log: RollupLog) => {})\n    await buildProject('warn', msgWarn, logger, {\n      onwarn(warning) {\n        onWarn(warning)\n      },\n    })\n    expect(onWarn).toBeCalledWith(\n      expect.objectContaining({ message: msgWarn, plugin: pluginName }),\n    )\n  })\n\n  test('should throw error when warning contains UNRESOLVED_IMPORT', async () => {\n    const logger = createLogger()\n    await expect(() =>\n      callOnRollupLog(logger, 'warn', {\n        code: 'UNRESOLVED_IMPORT',\n        message: 'test',\n      }),\n    ).rejects.toThrowError(/Rolldown failed to resolve import/)\n  })\n\n  test.each([[`Unsupported expression`], [`statically analyzed`]])(\n    'should ignore dynamic import warnings (%s)',\n    async (message: string) => {\n      const logger = createLogger()\n      const loggerSpy = vi.spyOn(logger, 'warn').mockImplementation(() => {})\n\n      await callOnRollupLog(logger, 'warn', {\n        code: 'PLUGIN_WARNING',\n        message: message,\n        plugin: 'rollup-plugin-dynamic-import-variables',\n      })\n      expect(loggerSpy).toBeCalledTimes(0)\n    },\n  )\n\n  test.each([[`CIRCULAR_DEPENDENCY`], [`THIS_IS_UNDEFINED`]])(\n    'should ignore some warnings (%s)',\n    async (code: string) => {\n      const logger = createLogger()\n      const loggerSpy = vi.spyOn(logger, 'warn').mockImplementation(() => {})\n\n      await callOnRollupLog(logger, 'warn', {\n        code: code,\n        message: 'test message',\n        plugin: pluginName,\n      })\n      expect(loggerSpy).toBeCalledTimes(0)\n    },\n  )\n})\n\ntest('watch rebuild manifest', async (ctx) => {\n  // this doesn't actually test watch rebuild\n  // but it simulates something similar by running two builds for the same environment\n  const root = resolve(dirname, 'fixtures/watch-rebuild-manifest')\n  const builder = await createBuilder({\n    root,\n    logLevel: 'error',\n    environments: {\n      client: {\n        build: {\n          rollupOptions: {\n            input: '/entry.js',\n          },\n        },\n      },\n    },\n    build: {\n      manifest: true,\n    },\n  })\n\n  function getManifestKeys(output: RolldownOutput) {\n    return Object.keys(\n      JSON.parse(\n        (output.output.find((o) => o.fileName === '.vite/manifest.json') as any)\n          .source,\n      ),\n    )\n  }\n\n  const result = await builder.build(builder.environments.client)\n  expect(getManifestKeys(result as RolldownOutput)).toMatchInlineSnapshot(`\n    [\n      \"dep.js\",\n      \"entry.js\",\n    ]\n  `)\n\n  const entry = resolve(root, 'entry.js')\n  const content = await fsp.readFile(entry, 'utf-8')\n  await fsp.writeFile(\n    entry,\n    content.replace(`import('./dep.js')`, `'dep.js removed'`),\n  )\n  ctx.onTestFinished(async () => {\n    await fsp.writeFile(entry, content)\n  })\n\n  const result2 = await builder.build(builder.environments.client)\n  expect(getManifestKeys(result2 as RolldownOutput)).toMatchInlineSnapshot(`\n    [\n      \"entry.js\",\n    ]\n  `)\n})\n\n/**\n * for each chunks in output1, if there's a chunk in output2 with the same fileName,\n * ensure that the chunk code is the same. if not, the chunk hash should have changed.\n */\nfunction assertOutputHashContentChange(\n  output1: RolldownOutput,\n  output2: RolldownOutput,\n) {\n  for (const chunk of output1.output) {\n    if (chunk.type === 'chunk') {\n      const chunk2 = output2.output.find(\n        (c) => c.type === 'chunk' && c.fileName === chunk.fileName,\n      ) as OutputChunk | undefined\n      if (chunk2) {\n        expect(\n          chunk.code,\n          `the ${chunk.fileName} chunk has the same hash but different contents between builds`,\n        ).toEqual(chunk2.code)\n      }\n    }\n  }\n}\n\nfunction getOutputHashChanges(\n  output1: RolldownOutput,\n  output2: RolldownOutput,\n) {\n  const map1 = Object.fromEntries(\n    output1.output.map((o) => [o.name, o.fileName]),\n  )\n  const map2 = Object.fromEntries(\n    output2.output.map((o) => [o.name, o.fileName]),\n  )\n  const names = Object.keys(map1).filter(Boolean)\n  return {\n    changed: names.filter((name) => map1[name] !== map2[name]),\n    unchanged: names.filter((name) => map1[name] === map2[name]),\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/config.spec.ts",
    "content": "import http from 'node:http'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport { afterEach, describe, expect, test, vi } from 'vitest'\nimport type { InlineConfig, PluginOption } from '..'\nimport type { UserConfig, UserConfigExport } from '../config'\nimport { defineConfig, loadConfigFromFile, resolveConfig } from '../config'\nimport { resolveEnvPrefix } from '../env'\nimport { mergeConfig } from '../utils'\nimport { createLogger } from '../logger'\n\ndescribe('mergeConfig', () => {\n  test('handles configs with different alias schemas', () => {\n    const baseConfig = defineConfig({\n      resolve: {\n        alias: [\n          {\n            find: 'foo',\n            replacement: 'foo-value',\n          },\n        ],\n      },\n    })\n\n    const newConfig = defineConfig({\n      resolve: {\n        alias: {\n          bar: 'bar-value',\n          baz: 'baz-value',\n        },\n      },\n    })\n\n    const mergedConfig: UserConfigExport = {\n      resolve: {\n        alias: [\n          {\n            find: 'bar',\n            replacement: 'bar-value',\n          },\n          {\n            find: 'baz',\n            replacement: 'baz-value',\n          },\n          {\n            find: 'foo',\n            replacement: 'foo-value',\n          },\n        ],\n      },\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('keep object alias schema', () => {\n    const baseConfig = {\n      resolve: {\n        alias: {\n          bar: 'bar-value',\n          baz: 'baz-value',\n        },\n      },\n    }\n\n    const newConfig = {\n      resolve: {\n        alias: {\n          bar: 'bar-value-2',\n          foo: 'foo-value',\n        },\n      },\n    }\n\n    const mergedConfig = {\n      resolve: {\n        alias: {\n          bar: 'bar-value-2',\n          baz: 'baz-value',\n          foo: 'foo-value',\n        },\n      },\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('handles arrays', () => {\n    const baseConfig: UserConfigExport = {\n      envPrefix: 'string1',\n    }\n\n    const newConfig: UserConfigExport = {\n      envPrefix: ['string2', 'string3'],\n    }\n\n    const mergedConfig: UserConfigExport = {\n      envPrefix: ['string1', 'string2', 'string3'],\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('handles assetsInclude', () => {\n    const baseConfig: UserConfigExport = {\n      assetsInclude: 'some-string',\n    }\n\n    const newConfig: UserConfigExport = {\n      assetsInclude: ['some-other-string', /regexp?/],\n    }\n\n    const mergedConfig: UserConfigExport = {\n      assetsInclude: ['some-string', 'some-other-string', /regexp?/],\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('not handles alias not under `resolve`', () => {\n    const baseConfig = {\n      custom: {\n        alias: {\n          bar: 'bar-value',\n          baz: 'baz-value',\n        },\n      },\n    }\n\n    const newConfig = {\n      custom: {\n        alias: {\n          bar: 'bar-value-2',\n          foo: 'foo-value',\n        },\n      },\n    }\n\n    const mergedConfig = {\n      custom: {\n        alias: {\n          bar: 'bar-value-2',\n          baz: 'baz-value',\n          foo: 'foo-value',\n        },\n      },\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('merge array correctly', () => {\n    const baseConfig = {\n      foo: null,\n    }\n\n    const newConfig = {\n      foo: ['bar'],\n    }\n\n    const mergedConfig = {\n      foo: ['bar'],\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('handles ssr.noExternal', () => {\n    const baseConfig: UserConfig = {\n      ssr: {\n        noExternal: true,\n        external: true,\n      },\n    }\n\n    const newConfig: UserConfig = {\n      ssr: {\n        noExternal: ['foo'],\n        external: ['bar'],\n      },\n    }\n\n    const mergedConfig: UserConfig = {\n      ssr: {\n        noExternal: true,\n        external: true,\n      },\n    }\n\n    // merging either ways, `ssr.noExternal: true` should take highest priority\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n    expect(mergeConfig(newConfig, baseConfig)).toEqual(mergedConfig)\n  })\n\n  test('handles environments.*.resolve.noExternal', () => {\n    const baseConfig = {\n      environments: {\n        ssr: {\n          resolve: {\n            noExternal: true,\n          },\n        },\n      },\n    }\n\n    const newConfig = {\n      environments: {\n        ssr: {\n          resolve: {\n            noExternal: ['foo'],\n          },\n        },\n      },\n    }\n\n    const mergedConfig = {\n      environments: {\n        ssr: {\n          resolve: {\n            noExternal: true,\n          },\n        },\n      },\n    }\n\n    // merging either ways, `resolve.noExternal: true` should take highest priority\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n    expect(mergeConfig(newConfig, baseConfig)).toEqual(mergedConfig)\n  })\n\n  test('merge ssr.noExternal and environments.ssr.resolve.noExternal', async () => {\n    const oldTrue = await resolveConfig(\n      {\n        ssr: {\n          noExternal: true,\n        },\n        environments: {\n          ssr: {\n            resolve: {\n              noExternal: ['dep'],\n            },\n          },\n        },\n      },\n      'serve',\n    )\n    expect(oldTrue.environments.ssr.resolve.noExternal).toEqual(true)\n\n    const newTrue = await resolveConfig(\n      {\n        ssr: {\n          noExternal: ['dep'],\n        },\n        environments: {\n          ssr: {\n            resolve: {\n              noExternal: true,\n            },\n          },\n        },\n      },\n      'serve',\n    )\n    expect(newTrue.environments.ssr.resolve.noExternal).toEqual(true)\n  })\n\n  test('handles server.hmr.server', () => {\n    const httpServer = http.createServer()\n\n    const baseConfig = { server: { hmr: { server: httpServer } } }\n    const newConfig = { server: { hmr: { server: httpServer } } }\n\n    const mergedConfig = mergeConfig(baseConfig, newConfig)\n\n    // Server instance should not be recreated\n    expect(mergedConfig.server.hmr.server).toBe(httpServer)\n  })\n\n  test('handles server.allowedHosts', () => {\n    const baseConfig = {\n      server: { allowedHosts: ['example.com'] },\n    }\n\n    const newConfig = {\n      server: { allowedHosts: true },\n    }\n\n    const mergedConfig = {\n      server: { allowedHosts: true },\n    }\n\n    expect(mergeConfig(baseConfig, newConfig)).toEqual(mergedConfig)\n  })\n\n  test('throws error with functions', () => {\n    const baseConfig = defineConfig(() => ({ base: 'base' }))\n    const newConfig = defineConfig(() => ({ base: 'new' }))\n\n    expect(() =>\n      mergeConfig(\n        // @ts-expect-error TypeScript shouldn't give you to pass a function as argument\n        baseConfig,\n        newConfig,\n      ),\n    ).toThrowError('Cannot merge config in form of callback')\n\n    expect(() =>\n      mergeConfig(\n        {},\n        // @ts-expect-error TypeScript shouldn't give you to pass a function as argument\n        newConfig,\n      ),\n    ).toThrowError('Cannot merge config in form of callback')\n  })\n\n  test('handles `rollupOptions`', () => {\n    const baseConfig = defineConfig({\n      build: {\n        rollupOptions: {\n          treeshake: false,\n        },\n      },\n      worker: {\n        rollupOptions: {\n          treeshake: false,\n        },\n      },\n      optimizeDeps: {\n        rollupOptions: {\n          treeshake: false,\n        },\n      },\n      ssr: {\n        optimizeDeps: {\n          rollupOptions: {\n            treeshake: false,\n          },\n        },\n      },\n    })\n\n    const newConfig = defineConfig({\n      build: {\n        rollupOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      worker: {\n        rollupOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      optimizeDeps: {\n        rollupOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      ssr: {\n        optimizeDeps: {\n          rollupOptions: {\n            output: {\n              minifyInternalExports: true,\n            },\n          },\n        },\n      },\n    })\n\n    const mergedConfig = mergeConfig(baseConfig, newConfig)\n\n    const expected = {\n      treeshake: false,\n      output: {\n        minifyInternalExports: true,\n      },\n    }\n    expect(mergedConfig.build.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.build.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.worker.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.worker.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.optimizeDeps.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.optimizeDeps.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.ssr.optimizeDeps.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.ssr.optimizeDeps.rolldownOptions).toStrictEqual(\n      expected,\n    )\n  })\n\n  test('handles `build.rolldownOptions`', () => {\n    const baseConfig = defineConfig({\n      build: {\n        rolldownOptions: {\n          treeshake: false,\n        },\n      },\n      worker: {\n        rolldownOptions: {\n          treeshake: false,\n        },\n      },\n      optimizeDeps: {\n        rolldownOptions: {\n          treeshake: false,\n        },\n      },\n      ssr: {\n        optimizeDeps: {\n          rolldownOptions: {\n            treeshake: false,\n          },\n        },\n      },\n    })\n\n    const newConfig = defineConfig({\n      build: {\n        rolldownOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      worker: {\n        rolldownOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      optimizeDeps: {\n        rolldownOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      ssr: {\n        optimizeDeps: {\n          rolldownOptions: {\n            output: {\n              minifyInternalExports: true,\n            },\n          },\n        },\n      },\n    })\n\n    const mergedConfig = mergeConfig(baseConfig, newConfig)\n\n    const expected = {\n      treeshake: false,\n      output: {\n        minifyInternalExports: true,\n      },\n    }\n    expect(mergedConfig.build.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.build.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.worker.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.worker.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.optimizeDeps.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.optimizeDeps.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.ssr.optimizeDeps.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.ssr.optimizeDeps.rolldownOptions).toStrictEqual(\n      expected,\n    )\n  })\n\n  test('syncs `build.rollupOptions` and `build.rolldownOptions`', () => {\n    const baseConfig = defineConfig({\n      build: {\n        rollupOptions: {\n          treeshake: false,\n        },\n      },\n      worker: {\n        rollupOptions: {\n          treeshake: false,\n        },\n      },\n      optimizeDeps: {\n        rollupOptions: {\n          treeshake: false,\n        },\n      },\n      ssr: {\n        optimizeDeps: {\n          rollupOptions: {\n            treeshake: false,\n          },\n        },\n      },\n    })\n\n    const newConfig = defineConfig({\n      build: {\n        rolldownOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      worker: {\n        rolldownOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      optimizeDeps: {\n        rolldownOptions: {\n          output: {\n            minifyInternalExports: true,\n          },\n        },\n      },\n      ssr: {\n        optimizeDeps: {\n          rollupOptions: {\n            output: {\n              minifyInternalExports: true,\n            },\n          },\n        },\n      },\n    })\n\n    const mergedConfig = mergeConfig(baseConfig, newConfig) as UserConfig\n\n    const expected = {\n      treeshake: false,\n      output: {\n        minifyInternalExports: true,\n      },\n    }\n    expect(mergedConfig.build!.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.build!.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.worker!.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.worker!.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.optimizeDeps!.rollupOptions).toStrictEqual(expected)\n    expect(mergedConfig.optimizeDeps!.rolldownOptions).toStrictEqual(expected)\n    expect(mergedConfig.ssr!.optimizeDeps!.rollupOptions).toStrictEqual(\n      expected,\n    )\n    expect(mergedConfig.ssr!.optimizeDeps!.rolldownOptions).toStrictEqual(\n      expected,\n    )\n\n    const upOutput = mergedConfig.build!.rollupOptions!.output!\n    if (Array.isArray(upOutput)) throw new Error()\n    const downOutput = mergedConfig.build!.rolldownOptions!.output!\n    if (Array.isArray(downOutput)) throw new Error()\n    upOutput.hashCharacters = 'base36'\n    expect(upOutput.hashCharacters).toBe('base36')\n    expect(downOutput.hashCharacters).toBe('base36')\n  })\n\n  test('rollupOptions/rolldownOptions.platform', async () => {\n    const testRollupOptions = await resolveConfig(\n      {\n        plugins: [\n          {\n            name: 'set-rollupOptions-platform',\n            configEnvironment(name) {\n              if (name === 'ssr') {\n                return {\n                  build: {\n                    rollupOptions: {\n                      platform: 'neutral',\n                    },\n                  },\n                }\n              }\n            },\n          },\n        ],\n      },\n      'serve',\n    )\n    expect(\n      testRollupOptions.environments.ssr.build.rolldownOptions.platform,\n    ).toBe('neutral')\n    expect(\n      testRollupOptions.environments.client.build.rolldownOptions.platform,\n    ).toBe('browser')\n\n    const testRolldownOptions = await resolveConfig(\n      {\n        plugins: [\n          {\n            name: 'set-rollupOptions-platform',\n            configEnvironment(name) {\n              if (name === 'ssr') {\n                return {\n                  build: {\n                    rolldownOptions: {\n                      platform: 'neutral',\n                    },\n                  },\n                }\n              }\n            },\n          },\n        ],\n      },\n      'serve',\n    )\n    expect(\n      testRolldownOptions.environments.ssr.build.rolldownOptions.platform,\n    ).toBe('neutral')\n    expect(\n      testRolldownOptions.environments.client.build.rolldownOptions.platform,\n    ).toBe('browser')\n  })\n\n  describe('later plugin can read `rollupOptions` set via `rolldownOptions` in earlier plugin', () => {\n    test('top-level config', async () => {\n      expect.assertions(2)\n      await resolveConfig(\n        {\n          plugins: [\n            {\n              name: 'plugin-a',\n              config() {\n                return {\n                  build: {\n                    rolldownOptions: {\n                      platform: 'neutral',\n                    },\n                  },\n                  worker: {\n                    rolldownOptions: {\n                      platform: 'neutral',\n                    },\n                  },\n                }\n              },\n            },\n            {\n              name: 'plugin-b',\n              config(config) {\n                expect(config.build?.rollupOptions?.platform).toBe('neutral')\n                expect(config.worker?.rollupOptions?.platform).toBe('neutral')\n              },\n            },\n          ],\n        },\n        'build',\n      )\n    })\n\n    test('new `environments` object', async () => {\n      expect.assertions(1)\n      await resolveConfig(\n        {\n          plugins: [\n            {\n              name: 'plugin-a',\n              config() {\n                return {\n                  environments: {\n                    ssr: {\n                      build: {\n                        rolldownOptions: {\n                          platform: 'neutral',\n                        },\n                      },\n                    },\n                  },\n                }\n              },\n            },\n            {\n              name: 'plugin-b',\n              config(config) {\n                expect(\n                  config.environments?.ssr?.build?.rollupOptions?.platform,\n                ).toBe('neutral')\n              },\n            },\n          ],\n        },\n        'build',\n      )\n    })\n\n    test('new environment on existing `environments` object', async () => {\n      expect.assertions(1)\n      await resolveConfig(\n        {\n          environments: {\n            // environments exists, but no ssr\n            client: {},\n          },\n          plugins: [\n            {\n              name: 'plugin-a',\n              config() {\n                return {\n                  environments: {\n                    ssr: {\n                      build: {\n                        rolldownOptions: {\n                          platform: 'neutral',\n                        },\n                      },\n                    },\n                  },\n                }\n              },\n            },\n            {\n              name: 'plugin-b',\n              config(config) {\n                expect(\n                  config.environments?.ssr?.build?.rollupOptions?.platform,\n                ).toBe('neutral')\n              },\n            },\n          ],\n        },\n        'build',\n      )\n    })\n  })\n})\n\ndescribe('resolveEnvPrefix', () => {\n  test(`use 'VITE_' as default value`, () => {\n    const config: UserConfig = {}\n    expect(resolveEnvPrefix(config)).toMatchObject(['VITE_'])\n  })\n\n  test(`throw error if envPrefix contains ''`, () => {\n    let config: UserConfig = { envPrefix: '' }\n    expect(() => resolveEnvPrefix(config)).toThrow()\n    config = { envPrefix: ['', 'CUSTOM_'] }\n    expect(() => resolveEnvPrefix(config)).toThrow()\n  })\n\n  test(`show a warning message if envPrefix contains a whitespace`, () => {\n    const consoleWarnSpy = vi\n      .spyOn(console, 'warn')\n      .mockImplementation(() => {})\n    let config: UserConfig = { envPrefix: 'WITH SPACE' }\n    resolveEnvPrefix(config)\n    expect(consoleWarnSpy).toHaveBeenCalled()\n    config = { envPrefix: ['CUSTOM_', 'ANOTHER SPACE'] }\n    resolveEnvPrefix(config)\n    expect(consoleWarnSpy).toHaveBeenCalledTimes(2)\n    consoleWarnSpy.mockRestore()\n  })\n\n  test('should work correctly for valid envPrefix value', () => {\n    const config: UserConfig = { envPrefix: ['CUSTOM_'] }\n    expect(resolveEnvPrefix(config)).toMatchObject(['CUSTOM_'])\n  })\n})\n\ndescribe('preview config', () => {\n  const serverConfig = () => ({\n    port: 3003,\n    strictPort: true,\n    host: true,\n    open: true,\n    headers: {\n      'Cache-Control': 'no-store',\n    },\n    proxy: { '/foo': 'http://localhost:4567' },\n    cors: true,\n  })\n\n  test('preview inherits server config with default port', async () => {\n    const config: InlineConfig = {\n      server: serverConfig(),\n    }\n    expect(await resolveConfig(config, 'serve')).toMatchObject({\n      preview: {\n        ...serverConfig(),\n        port: 4173,\n      },\n    })\n  })\n\n  test('preview inherits server config with port override', async () => {\n    const config: InlineConfig = {\n      server: serverConfig(),\n      preview: {\n        port: 3006,\n      },\n    }\n    expect(await resolveConfig(config, 'serve')).toMatchObject({\n      preview: {\n        ...serverConfig(),\n        port: 3006,\n      },\n    })\n  })\n\n  const previewConfig = () => ({\n    port: 3006,\n    strictPort: false,\n    open: false,\n    host: false,\n    proxy: { '/bar': 'http://localhost:3010' },\n    cors: false,\n  })\n\n  test('preview overrides server config', async () => {\n    const config: InlineConfig = {\n      server: serverConfig(),\n      preview: previewConfig(),\n    }\n    expect(await resolveConfig(config, 'serve')).toMatchObject({\n      preview: previewConfig(),\n    })\n  })\n})\n\ndescribe('resolveConfig', () => {\n  const keepScreenMergePlugin = (): PluginOption => {\n    return {\n      name: 'vite-plugin-keep-screen-merge',\n      config() {\n        return { clearScreen: false }\n      },\n    }\n  }\n\n  const keepScreenOverridePlugin = (): PluginOption => {\n    return {\n      name: 'vite-plugin-keep-screen-override',\n      config(config) {\n        config.clearScreen = false\n      },\n    }\n  }\n\n  test('plugin merges `clearScreen` option', async () => {\n    const config1: InlineConfig = { plugins: [keepScreenMergePlugin()] }\n    const config2: InlineConfig = {\n      plugins: [keepScreenMergePlugin()],\n      clearScreen: true,\n    }\n\n    const results1 = await resolveConfig(config1, 'build')\n    const results2 = await resolveConfig(config2, 'build')\n\n    expect(results1.clearScreen).toBe(false)\n    expect(results2.clearScreen).toBe(false)\n  })\n\n  test('plugin overrides `clearScreen` option', async () => {\n    const config1: InlineConfig = { plugins: [keepScreenOverridePlugin()] }\n    const config2: InlineConfig = {\n      plugins: [keepScreenOverridePlugin()],\n      clearScreen: true,\n    }\n\n    const results1 = await resolveConfig(config1, 'build')\n    const results2 = await resolveConfig(config2, 'build')\n\n    expect(results1.clearScreen).toBe(false)\n    expect(results2.clearScreen).toBe(false)\n  })\n\n  test('resolveConfig with root path including \"#\" and \"?\" and \"*\" should warn ', async () => {\n    expect.assertions(1)\n\n    const logger = createLogger('info')\n    logger.warn = (str) => {\n      expect(str).to.include(\n        'Consider renaming the directory / file to remove the characters',\n      )\n    }\n\n    await resolveConfig({ root: './inc?ud#s*', customLogger: logger }, 'build')\n  })\n\n  test('syncs `build.rollupOptions` and `build.rolldownOptions`', async () => {\n    const resolved = await resolveConfig({}, 'build')\n    expect(resolved.build!.rollupOptions).toStrictEqual(\n      resolved.build!.rolldownOptions,\n    )\n    expect(resolved.worker!.rollupOptions).toStrictEqual(\n      resolved.worker!.rolldownOptions,\n    )\n    expect(resolved.optimizeDeps!.rollupOptions).toStrictEqual(\n      resolved.optimizeDeps!.rolldownOptions,\n    )\n  })\n})\n\ntest('config compat 1', async () => {\n  const config = await resolveConfig(\n    {\n      resolve: {\n        conditions: ['client1'],\n      },\n      ssr: {\n        resolve: {\n          conditions: ['ssr1'],\n        },\n      },\n      plugins: [\n        {\n          name: 'test',\n          config() {\n            return {\n              environments: {\n                client: {\n                  resolve: {\n                    conditions: ['client2'],\n                  },\n                },\n                ssr: {\n                  resolve: {\n                    conditions: ['ssr2'],\n                  },\n                },\n              },\n            }\n          },\n        },\n      ],\n    },\n    'serve',\n  )\n  expect(config.resolve.conditions).toMatchInlineSnapshot(`\n    [\n      \"client1\",\n      \"client2\",\n    ]\n  `)\n  expect(config.environments.client.resolve.conditions).toMatchInlineSnapshot(`\n    [\n      \"client1\",\n      \"client2\",\n    ]\n  `)\n  expect(config.ssr.resolve?.conditions).toMatchInlineSnapshot(`\n    [\n      \"ssr1\",\n      \"ssr2\",\n    ]\n  `)\n  expect(config.environments.ssr.resolve?.conditions).toMatchInlineSnapshot(`\n    [\n      \"ssr1\",\n      \"ssr2\",\n    ]\n  `)\n})\n\ntest('config compat 2', async () => {\n  const config = await resolveConfig(\n    {\n      environments: {\n        client: {\n          resolve: {\n            conditions: ['client1'],\n          },\n        },\n        ssr: {\n          resolve: {\n            conditions: ['ssr1'],\n          },\n        },\n      },\n      plugins: [\n        {\n          name: 'test',\n          config() {\n            return {\n              resolve: {\n                conditions: ['client2'],\n              },\n              ssr: {\n                resolve: {\n                  conditions: ['ssr2'],\n                },\n              },\n            }\n          },\n        },\n      ],\n    },\n    'serve',\n  )\n  expect(config.resolve.conditions).toMatchInlineSnapshot(`\n    [\n      \"client2\",\n      \"client1\",\n    ]\n  `)\n  expect(config.environments.client.resolve.conditions).toMatchInlineSnapshot(`\n    [\n      \"client2\",\n      \"client1\",\n    ]\n  `)\n  expect(config.ssr.resolve?.conditions).toMatchInlineSnapshot(`\n    [\n      \"ssr2\",\n      \"ssr1\",\n    ]\n  `)\n  expect(config.environments.ssr.resolve?.conditions).toMatchInlineSnapshot(`\n    [\n      \"ssr2\",\n      \"ssr1\",\n    ]\n  `)\n})\n\ntest('config compat 3', async () => {\n  const config = await resolveConfig({}, 'serve')\n  expect(config.resolve.conditions).toMatchInlineSnapshot(`\n    [\n      \"module\",\n      \"browser\",\n      \"development|production\",\n    ]\n  `)\n  expect(config.environments.client.resolve.conditions).toMatchInlineSnapshot(`\n    [\n      \"module\",\n      \"browser\",\n      \"development|production\",\n    ]\n  `)\n  expect(config.ssr.resolve?.conditions).toMatchInlineSnapshot(`\n    [\n      \"module\",\n      \"node\",\n      \"development|production\",\n    ]\n  `)\n  expect(config.environments.ssr.resolve?.conditions).toMatchInlineSnapshot(`\n    [\n      \"module\",\n      \"node\",\n      \"development|production\",\n    ]\n  `)\n})\n\ntest('preTransformRequests', async () => {\n  async function testConfig(inlineConfig: InlineConfig) {\n    return Object.fromEntries(\n      Object.entries(\n        (await resolveConfig(inlineConfig, 'serve')).environments,\n      ).map(([name, e]) => [name, e.dev.preTransformRequests]),\n    )\n  }\n\n  expect(\n    await testConfig({\n      environments: {\n        custom: {},\n        customTrue: {\n          dev: {\n            preTransformRequests: true,\n          },\n        },\n        customFalse: {\n          dev: {\n            preTransformRequests: false,\n          },\n        },\n      },\n    }),\n  ).toMatchInlineSnapshot(`\n    {\n      \"client\": true,\n      \"custom\": false,\n      \"customFalse\": false,\n      \"customTrue\": true,\n      \"ssr\": false,\n    }\n  `)\n\n  expect(\n    await testConfig({\n      server: {\n        preTransformRequests: true,\n      },\n      environments: {\n        custom: {},\n        customTrue: {\n          dev: {\n            preTransformRequests: true,\n          },\n        },\n        customFalse: {\n          dev: {\n            preTransformRequests: false,\n          },\n        },\n      },\n    }),\n  ).toMatchInlineSnapshot(`\n    {\n      \"client\": true,\n      \"custom\": true,\n      \"customFalse\": false,\n      \"customTrue\": true,\n      \"ssr\": true,\n    }\n  `)\n\n  expect(\n    await testConfig({\n      server: {\n        preTransformRequests: false,\n      },\n      environments: {\n        custom: {},\n        customTrue: {\n          dev: {\n            preTransformRequests: true,\n          },\n        },\n        customFalse: {\n          dev: {\n            preTransformRequests: false,\n          },\n        },\n      },\n    }),\n  ).toMatchInlineSnapshot(`\n    {\n      \"client\": false,\n      \"custom\": false,\n      \"customFalse\": false,\n      \"customTrue\": true,\n      \"ssr\": false,\n    }\n  `)\n})\n\ndescribe('loadConfigFromFile', () => {\n  const fixtures = path.resolve(import.meta.dirname, './fixtures/config')\n\n  describe('load default files', () => {\n    const root = path.resolve(fixtures, './loadConfigFromFile')\n\n    let writtenConfig: string | undefined\n    afterEach(() => {\n      if (writtenConfig) {\n        fs.unlinkSync(path.resolve(root, writtenConfig))\n      }\n      fs.unlinkSync(path.resolve(root, 'package.json'))\n    })\n\n    const writeConfig = (fileName: string, content: string) => {\n      fs.writeFileSync(path.resolve(root, fileName), content)\n      writtenConfig = fileName\n    }\n    const writePackageJson = (typeField: string | undefined) => {\n      fs.writeFileSync(\n        path.resolve(root, 'package.json'),\n        JSON.stringify({\n          name: '@vitejs/test-load-config-from-file',\n          type: typeField,\n        }),\n      )\n    }\n\n    const canLoadConfig = async () => {\n      const result = await loadConfigFromFile(\n        { command: 'build', mode: 'production' },\n        undefined,\n        root,\n      )\n      expect(result).toBeTruthy()\n      expect(result?.config).toStrictEqual({ define: { foo: 1 } })\n      expect(path.normalize(result!.path)).toBe(\n        path.resolve(root, writtenConfig!),\n      )\n    }\n\n    const cases = [\n      {\n        fileName: 'vite.config.js',\n        content: 'export default { define: { foo: 1 } }',\n      },\n      {\n        fileName: 'vite.config.js',\n        content: 'export default { define: { foo: 1 } }',\n      },\n      {\n        fileName: 'vite.config.cjs',\n        content: 'module.exports = { define: { foo: 1 } }',\n      },\n      {\n        fileName: 'vite.config.cjs',\n        content: 'module.exports = { define: { foo: 1 } }',\n      },\n      {\n        fileName: 'vite.config.mjs',\n        content: 'export default { define: { foo: 1 } }',\n      },\n      {\n        fileName: 'vite.config.mjs',\n        content: 'export default { define: { foo: 1 } }',\n      },\n      {\n        fileName: 'vite.config.ts',\n        content: 'export default { define: { foo: 1 as number } }',\n      },\n      {\n        fileName: 'vite.config.ts',\n        content: 'export default { define: { foo: 1 as number } }',\n      },\n      {\n        fileName: 'vite.config.mts',\n        content: 'export default { define: { foo: 1 as number } }',\n      },\n      {\n        fileName: 'vite.config.mts',\n        content: 'export default { define: { foo: 1 as number } }',\n      },\n      {\n        fileName: 'vite.config.cts',\n        content: 'module.exports = { define: { foo: 1 as number } }',\n      },\n      {\n        fileName: 'vite.config.cts',\n        content: 'module.exports = { define: { foo: 1 as number } }',\n      },\n    ]\n\n    for (const { fileName, content } of cases) {\n      for (const typeField of [undefined, 'module']) {\n        test(`load ${fileName}${typeField ? ' with package#type module' : ''}`, async () => {\n          writePackageJson(typeField)\n          writeConfig(fileName, content)\n          await canLoadConfig()\n        })\n      }\n    }\n  })\n\n  test('can import values', async () => {\n    const { config } = (await loadConfigFromFile(\n      {} as any,\n      path.resolve(fixtures, './entry/vite.config.ts'),\n      path.resolve(fixtures, './entry'),\n    ))!\n    expect(config).toMatchInlineSnapshot(`\n      {\n        \"array\": [\n          [\n            1,\n            3,\n          ],\n          [\n            2,\n            4,\n          ],\n        ],\n        \"importsField\": \"imports-field\",\n        \"moduleCondition\": \"import condition\",\n      }\n    `)\n  })\n\n  test('loadConfigFromFile with import attributes', async () => {\n    const { config } = (await loadConfigFromFile(\n      {} as any,\n      path.resolve(fixtures, './entry/vite.config.import-attributes.ts'),\n      path.resolve(fixtures, './entry'),\n    ))!\n    expect(config).toMatchInlineSnapshot(`\n        {\n          \"jsonValue\": \"vite\",\n        }\n      `)\n  })\n\n  test('import.meta properties are supported', async () => {\n    const { config } = (await loadConfigFromFile(\n      {} as any,\n      path.resolve(fixtures, './import-meta/vite.config.ts'),\n      path.resolve(fixtures, './import-meta'),\n    ))!\n\n    const c = config as any\n    expect(c.isMain).toBe(false)\n    expect(c.url).toContain('file://')\n    expect(c.dirname).toContain('import-meta')\n    expect(c.filename).toContain('vite.config.ts')\n    expect(c.resolved).toBe(c.url)\n    expect(c.resolvedMultiline).toBe(c.url)\n  })\n\n  test('shebang is preserved at the top of the file', async () => {\n    const { config } = (await loadConfigFromFile(\n      {} as any,\n      path.resolve(fixtures, './shebang/vite.config.ts'),\n      path.resolve(fixtures, './shebang'),\n    ))!\n\n    const c = config as any\n    expect(c.dirname).toContain('shebang')\n  })\n\n  describe('loadConfigFromFile with configLoader: native', () => {\n    const fixtureRoot = path.resolve(fixtures, './native-import')\n\n    test('imports a basic js config', async () => {\n      const result = (await loadConfigFromFile(\n        {} as any,\n        path.resolve(fixtureRoot, 'basic.js'),\n        fixtureRoot,\n        undefined,\n        undefined,\n        'native',\n      ))!\n      expect(result.config).toMatchInlineSnapshot(`\n        {\n          \"value\": \"works\",\n        }\n      `)\n      expect(result.dependencies.length).toBe(0)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/constants.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { defaultAllowedOrigins } from '../constants'\n\ntest('defaultAllowedOrigins', () => {\n  const allowed = [\n    'http://localhost',\n    'http://foo.localhost',\n    'http://localhost:3000',\n    'https://localhost:3000',\n    'http://127.0.0.1',\n    'http://[::1]',\n    'http://[::1]:3000',\n  ]\n  const denied = [\n    'file:///foo',\n    'http://localhost.example.com',\n    'http://foo.example.com:localhost',\n    'http://',\n    'http://192.0.2',\n    'http://[2001:db8::1]',\n    'http://vite',\n    'http://vite:3000',\n  ]\n\n  for (const origin of allowed) {\n    expect(defaultAllowedOrigins.test(origin), origin).toBe(true)\n  }\n\n  for (const origin of denied) {\n    expect(defaultAllowedOrigins.test(origin), origin).toBe(false)\n  }\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/dev.spec.ts",
    "content": "import { afterEach, describe, expect, test } from 'vitest'\nimport type { ResolvedServerUrls } from 'vite'\nimport { createServer, resolveConfig } from '..'\nimport type { ViteDevServer } from '..'\nimport { promiseWithResolvers } from '../../shared/utils'\n\ndescribe('resolveBuildEnvironmentOptions in dev', () => {\n  test('build.rollupOptions should not have input in lib', async () => {\n    const config = await resolveConfig(\n      {\n        build: {\n          lib: {\n            entry: './index.js',\n          },\n        },\n      },\n      'serve',\n    )\n\n    expect(config.build.rollupOptions).not.toHaveProperty('input')\n  })\n})\n\ndescribe('the dev server', () => {\n  let server: ViteDevServer\n\n  afterEach(async () => {\n    await server?.close()\n  })\n\n  test('resolves the server URLs before the httpServer listening events are called', async () => {\n    expect.assertions(1)\n\n    const options = {\n      port: 5013, // make sure the port is unique\n    }\n\n    const { promise, resolve } =\n      promiseWithResolvers<ResolvedServerUrls | null>()\n    server = await createServer({\n      root: import.meta.dirname,\n      logLevel: 'error',\n      server: {\n        strictPort: true,\n        ws: false,\n        ...options,\n      },\n      plugins: [\n        {\n          name: 'test',\n          configureServer(server) {\n            server.httpServer?.on('listening', () => {\n              resolve(server.resolvedUrls)\n            })\n          },\n        },\n      ],\n    })\n\n    await server.listen()\n    const urls = await promise\n\n    expect(urls).toStrictEqual({\n      local: ['http://localhost:5013/'],\n      network: [],\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/env.spec.ts",
    "content": "import { join } from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { loadEnv } from '../env'\n\nconst dirname = import.meta.dirname\n\ndescribe('loadEnv', () => {\n  test('basic', () => {\n    expect(loadEnv('development', join(dirname, './env')))\n      .toMatchInlineSnapshot(`\n        {\n          \"VITE_APP_BASE_ROUTE\": \"/\",\n          \"VITE_APP_BASE_URL\": \"/\",\n          \"VITE_ENV1\": \"ENV1\",\n          \"VITE_ENV2\": \"ENV2\",\n          \"VITE_ENV3\": \"ENV3\",\n        }\n      `)\n  })\n\n  test('specific prefix', () => {\n    expect(loadEnv('development', join(dirname, './env'), 'VVITE'))\n      .toMatchInlineSnapshot(`\n        {\n          \"VVITE_A\": \"A\",\n          \"VVITE_B\": \"B\",\n        }\n      `)\n  })\n\n  test('override', () => {\n    expect(loadEnv('production', join(dirname, './env')))\n      .toMatchInlineSnapshot(`\n        {\n          \"VITE_APP_BASE_ROUTE\": \"/app/\",\n          \"VITE_APP_BASE_URL\": \"/app/\",\n        }\n      `)\n  })\n\n  test('override 2', () => {\n    expect(loadEnv('development2', join(dirname, './env')))\n      .toMatchInlineSnapshot(`\n        {\n          \"VITE_APP_BASE_ROUTE\": \"source\",\n          \"VITE_APP_BASE_URL\": \"source\",\n          \"VITE_SOURCE\": \"source\",\n        }\n      `)\n  })\n\n  test('VITE_USER_NODE_ENV', () => {\n    loadEnv('development', join(dirname, './env'))\n    expect(process.env.VITE_USER_NODE_ENV).toEqual(undefined)\n  })\n\n  test('VITE_USER_NODE_ENV for dev behaviour in build', () => {\n    const _nodeEnv = process.env.NODE_ENV\n    process.env.NODE_ENV = 'production'\n    loadEnv('testing', join(dirname, './env'))\n    expect(process.env.VITE_USER_NODE_ENV).toEqual('development')\n    process.env.NODE_ENV = _nodeEnv\n  })\n\n  test('Already exists VITE_USER_NODE_ENV', () => {\n    process.env.VITE_USER_NODE_ENV = 'test'\n    loadEnv('development', join(dirname, './env'))\n    expect(process.env.VITE_USER_NODE_ENV).toEqual('test')\n  })\n\n  test('prioritize existing process.env', () => {\n    process.env.VITE_ENV_TEST_ENV = 'EXIST'\n    expect(loadEnv('existing', join(dirname, './env'))).toMatchInlineSnapshot(`\n        {\n          \"VITE_APP_BASE_ROUTE\": \"/\",\n          \"VITE_APP_BASE_URL\": \"/\",\n          \"VITE_ENV_TEST_ENV\": \"EXIST\",\n          \"VITE_USER_NODE_ENV\": \"test\",\n        }\n      `)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/environment.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, onTestFinished, test } from 'vitest'\nimport type { RolldownOutput } from 'rolldown'\nimport { createServer } from '../server'\nimport type { InlineConfig } from '../config'\nimport { createBuilder } from '../build'\nimport { createServerModuleRunner } from '../ssr/runtime/serverModuleRunner'\n\ndescribe('custom environment conditions', () => {\n  function getConfig({\n    noExternal,\n  }: {\n    noExternal: true | undefined\n  }): InlineConfig {\n    return {\n      configFile: false,\n      root: import.meta.dirname,\n      logLevel: 'error',\n      server: {\n        middlewareMode: true,\n        ws: false,\n      },\n      // disable scanner for client env to suppress scanner warnings\n      optimizeDeps: { entries: [] },\n      environments: {\n        // default\n        ssr: {\n          resolve: {\n            noExternal,\n          },\n          build: {\n            outDir: path.join(\n              import.meta.dirname,\n              'fixtures/test-dep-conditions/dist/ssr',\n            ),\n            rollupOptions: {\n              input: { index: '@vitejs/test-dep-conditions' },\n            },\n          },\n        },\n        // worker\n        worker: {\n          resolve: {\n            noExternal,\n            conditions: ['worker'],\n            externalConditions: ['worker'],\n          },\n          build: {\n            outDir: path.join(\n              import.meta.dirname,\n              'fixtures/test-dep-conditions/dist/worker',\n            ),\n            rollupOptions: {\n              input: { index: '@vitejs/test-dep-conditions' },\n            },\n          },\n        },\n        // custom1\n        custom1: {\n          resolve: {\n            noExternal,\n            conditions: ['custom1'],\n            externalConditions: ['custom1'],\n          },\n          build: {\n            outDir: path.join(\n              import.meta.dirname,\n              'fixtures/test-dep-conditions/dist/custom1',\n            ),\n            rollupOptions: {\n              input: { index: '@vitejs/test-dep-conditions' },\n            },\n          },\n        },\n        // same as custom1\n        custom1_2: {\n          resolve: {\n            noExternal,\n            conditions: ['custom1'],\n            externalConditions: ['custom1'],\n          },\n          build: {\n            outDir: path.join(\n              import.meta.dirname,\n              'fixtures/test-dep-conditions/dist/custom1_2',\n            ),\n            rollupOptions: {\n              input: { index: '@vitejs/test-dep-conditions' },\n            },\n          },\n        },\n      },\n    }\n  }\n\n  test('dev noExternal', async () => {\n    const server = await createServer(getConfig({ noExternal: true }))\n    onTestFinished(() => server.close())\n\n    const results: Record<string, unknown> = {}\n    for (const key of ['ssr', 'worker', 'custom1', 'custom1_2']) {\n      const runner = createServerModuleRunner(server.environments[key], {\n        hmr: {\n          logger: false,\n        },\n        sourcemapInterceptor: false,\n      })\n      const mod = await runner.import('@vitejs/test-dep-conditions')\n      results[key] = mod.default\n    }\n    expect(results).toMatchInlineSnapshot(`\n      {\n        \"custom1\": \"index.custom1.js\",\n        \"custom1_2\": \"index.custom1.js\",\n        \"ssr\": \"index.default.js\",\n        \"worker\": \"index.worker.js\",\n      }\n    `)\n  })\n\n  test('dev external', async () => {\n    const server = await createServer(getConfig({ noExternal: undefined }))\n    onTestFinished(() => server.close())\n\n    const results: Record<string, unknown> = {}\n    for (const key of ['ssr', 'worker', 'custom1', 'custom1_2']) {\n      const runner = createServerModuleRunner(server.environments[key], {\n        hmr: {\n          logger: false,\n        },\n        sourcemapInterceptor: false,\n      })\n      const mod = await runner.import(\n        '/fixtures/test-dep-conditions-app/entry.js',\n      )\n      results[key] = mod.default\n    }\n    expect(results).toMatchInlineSnapshot(`\n      {\n        \"custom1\": \"index.custom1.js\",\n        \"custom1_2\": \"index.custom1.js\",\n        \"ssr\": \"index.default.js\",\n        \"worker\": \"index.worker.js\",\n      }\n    `)\n  })\n\n  test('css', async () => {\n    const server = await createServer(getConfig({ noExternal: true }))\n    onTestFinished(() => server.close())\n\n    const modJs = await server.ssrLoadModule(\n      '/fixtures/test-dep-conditions-app/entry.js',\n    )\n    const modCss = await server.ssrLoadModule(\n      '/fixtures/test-dep-conditions-app/entry.css?inline',\n    )\n    expect([modCss.default.replace(/\\s+/g, ' '), modJs.default])\n      .toMatchInlineSnapshot(`\n      [\n        \".test-css { color: orange; } \",\n        \"index.default.js\",\n      ]\n    `)\n  })\n\n  test('build', async () => {\n    const builder = await createBuilder(getConfig({ noExternal: true }))\n    const results: Record<string, unknown> = {}\n    for (const key of ['ssr', 'worker', 'custom1', 'custom1_2']) {\n      const output = await builder.build(builder.environments[key])\n      const chunk = (output as RolldownOutput).output[0]\n      const mod = await import(\n        path.join(\n          import.meta.dirname,\n          'fixtures/test-dep-conditions/dist',\n          key,\n          chunk.fileName,\n        )\n      )\n      results[key] = mod.default\n    }\n    expect(results).toMatchInlineSnapshot(`\n      {\n        \"custom1\": \"index.custom1.js\",\n        \"custom1_2\": \"index.custom1.js\",\n        \"ssr\": \"index.default.js\",\n        \"worker\": \"index.worker.js\",\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/external.spec.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { describe, expect, test } from 'vitest'\nimport { resolveConfig } from '../config'\nimport { createIsConfiguredAsExternal } from '../external'\nimport { PartialEnvironment } from '../baseEnvironment'\n\ndescribe('createIsConfiguredAsExternal', () => {\n  test('default', async () => {\n    const isExternal = await createIsExternal()\n    expect(isExternal('@vitejs/cjs-ssr-dep')).toBe(false)\n  })\n\n  test('force external', async () => {\n    const isExternal = await createIsExternal(true)\n    expect(isExternal('@vitejs/cjs-ssr-dep')).toBe(true)\n  })\n})\n\nasync function createIsExternal(external?: true) {\n  const resolvedConfig = await resolveConfig(\n    {\n      configFile: false,\n      root: fileURLToPath(new URL('./', import.meta.url)),\n      resolve: { external },\n    },\n    'serve',\n  )\n  const environment = new PartialEnvironment('ssr', resolvedConfig)\n  return createIsConfiguredAsExternal(environment)\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/filterRegex.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { assetImportMetaUrlRE } from '../plugins/assetImportMetaUrl'\nimport { workerImportMetaUrlRE } from '../plugins/workerImportMetaUrl'\n\ndescribe('filter regexes do not cause catastrophic backtracking', () => {\n  const largeCode =\n    `new URL('https://example.com');\\n`.repeat(200) +\n    `var a = 1;\\n`.repeat(200_000)\n\n  test('assetImportMetaUrlRE completes without backtracking on large files', () => {\n    assetImportMetaUrlRE.lastIndex = 0\n    expect(assetImportMetaUrlRE.test(largeCode)).toBe(false)\n  })\n\n  test('workerImportMetaUrlRE completes without backtracking on large files', () => {\n    workerImportMetaUrlRE.lastIndex = 0\n    expect(workerImportMetaUrlRE.test(largeCode)).toBe(false)\n  })\n\n  test('assetImportMetaUrlRE still matches valid patterns', () => {\n    assetImportMetaUrlRE.lastIndex = 0\n    expect(\n      assetImportMetaUrlRE.test(`new URL('./asset.png', import.meta.url)`),\n    ).toBe(true)\n  })\n\n  test('workerImportMetaUrlRE still matches valid patterns', () => {\n    workerImportMetaUrlRE.lastIndex = 0\n    expect(\n      workerImportMetaUrlRE.test(\n        `new Worker(new URL('./worker.js', import.meta.url))`,\n      ),\n    ).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/cjs-ssr-dep/index.js",
    "content": "// eslint-disable-next-line no-undef\nmodule.exports = {\n  hello: () => 'world',\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/cjs-ssr-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/cjs-ssr-dep\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/entry/imports-field.ts",
    "content": "export default 'imports-field'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/entry/package.json",
    "content": "{\n  \"name\": \"@vite/test-config-entry\",\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@vite/test-config-plugin-module-condition\": \"link:../plugin-module-condition\"\n  },\n  \"imports\": {\n    \"#imports-field\": \"./imports-field.ts\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/entry/vite.config.import-attributes.ts",
    "content": "// We have to import external json to prevent Vite / esbuild from bundling it.\nimport pkg from 'vite/package.json' with { type: 'json' }\n\nexport default {\n  jsonValue: pkg.name,\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/entry/vite.config.ts",
    "content": "import moduleCondition from '@vite/test-config-plugin-module-condition'\nimport { array } from '../siblings/foo'\nimport importsField from '#imports-field'\n\nexport default {\n  array,\n  moduleCondition,\n  importsField,\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/import-meta/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/import-meta/vite.config.ts",
    "content": "export default {\n  isMain: import.meta.main,\n  url: import.meta.url,\n  dirname: import.meta.dirname,\n  filename: import.meta.filename,\n  resolved: import.meta.resolve('../import-meta/vite.config.ts'),\n  // prettier-ignore\n  resolvedMultiline: import.meta\n    .resolve('../import-meta/vite.config.ts'),\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/loadConfigFromFile/.gitkeep",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/native-import/basic.js",
    "content": "export default {\n  value: 'works',\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/plugin-module-condition/index.cjs",
    "content": "module.exports = 'require condition'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/plugin-module-condition/index.d.ts",
    "content": "const str: string\nexport default str\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/plugin-module-condition/index.mjs",
    "content": "export default 'import condition'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/plugin-module-condition/module.mjs",
    "content": "export default 'module condition'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/plugin-module-condition/package.json",
    "content": "{\n  \"name\": \"@vite/test-config-plugin-module-condition\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./index.d.ts\",\n      \"module\": \"./module.mjs\",\n      \"import\": \"./index.mjs\",\n      \"require\": \"./index.cjs\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/shebang/vite.config.ts",
    "content": "#!/usr/bin/env node\nexport default {\n  dirname: import.meta.dirname,\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/siblings/foo.ts",
    "content": "import lodash from 'lodash'\n\nexport const array = lodash.partition([1, 2, 3, 4], (n) => n % 2)\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/config/siblings/package.json",
    "content": "{\n  \"name\": \"@vite/test-config-sibling\",\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"@types/lodash\": \"^4.17.16\",\n    \"lodash\": \"^4.17.21\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/dynamic-import/dep.mjs",
    "content": "export const hello = 'hello'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/dynamic-import/entry.mjs",
    "content": "export async function main() {\n  const mod = await import('./dep.mjs')\n  console.log(mod)\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/emit-assets/css-module.module.css",
    "content": ".css-module {\n  background: rgb(200, 250, 250);\n  padding: 20px;\n  width: 200px;\n  border: 1px solid gray;\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/emit-assets/css-normal.css",
    "content": "#css-normal {\n  background: rgb(250, 250, 200);\n  padding: 20px;\n  width: 200px;\n  border: 1px solid gray;\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/emit-assets/entry.mjs",
    "content": "import './css-normal.css'\nimport cssModule from './css-module.module.css'\n\nexport default function Page() {\n  console.log(cssModule)\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/environment-alias/test.client.js",
    "content": "export const msg = `[success] (client) alias to mod path`\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/environment-alias/test.rsc.js",
    "content": "export const msg = `[success] (rsc) alias to mod path`\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/environment-alias/test.ssr.js",
    "content": "export const msg = `[success] (ssr) alias to mod path`\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/file-url/entry.js",
    "content": "export default 'ok'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/file-url/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/basic.ts",
    "content": "interface Test {\n  field: true\n}\n\nexport const test: Test = {\n  field: true,\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/cjs.js",
    "content": "module.exports = {}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/dynamic-import-dep.ts",
    "content": "export default 'ok'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/dynamic-import.ts",
    "content": "export default () => import('./dynamic-import-dep')\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/plugin.ts",
    "content": "import { Plugin } from 'vite'\n\nexport default function testPlugin(): Plugin {\n  return {\n    name: 'test',\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/vite.config.outside-pkg-import.mts",
    "content": "import parent from '@vitejs/parent'\n\nexport default {\n  __injected: parent.child,\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/runner-import/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport plugin from './plugin'\n\nexport default defineConfig({\n  root: './test',\n  plugins: [plugin()],\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/entry-jsx.tsx",
    "content": ";(globalThis as any).__test_scan_jsx_runtime ??= 0\n;(globalThis as any).__test_scan_jsx_runtime++\n\nexport default <div />\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/entry-no-jsx.js",
    "content": "import * as vue from 'vue'\n\nexport default vue\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/scan-jsx-runtime/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"vue\",\n    \"strict\": true,\n    \"verbatimModuleSyntax\": true,\n    \"noEmit\": true,\n    \"moduleResolution\": \"Bundler\",\n    \"module\": \"ESNext\",\n    \"target\": \"ESNext\",\n    \"lib\": [\"ESNext\", \"DOM\", \"DOM.Iterable\"]\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/shared-config-build/emitAssets/entry.js",
    "content": "import './test.css'\nconsole.log('entry')\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/shared-config-build/emitAssets/test.css",
    "content": "body {\n  color: orange;\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/shared-plugins/minify/entry.js",
    "content": "function main() {\n  console.log('test')\n}\nmain()\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/dir/index.default.js",
    "content": "export default 'dir/index.default.js'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/dir/index.module.js",
    "content": "export default 'dir/index.module.js'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/index.browser.js",
    "content": "export default 'index.browser.js'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/index.css",
    "content": ".test-css {\n  color: orange;\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/index.custom1.js",
    "content": "export default 'index.custom1.js'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/index.default.js",
    "content": "export default 'index.default.js'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/index.worker.js",
    "content": "export default 'index.worker.js'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-conditions\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"style\": \"./index.css\",\n      \"custom1\": \"./index.custom1.js\",\n      \"worker\": \"./index.worker.js\",\n      \"browser\": \"./index.browser.js\",\n      \"default\": \"./index.default.js\"\n    },\n    \"./with-module\": {\n      \"module\": \"./dir/index.module.js\",\n      \"default\": \"./dir/index.default.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions-app/entry-with-module.js",
    "content": "import dep from '@vitejs/test-dep-conditions/with-module'\nexport default dep\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions-app/entry.css",
    "content": "@import '@vitejs/test-dep-conditions';\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/test-dep-conditions-app/entry.js",
    "content": "import dep from '@vitejs/test-dep-conditions'\nexport default dep\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/watch-rebuild-manifest/dep.js",
    "content": "console.log('dep.js')\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/watch-rebuild-manifest/entry.js",
    "content": "console.log('entry.js')\nconsole.log(import('./dep.js'))\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/watch-rebuild-manifest/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/worker-dynamic/dynamic.js",
    "content": "export default 'dynamic ok'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/worker-dynamic/main.js",
    "content": "document.querySelector('#app').innerHTML = `\n  <div>\n    <h1>Test worker</h1>\n    <div id=\"worker\">???</div>\n  </div>\n`\n\nconst worker = new Worker(new URL('./worker.js', import.meta.url))\nworker.onmessage = (e) => {\n  document.querySelector('#worker').textContent = e.data\n}\nworker.postMessage('hi')\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/fixtures/worker-dynamic/worker.js",
    "content": "self.onmessage = async () => {\n  const mod = await import('./dynamic')\n  self.postMessage('hello from worker: ' + mod.default)\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/http.spec.ts",
    "content": "import http from 'node:http'\nimport net from 'node:net'\nimport { afterEach, describe, expect, test, vi } from 'vitest'\nimport { wildcardHosts } from '../constants'\nimport { createServer } from '..'\nimport type { ViteDevServer } from '..'\n\nconst BASE_PORT = 15181\n\ndescribe('port detection', () => {\n  let blockingServer: http.Server | null = null\n  let viteServer: ViteDevServer | null = null\n\n  afterEach(async () => {\n    if (viteServer) {\n      await viteServer.close()\n      viteServer = null\n    }\n\n    await new Promise<void>((resolve) => {\n      if (blockingServer) {\n        blockingServer.close(() => resolve())\n        blockingServer = null\n      } else {\n        resolve()\n      }\n    })\n  })\n\n  async function createSimpleServer(port: number, host: string) {\n    const server = http.createServer()\n    await new Promise<void>((resolve) => {\n      server.listen(port, host, () => resolve())\n    })\n    return {\n      [Symbol.asyncDispose]() {\n        return new Promise<void>((resolve) => {\n          server.close(() => resolve())\n        })\n      },\n    }\n  }\n\n  describe('port fallback', () => {\n    test('detects port conflict', async () => {\n      await using _blockingServer = await createSimpleServer(\n        BASE_PORT,\n        'localhost',\n      )\n\n      viteServer = await createServer({\n        root: import.meta.dirname,\n        logLevel: 'silent',\n        server: { port: BASE_PORT, strictPort: false, ws: false },\n      })\n      await viteServer.listen()\n\n      const address = viteServer.httpServer!.address()\n      expect(address).toStrictEqual(\n        expect.objectContaining({ port: BASE_PORT + 1 }),\n      )\n    })\n\n    test('detects multiple port conflict', async () => {\n      await using _blockingServer1 = await createSimpleServer(\n        BASE_PORT,\n        'localhost',\n      )\n      await using _blockingServer2 = await createSimpleServer(\n        BASE_PORT + 1,\n        'localhost',\n      )\n\n      viteServer = await createServer({\n        root: import.meta.dirname,\n        logLevel: 'silent',\n        server: { port: BASE_PORT, strictPort: false, ws: false },\n      })\n      await viteServer.listen()\n\n      const address = viteServer.httpServer!.address()\n      expect(address).toStrictEqual(\n        expect.objectContaining({ port: BASE_PORT + 2 }),\n      )\n    })\n\n    test('detects port conflict when server listens on 0.0.0.0', async () => {\n      await using _blockingServer = await createSimpleServer(\n        BASE_PORT,\n        '0.0.0.0',\n      )\n\n      viteServer = await createServer({\n        root: import.meta.dirname,\n        logLevel: 'silent',\n        server: { port: BASE_PORT, strictPort: false, ws: false },\n      })\n      await viteServer.listen()\n\n      const address = viteServer.httpServer!.address()\n      expect(address).toStrictEqual(\n        expect.objectContaining({ port: BASE_PORT + 1 }),\n      )\n    })\n\n    test('detects port conflict when server listens on :: (IPv6)', async (ctx) => {\n      let blockingServer\n      try {\n        blockingServer = await createSimpleServer(BASE_PORT, '::')\n      } catch {\n        // Skip test if IPv6 is not available on this system\n        ctx.skip()\n        return\n      }\n      await using _blockingServer = blockingServer\n\n      viteServer = await createServer({\n        root: import.meta.dirname,\n        logLevel: 'silent',\n        server: { port: BASE_PORT, strictPort: false, ws: false },\n      })\n      await viteServer.listen()\n\n      const address = viteServer.httpServer!.address()\n      expect(address).toStrictEqual(\n        expect.objectContaining({ port: BASE_PORT + 1 }),\n      )\n    })\n\n    test('wildcard check also runs after EADDRINUSE fallback', async () => {\n      // localhost:n occupied\n      // 0.0.0.0:n+1 occupied\n      // => Vite should pick n+2\n\n      await using _localhostServer = await createSimpleServer(\n        BASE_PORT,\n        'localhost',\n      )\n      await using _wildcardServer = await createSimpleServer(\n        BASE_PORT + 1,\n        '0.0.0.0',\n      )\n\n      viteServer = await createServer({\n        root: import.meta.dirname,\n        logLevel: 'silent',\n        server: {\n          port: BASE_PORT,\n          strictPort: false,\n          ws: false,\n        },\n      })\n      await viteServer.listen()\n\n      const address = viteServer.httpServer!.address()\n      expect(address).toStrictEqual(\n        expect.objectContaining({ port: BASE_PORT + 2 }),\n      )\n    })\n  })\n\n  test('non-EADDRINUSE errors on wildcard do not block port selection', async () => {\n    const originalCreateServer = net.createServer.bind(net)\n    using _ = vi.spyOn(net, 'createServer').mockImplementation(() => {\n      const server = originalCreateServer()\n      const originalListen = server.listen.bind(server)\n      // @ts-expect-error this is the overload used internally\n      server.listen = (\n        port: number,\n        host: string,\n        ...args: unknown[]\n      ): net.Server => {\n        if (wildcardHosts.has(host)) {\n          process.nextTick(() => {\n            const err: NodeJS.ErrnoException = new Error(\n              'listen EACCES: permission denied',\n            )\n            err.code = 'EACCES'\n            server.emit('error', err)\n          })\n          return server\n        }\n        // @ts-expect-error this is the overload used internally\n        return originalListen(port, host, ...args)\n      }\n      return server\n    })\n\n    viteServer = await createServer({\n      root: import.meta.dirname,\n      logLevel: 'silent',\n      server: { port: BASE_PORT, strictPort: false, ws: false },\n    })\n    await viteServer.listen()\n\n    const address = viteServer.httpServer!.address()\n    expect(address).toStrictEqual(expect.objectContaining({ port: BASE_PORT }))\n  })\n\n  test('throws error when port is blocked and strictPort is true', async () => {\n    await using _blockingServer = await createSimpleServer(\n      BASE_PORT,\n      'localhost',\n    )\n\n    viteServer = await createServer({\n      root: import.meta.dirname,\n      logLevel: 'silent',\n      server: { port: BASE_PORT, strictPort: true, ws: false },\n    })\n\n    await expect(viteServer.listen()).rejects.toThrow(\n      `Port ${BASE_PORT} is already in use`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/optimizer/rolldownDepPlugin.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { rolldownDepPlugin } from '../../optimizer/rolldownDepPlugin'\nimport { normalizePath } from '../../utils'\n\nasync function createRolldownDepPluginTransform(cacheDir: string) {\n  const baseConfig = {\n    cacheDir: normalizePath(cacheDir),\n    optimizeDeps: { extensions: [] },\n    server: { fs: { allow: [] } },\n    resolve: { builtins: [] },\n    createResolver: () => ({}),\n  }\n\n  const mockEnvironment = {\n    config: baseConfig,\n    getTopLevelConfig: () => baseConfig,\n  } as any\n\n  const plugins = rolldownDepPlugin(mockEnvironment, {}, [])\n  const plugin = plugins.find(\n    (p: any) => p.name === 'vite:dep-pre-bundle',\n  ) as any\n\n  if (!plugin || !plugin.transform) {\n    throw new Error('Could not find vite:dep-pre-bundle plugin')\n  }\n\n  const handler = plugin.transform.handler\n\n  return async (code: string, id: string) => {\n    const result = await handler.call({}, code, normalizePath(id))\n    return result?.code || result\n  }\n}\n\ndescribe('rolldownDepPlugin transform', async () => {\n  const transform = await createRolldownDepPluginTransform('/root/.vite')\n\n  test('rewrite various relative asset formats', async () => {\n    const code = `\n      const img = new URL('./logo.png', import.meta.url).href\n      const icon = new URL('./icons/search.svg', import.meta.url)\n      const worker = new URL('./worker.js', import.meta.url)\n      const wasm = new URL('./module.wasm', import.meta.url)\n    `\n    expect(await transform(code, '/root/node_modules/my-lib/dist/index.js'))\n      .toMatchInlineSnapshot(`\n      \"\n            const img = new URL('' + \"../../node_modules/my-lib/dist/logo.png\", import.meta.url).href\n            const icon = new URL('' + \"../../node_modules/my-lib/dist/icons/search.svg\", import.meta.url)\n            const worker = new URL('' + \"../../node_modules/my-lib/dist/worker.js\", import.meta.url)\n            const wasm = new URL('' + \"../../node_modules/my-lib/dist/module.wasm\", import.meta.url)\n          \"\n    `)\n  })\n\n  test('respects /* @vite-ignore */', async () => {\n    expect(\n      await transform(\n        \"new URL(/* @vite-ignore */ './worker.js', import.meta.url)\",\n        '/root/node_modules/my-lib/index.js',\n      ),\n    ).toBeUndefined()\n  })\n\n  test('skips non-relative URLs (absolute, data, protocols)', async () => {\n    const code = `\n      new URL('/absolute/path.png', import.meta.url)\n      new URL('https://example.com/worker.js', import.meta.url)\n      new URL('data:text/javascript;base64,Y29uc29sZS5sb2coMSk=', import.meta.url)\n    `\n    expect(\n      await transform(code, '/root/node_modules/my-lib/index.js'),\n    ).toBeUndefined()\n  })\n\n  test('skips dynamic template strings', async () => {\n    expect(\n      await transform(\n        'new URL(`./${name}.js`, import.meta.url)',\n        '/root/node_modules/my-lib/index.js',\n      ),\n    ).toBeUndefined()\n  })\n\n  test('handles backticks for static relative strings', async () => {\n    expect(\n      await transform(\n        'new URL(`./static.js`, import.meta.url)',\n        '/root/node_modules/my-lib/index.js',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new URL('' + \"../../node_modules/my-lib/static.js\", import.meta.url)\"`,\n    )\n  })\n\n  test('handles assets with query parameters and hashes', async () => {\n    const code = `\n      const url1 = new URL('./style.css?raw', import.meta.url)\n      const url2 = new URL('./data.json#config', import.meta.url)\n    `\n    expect(await transform(code, '/root/node_modules/my-lib/index.js'))\n      .toMatchInlineSnapshot(`\n      \"\n            const url1 = new URL('' + \"../../node_modules/my-lib/style.css?raw\", import.meta.url)\n            const url2 = new URL('' + \"../../node_modules/my-lib/data.json#config\", import.meta.url)\n          \"\n    `)\n  })\n\n  test('handles deeply nested relative paths', async () => {\n    expect(\n      await transform(\n        \"new URL('../../../assets/file.js', import.meta.url)\",\n        '/root/node_modules/my-lib/dist/deep/folder/index.js',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new URL('' + \"../../node_modules/my-lib/assets/file.js\", import.meta.url)\"`,\n    )\n  })\n\n  test('rewrite relative URLs even if id is not in node_modules', async () => {\n    expect(\n      await transform(\n        \"new URL('./asset.js', import.meta.url)\",\n        '/root/src/local-dep.js',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new URL('' + \"../../src/asset.js\", import.meta.url)\"`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/package.json",
    "content": "{\n  \"name\": \"@vitejs/unit-ssr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"@vitejs/parent\": \"link:./packages/parent\",\n    \"@vitejs/cjs-ssr-dep\": \"link:./fixtures/cjs-ssr-dep\",\n    \"@vitejs/test-dep-conditions\": \"file:./fixtures/test-dep-conditions\",\n    \"vue\": \"^3.5.18\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/build-project/index.html",
    "content": "<h1>Hello world</h1>\n\n<script type=\"module\" src=\"entry.js\"></script>\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/child/index.js",
    "content": "export default true\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/child/package.json",
    "content": "{\n  \"name\": \"@vitejs/child\",\n  \"type\": \"module\",\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/module/package.json",
    "content": "{\n  \"name\": \"mylib\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/name/package.json",
    "content": "{\n  \"name\": \"mylib\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/noname/package.json",
    "content": "{}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/package.json",
    "content": "{\n  \"name\": \"named-testing-package\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/parent/index.ts",
    "content": "// @ts-expect-error not typed\nimport child from '@vitejs/child'\n\nexport default {\n  child,\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/packages/parent/package.json",
    "content": "{\n  \"name\": \"@vitejs/parent\",\n  \"type\": \"module\",\n  \"main\": \"./index.ts\",\n  \"dependencies\": {\n    \"@vitejs/child\": \"link:../child\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/__snapshots__/license.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`json 1`] = `\n\"[\n  {\n    \"name\": \"@vitejs/test-dep-licence-cc0\",\n    \"version\": \"0.0.0\",\n    \"identifier\": \"CC0-1.0\",\n    \"text\": \"CC0 1.0 Universal\\\\n\\\\n...\"\n  },\n  {\n    \"name\": \"@vitejs/test-dep-license-mit\",\n    \"version\": \"0.0.0\",\n    \"identifier\": \"MIT\",\n    \"text\": \"MIT License\\\\n\\\\nCopyright (c) ...\"\n  },\n  {\n    \"name\": \"@vitejs/test-dep-nested-license-isc\",\n    \"version\": \"0.0.0\",\n    \"identifier\": \"ISC\",\n    \"text\": \"Copyright (c) ...\"\n  }\n]\"\n`;\n\nexports[`markdown 1`] = `\n\"# Licenses\n\nThe app bundles dependencies which contain the following licenses:\n\n## @vitejs/test-dep-licence-cc0 - 0.0.0 (CC0-1.0)\n\nCC0 1.0 Universal\n\n...\n\n## @vitejs/test-dep-license-mit - 0.0.0 (MIT)\n\nMIT License\n\nCopyright (c) ...\n\n## @vitejs/test-dep-nested-license-isc - 0.0.0 (ISC)\n\nCopyright (c) ...\n\"\n`;\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/assetImportMetaUrl.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { parseAst } from 'rollup/parseAst'\nimport { assetImportMetaUrlPlugin } from '../../plugins/assetImportMetaUrl'\nimport { resolveConfig } from '../../config'\nimport { PartialEnvironment } from '../../baseEnvironment'\n\nasync function createAssetImportMetaurlPluginTransform() {\n  const config = await resolveConfig({ configFile: false }, 'serve')\n  const instance = assetImportMetaUrlPlugin(config)\n  const environment = new PartialEnvironment('client', config)\n\n  return async (code: string) => {\n    // @ts-expect-error transform.handler should exist\n    const result = await instance.transform.handler.call(\n      { environment, parse: parseAst },\n      code,\n      'foo.ts',\n    )\n    return result?.code || result\n  }\n}\n\ndescribe('assetImportMetaUrlPlugin', async () => {\n  const transform = await createAssetImportMetaurlPluginTransform()\n\n  test('variable between /', async () => {\n    expect(\n      await transform('new URL(`./foo/${dir}/index.js`, import.meta.url)'),\n    ).toMatchInlineSnapshot(\n      `\"new URL((import.meta.glob(\"./foo/*/index.js\", {\"eager\":true,\"import\":\"default\",\"query\":\"?url\"}))[\\`./foo/\\${dir}/index.js\\`], import.meta.url)\"`,\n    )\n  })\n\n  test('variable before non-/', async () => {\n    expect(\n      await transform('new URL(`./foo/${dir}.js`, import.meta.url)'),\n    ).toMatchInlineSnapshot(\n      `\"new URL((import.meta.glob(\"./foo/*.js\", {\"eager\":true,\"import\":\"default\",\"query\":\"?url\"}))[\\`./foo/\\${dir}.js\\`], import.meta.url)\"`,\n    )\n  })\n\n  test('two variables', async () => {\n    expect(\n      await transform('new URL(`./foo/${dir}${file}.js`, import.meta.url)'),\n    ).toMatchInlineSnapshot(\n      `\"new URL((import.meta.glob(\"./foo/*.js\", {\"eager\":true,\"import\":\"default\",\"query\":\"?url\"}))[\\`./foo/\\${dir}\\${file}.js\\`], import.meta.url)\"`,\n    )\n  })\n\n  test('two variables between /', async () => {\n    expect(\n      await transform(\n        'new URL(`./foo/${dir}${dir2}/index.js`, import.meta.url)',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new URL((import.meta.glob(\"./foo/*/index.js\", {\"eager\":true,\"import\":\"default\",\"query\":\"?url\"}))[\\`./foo/\\${dir}\\${dir2}/index.js\\`], import.meta.url)\"`,\n    )\n  })\n\n  test('ignore starting with a variable', async () => {\n    expect(\n      await transform('new URL(`${file}.js`, import.meta.url)'),\n    ).toMatchInlineSnapshot(`\"new URL(\\`\\${file}.js\\`, import.meta.url)\"`)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/css.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport type { InternalModuleFormat } from 'rolldown'\nimport MagicString from 'magic-string'\nimport { resolveConfig } from '../../config'\nimport type { InlineConfig } from '../../config'\nimport {\n  convertTargets,\n  cssPlugin,\n  cssUrlRE,\n  getEmptyChunkReplacer,\n  hoistAtRules,\n  injectInlinedCSS,\n  preprocessCSS,\n  resolveLibCssFilename,\n} from '../../plugins/css'\nimport { PartialEnvironment } from '../../baseEnvironment'\n\nconst dirname = import.meta.dirname\n\ndescribe('search css url function', () => {\n  test('some spaces before it', () => {\n    expect(\n      cssUrlRE.test(\"list-style-image: url('../images/bullet.jpg');\"),\n    ).toBe(true)\n  })\n\n  test('no space after colon', () => {\n    expect(cssUrlRE.test(\"list-style-image:url('../images/bullet.jpg');\")).toBe(\n      true,\n    )\n  })\n\n  test('at the beginning of line', () => {\n    expect(cssUrlRE.test(\"url('../images/bullet.jpg');\")).toBe(true)\n  })\n\n  test('as suffix of a function name', () => {\n    expect(\n      cssUrlRE.test(`@function svg-url($string) {\n      @return \"\";\n    }`),\n    ).toBe(false)\n  })\n\n  test('after parenthesis', () => {\n    expect(\n      cssUrlRE.test(\n        'mask-image: image(url(mask.png), skyblue, linear-gradient(rgba(0, 0, 0, 1.0), transparent));',\n      ),\n    ).toBe(true)\n  })\n\n  test('after comma', () => {\n    expect(\n      cssUrlRE.test(\n        'mask-image: image(skyblue,url(mask.png), linear-gradient(rgba(0, 0, 0, 1.0), transparent));',\n      ),\n    ).toBe(true)\n  })\n\n  test('should capture the full url with escaped parentheses', () => {\n    const css = 'background-image: url(public/awkward-name\\\\)2.png);'\n    const match = cssUrlRE.exec(css)\n    expect(match?.[1].trim()).toBe('public/awkward-name\\\\)2.png')\n  })\n})\n\ndescribe('css modules', () => {\n  test('css module compose/from path resolutions', async () => {\n    const { transform } = await createCssPluginTransform({\n      configFile: false,\n      resolve: {\n        alias: [\n          {\n            find: '@',\n            replacement: path.join(\n              import.meta.dirname,\n              './fixtures/css-module-compose',\n            ),\n          },\n        ],\n      },\n    })\n\n    const result = await transform(\n      `\\\n.foo {\nposition: fixed;\ncomposes: bar from '@/css/bar.module.css';\n}`,\n      '/css/foo.module.css',\n    )\n\n    expect(result.code).toMatchInlineSnapshot(\n      `\n      \"._bar_1b4ow_1 {\n        display: block;\n        background: #f0f;\n      }\n      ._foo_86148_1 {\n      position: fixed;\n      }\"\n    `,\n    )\n  })\n\n  test('custom generateScopedName', async () => {\n    const { transform } = await createCssPluginTransform({\n      configFile: false,\n      css: {\n        modules: {\n          generateScopedName: 'custom__[hash:base64:5]',\n        },\n      },\n    })\n    const css = `\\\n.foo {\n  color: red;\n}`\n    const result1 = await transform(css, '/foo.module.css') // server\n    const result2 = await transform(css, '/foo.module.css?direct') // client\n    expect(result1.code).toBe(result2.code)\n  })\n\n  test('custom generateScopedName with lightningcss', async () => {\n    const { transform } = await createCssPluginTransform({\n      configFile: false,\n      css: {\n        modules: {\n          generateScopedName: 'custom__[hash:base64:5]',\n        },\n        transformer: 'lightningcss',\n      },\n    })\n    const css = `\\\n.foo {\n  color: red;\n}`\n    const result1 = await transform(css, '/foo.module.css') // server\n    const result2 = await transform(css, '/foo.module.css?direct') // client\n    expect(result1.code).toBe(result2.code)\n  })\n})\n\ndescribe('hoist @ rules', () => {\n  test('hoist @import', async () => {\n    const css = `.foo{color:red;}@import \"bla\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(`@import \"bla\";.foo{color:red;}`)\n  })\n\n  test('hoist @import url with semicolon', async () => {\n    const css = `.foo{color:red;}@import url(\"bla;bla\");`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(`@import url(\"bla;bla\");.foo{color:red;}`)\n  })\n\n  test('hoist @import url data with semicolon', async () => {\n    const css = `.foo{color:red;}@import url(data:image/png;base64,iRxVB0);`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(\n      `@import url(data:image/png;base64,iRxVB0);.foo{color:red;}`,\n    )\n  })\n\n  test('hoist @import with semicolon in quotes', async () => {\n    const css = `.foo{color:red;}@import \"bla;bar\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(`@import \"bla;bar\";.foo{color:red;}`)\n  })\n\n  test('hoist @charset', async () => {\n    const css = `.foo{color:red;}@charset \"utf-8\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(`@charset \"utf-8\";.foo{color:red;}`)\n  })\n\n  test('hoist one @charset only', async () => {\n    const css = `.foo{color:red;}@charset \"utf-8\";@charset \"utf-8\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(`@charset \"utf-8\";.foo{color:red;}`)\n  })\n\n  test('hoist @import and @charset', async () => {\n    const css = `.foo{color:red;}@import \"bla\";@charset \"utf-8\";.bar{color:green;}@import \"baz\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(\n      `@charset \"utf-8\";@import \"bla\";@import \"baz\";.foo{color:red;}.bar{color:green;}`,\n    )\n  })\n\n  test('dont hoist @import in comments', async () => {\n    const css = `.foo{color:red;}/* @import \"bla\"; */@import \"bar\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(`@import \"bar\";.foo{color:red;}/* @import \"bla\"; */`)\n  })\n\n  test('dont hoist @charset in comments', async () => {\n    const css = `.foo{color:red;}/* @charset \"utf-8\"; */@charset \"utf-8\";`\n    const result = await hoistAtRules(css)\n    expect(result).toBe(\n      `@charset \"utf-8\";.foo{color:red;}/* @charset \"utf-8\"; */`,\n    )\n  })\n\n  test('dont hoist @import and @charset in comments', async () => {\n    const css = `\n.foo{color:red;}\n/*\n  @import \"bla\";\n*/\n@charset \"utf-8\";\n/*\n  @charset \"utf-8\";\n  @import \"bar\";\n*/\n@import \"baz\";`\n    const result = await hoistAtRules(css)\n    expect(result).toMatchInlineSnapshot(`\n      \"@charset \"utf-8\";@import \"baz\";\n      .foo{color:red;}\n      /*\n        @import \"bla\";\n      */\n\n      /*\n        @charset \"utf-8\";\n        @import \"bar\";\n      */\n      \"\n    `)\n  })\n})\n\nasync function createCssPluginTransform(inlineConfig: InlineConfig = {}) {\n  const config = await resolveConfig(inlineConfig, 'serve')\n  const environment = new PartialEnvironment('client', config)\n\n  const { transform, buildStart } = cssPlugin(config)\n\n  // @ts-expect-error buildStart is function\n  await buildStart.call({})\n\n  return {\n    async transform(code: string, id: string) {\n      // @ts-expect-error transform.handler is function\n      return await transform.handler.call(\n        {\n          addWatchFile() {\n            return\n          },\n          environment,\n        },\n        code,\n        id,\n      )\n    },\n  }\n}\n\ndescribe('convertTargets', () => {\n  test('basic cases', () => {\n    expect(convertTargets('es2018')).toStrictEqual({\n      chrome: 4128768,\n      edge: 5177344,\n      firefox: 3801088,\n      safari: 786432,\n      ios_saf: 786432,\n      opera: 3276800,\n    })\n    expect(convertTargets(['safari13.1', 'ios13', 'node14'])).toStrictEqual({\n      ios_saf: 851968,\n      safari: 852224,\n    })\n  })\n\n  test('supports es6 as an alias of es2015', () => {\n    expect(convertTargets('es6')).toStrictEqual(convertTargets('es2015'))\n  })\n})\n\ndescribe('getEmptyChunkReplacer', () => {\n  test('replaces import call', () => {\n    const code = `\\\nimport \"some-module\";\nimport \"pure_css_chunk.js\";\nimport \"other-module\";`\n\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'es')\n    const replaced = replacer(code)\n    expect(replaced.length).toBe(code.length)\n    expect(replaced).toMatchInlineSnapshot(`\n      \"import \"some-module\";\n      /* empty css             */\n      import \"other-module\";\"\n    `)\n  })\n\n  test('replaces import call without new lines', () => {\n    const code = `import \"some-module\";import \"pure_css_chunk.js\";import \"other-module\";`\n\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'es')\n    const replaced = replacer(code)\n    expect(replaced.length).toBe(code.length)\n    expect(replaced).toMatchInlineSnapshot(\n      `\"import \"some-module\";/* empty css             */import \"other-module\";\"`,\n    )\n  })\n\n  test('replaces require call', () => {\n    const code = `\\\nrequire(\"some-module\");\nrequire(\"pure_css_chunk.js\");\nrequire(\"other-module\");`\n\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')\n    const replaced = replacer(code)\n    expect(replaced.length).toBe(code.length)\n    expect(replaced).toMatchInlineSnapshot(`\n      \"require(\"some-module\");\n      ;/* empty css              */\n      require(\"other-module\");\"\n    `)\n  })\n\n  test('replaces require call in minified code without new lines', () => {\n    const code = `require(\"some-module\");require(\"pure_css_chunk.js\");require(\"other-module\");`\n\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')\n    const replaced = replacer(code)\n    expect(replaced.length).toBe(code.length)\n    expect(replaced).toMatchInlineSnapshot(\n      `\"require(\"some-module\");;/* empty css              */require(\"other-module\");\"`,\n    )\n  })\n\n  test('replaces require call in minified code that uses comma operator', () => {\n    const code =\n      'require(\"some-module\"),require(\"pure_css_chunk.js\"),require(\"other-module\");'\n\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')\n    const newCode = replacer(code)\n    expect(newCode.length).toBe(code.length)\n    expect(newCode).toMatchInlineSnapshot(\n      `\"require(\"some-module\"),/* empty css               */require(\"other-module\");\"`,\n    )\n    // So there should be no pure css chunk anymore\n    expect(newCode).not.toContain('pure_css_chunk.js')\n  })\n\n  test('replaces require call in minified code that uses comma operator 2', () => {\n    const code = 'require(\"pure_css_chunk.js\"),console.log();'\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')\n    const newCode = replacer(code)\n    expect(newCode.length).toBe(code.length)\n    expect(newCode).toMatchInlineSnapshot(\n      `\"/* empty css               */console.log();\"`,\n    )\n    expect(newCode).not.toContain('pure_css_chunk.js')\n  })\n\n  test('replaces require call in minified code that uses comma operator followed by assignment', () => {\n    const code =\n      'require(\"some-module\"),require(\"pure_css_chunk.js\");const v=require(\"other-module\");'\n\n    const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs')\n    const newCode = replacer(code)\n    expect(newCode.length).toBe(code.length)\n    expect(newCode).toMatchInlineSnapshot(\n      `\"require(\"some-module\");/* empty css               */const v=require(\"other-module\");\"`,\n    )\n    expect(newCode).not.toContain('pure_css_chunk.js')\n  })\n})\n\ndescribe('preprocessCSS', () => {\n  test('works', async () => {\n    const resolvedConfig = await resolveConfig({ configFile: false }, 'serve')\n    const result = await preprocessCSS(\n      `\\\n.foo {\n  color:red;\n  background: url(./foo.png);\n}`,\n      'foo.css',\n      resolvedConfig,\n    )\n    expect(result.code).toMatchInlineSnapshot(`\n      \".foo {\n        color:red;\n        background: url(./foo.png);\n      }\"\n    `)\n  })\n\n  test('works with lightningcss', async () => {\n    const resolvedConfig = await resolveConfig(\n      {\n        configFile: false,\n        css: { transformer: 'lightningcss' },\n      },\n      'serve',\n    )\n    const result = await preprocessCSS(\n      `\\\n.foo {\n  color: red;\n  background: url(./foo.png);\n}`,\n      'foo.css',\n      resolvedConfig,\n    )\n    expect(result.code).toMatchInlineSnapshot(`\n      \".foo {\n        color: red;\n        background: url(\"./foo.png\");\n      }\n      \"\n    `)\n  })\n})\n\ndescribe('resolveLibCssFilename', () => {\n  test('use name from package.json', () => {\n    const filename = resolveLibCssFilename(\n      {\n        entry: 'mylib.js',\n      },\n      path.resolve(dirname, '../packages/name'),\n    )\n    expect(filename).toBe('mylib.css')\n  })\n\n  test('set cssFileName', () => {\n    const filename = resolveLibCssFilename(\n      {\n        entry: 'mylib.js',\n        cssFileName: 'style',\n      },\n      path.resolve(dirname, '../packages/noname'),\n    )\n    expect(filename).toBe('style.css')\n  })\n\n  test('use fileName if set', () => {\n    const filename = resolveLibCssFilename(\n      {\n        entry: 'mylib.js',\n        fileName: 'custom-name',\n      },\n      path.resolve(dirname, '../packages/name'),\n    )\n    expect(filename).toBe('custom-name.css')\n  })\n\n  test('use fileName if set and has array entry', () => {\n    const filename = resolveLibCssFilename(\n      {\n        entry: ['mylib.js', 'mylib2.js'],\n        fileName: 'custom-name',\n      },\n      path.resolve(dirname, '../packages/name'),\n    )\n    expect(filename).toBe('custom-name.css')\n  })\n})\n\ndescribe('injectInlinedCSS', () => {\n  function getInlinedCSSInjectedCode(\n    code: string,\n    format: InternalModuleFormat,\n  ) {\n    const s = new MagicString(code)\n    injectInlinedCSS(\n      s,\n      {\n        error(e) {\n          throw e\n        },\n      },\n      code,\n      format,\n      'injectCSS();',\n    )\n    return s.toString()\n  }\n\n  test('should inject CSS for iife without exports from esm', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function() {\n\n\"use strict\";\n\n//#region src/index.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\");\n})();\n\n//#endregion\n})();`,\n      'iife',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function() {\n\n      \"use strict\";injectCSS();\n\n      //#region src/index.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\");\n      })();\n\n      //#endregion\n      })();\"\n    `)\n  })\n\n  test('should inject helper for iife without exports from cjs', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function() {\n\n\n//#region src/index.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\");\n})();\n\n//#endregion\n})();`,\n      'iife',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function() {injectCSS();\n\n\n      //#region src/index.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\");\n      })();\n\n      //#endregion\n      })();\"\n    `)\n  })\n\n  test('should inject helper for iife with exports', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `var lib = (function(exports) {\n\n\n//#region entry.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\");\n})();\nconst foo = \"foo\";\n\n//#endregion\nexports.foo = foo;\nreturn exports;\n})({});`,\n      'iife',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"var lib = (function(exports) {injectCSS();\n\n\n      //#region entry.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\");\n      })();\n      const foo = \"foo\";\n\n      //#endregion\n      exports.foo = foo;\n      return exports;\n      })({});\"\n    `)\n  })\n\n  test('should inject helper for iife with nested name', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `this.nested = this.nested || {};\nthis.nested.lib = (function(exports) {\n\nObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\n//#region a.ts\n\tconst foo = \"foo\";\n\n//#endregion\nexports.foo = foo;\nreturn exports;\n})({});`,\n      'iife',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"this.nested = this.nested || {};\n      this.nested.lib = (function(exports) {injectCSS();\n\n      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\n      //#region a.ts\n      \tconst foo = \"foo\";\n\n      //#endregion\n      exports.foo = foo;\n      return exports;\n      })({});\"\n    `)\n  })\n\n  test('should inject helper for umd without exports', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function(factory) {\n\n  typeof define === 'function' && define.amd ? define([], factory) :\n  factory();\n})(function() {\n\n//#region entry.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\");\n})();\n\n//#endregion\n});`,\n      'umd',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function(factory) {\n\n        typeof define === 'function' && define.amd ? define([], factory) :\n        factory();\n      })(function() {injectCSS();\n\n      //#region entry.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\");\n      })();\n\n      //#endregion\n      });\"\n    `)\n  })\n\n  test('should inject helper for umd with exports', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function(global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :\n  typeof define === 'function' && define.amd ? define(['exports'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.lib = {})));\n})(this, function(exports) {\n\n//#region entry.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\");\n})();\nconst foo = \"foo\";\n\n//#endregion\nexports.foo = foo;\n});`,\n      'umd',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function(global, factory) {\n        typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :\n        typeof define === 'function' && define.amd ? define(['exports'], factory) :\n        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.lib = {})));\n      })(this, function(exports) {injectCSS();\n\n      //#region entry.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\");\n      })();\n      const foo = \"foo\";\n\n      //#endregion\n      exports.foo = foo;\n      });\"\n    `)\n  })\n\n  test('should inject helper for umd with only default export', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function(global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports =  factory() :\n  typeof define === 'function' && define.amd ? define([], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.lib = factory()));\n})(this, function() {\n\n//#region entry.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\");\n})();\nvar index_default = \"foo\";\n\n//#endregion\nreturn index_default;\n});`,\n      'umd',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function(global, factory) {\n        typeof exports === 'object' && typeof module !== 'undefined' ? module.exports =  factory() :\n        typeof define === 'function' && define.amd ? define([], factory) :\n        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, (global.lib = factory()));\n      })(this, function() {injectCSS();\n\n      //#region entry.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\");\n      })();\n      var index_default = \"foo\";\n\n      //#endregion\n      return index_default;\n      });\"\n    `)\n  })\n\n  test('should inject helper for umd with nested name', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function(global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :\n  typeof define === 'function' && define.amd ? define(['exports'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.nested = global.nested || {},global.nested.lib = {})));\n})(this, function(exports) {\nObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\n//#region a.ts\n\tconst foo = \"foo\";\n\n//#endregion\nexports.foo = foo;\n});`,\n      'umd',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function(global, factory) {\n        typeof exports === 'object' && typeof module !== 'undefined' ?  factory(exports) :\n        typeof define === 'function' && define.amd ? define(['exports'], factory) :\n        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.nested = global.nested || {},global.nested.lib = {})));\n      })(this, function(exports) {injectCSS();\n      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\n      //#region a.ts\n      \tconst foo = \"foo\";\n\n      //#endregion\n      exports.foo = foo;\n      });\"\n    `)\n  })\n\n  test('should inject multiple helpers', async () => {\n    const result = getInlinedCSSInjectedCode(\n      `(function() {\n\n\"use strict\";\n\n//#region src/index.js\n(async () => {\n\tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n\tconsole.log(\"foo\", { ...\"foo\" });\n})();\n\n//#endregion\n})();`,\n      'iife',\n    )\n    expect(result).toMatchInlineSnapshot(`\n      \"(function() {\n\n      \"use strict\";injectCSS();\n\n      //#region src/index.js\n      (async () => {\n      \tawait new Promise((resolve) => setTimeout(resolve, 1e3));\n      \tconsole.log(\"foo\", { ...\"foo\" });\n      })();\n\n      //#endregion\n      })();\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/define.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { rolldown } from 'rolldown'\nimport { definePlugin } from '../../plugins/define'\nimport { resolveConfig } from '../../config'\nimport { PartialEnvironment } from '../../baseEnvironment'\n\nasync function createDefinePluginTransform(\n  define: Record<string, any> = {},\n  isSsrDev = false,\n) {\n  const ssr = isSsrDev\n  const build = !isSsrDev\n  const config = await resolveConfig(\n    { configFile: false, define, environments: { ssr: {} } },\n    build ? 'build' : 'serve',\n  )\n  const instance = definePlugin(config)\n  const environment = new PartialEnvironment(ssr ? 'ssr' : 'client', config)\n\n  return async (code: string) => {\n    if (isSsrDev) {\n      // @ts-expect-error transform.handler should exist\n      const result = await instance.transform.handler.call(\n        { environment },\n        code,\n        'foo.ts',\n      )\n      return result?.code || result\n    } else {\n      const bundler = await rolldown({\n        input: 'entry.js',\n        plugins: [\n          {\n            name: 'test',\n            resolveId(id) {\n              if (id === 'entry.js') {\n                return '\\0' + id\n              }\n            },\n            load(id) {\n              if (id === '\\0entry.js') {\n                return code\n              }\n            },\n          },\n          {\n            name: 'native:define',\n            options: (definePlugin(config).options! as any).bind({\n              environment,\n            }),\n          },\n        ],\n        experimental: {\n          attachDebugInfo: 'none',\n        },\n      })\n      return (await bundler.generate()).output[0].code\n    }\n  }\n}\n\ndescribe('definePlugin (SSR dev)', () => {\n  const createJsDefinePluginTransform = (define: Record<string, any> = {}) =>\n    createDefinePluginTransform(define, true)\n\n  test('replaces custom define', async () => {\n    const transform = await createJsDefinePluginTransform({\n      __APP_VERSION__: JSON.stringify('1.0'),\n    })\n    expect(await transform('export const version = __APP_VERSION__ ;')).toBe(\n      'export const version = \"1.0\";\\n',\n    )\n    expect(await transform('export const version = __APP_VERSION__;')).toBe(\n      'export const version = \"1.0\";\\n',\n    )\n  })\n\n  test('should not replace if not defined', async () => {\n    const transform = await createJsDefinePluginTransform({\n      __APP_VERSION__: JSON.stringify('1.0'),\n    })\n    expect(await transform('export const version = \"1.0\";')).toBe(undefined)\n    expect(\n      await transform('export const version = import.meta.SOMETHING'),\n    ).toBe(undefined)\n  })\n\n  test('replace import.meta.env when it is a invalid json', async () => {\n    const transform = await createJsDefinePluginTransform({\n      'import.meta.env.LEGACY': '__VITE_IS_LEGACY__',\n    })\n\n    expect(\n      await transform(\n        'export const isLegacy = import.meta.env.LEGACY;\\nimport.meta.env.UNDEFINED && console.log(import.meta.env.UNDEFINED);',\n      ),\n    ).toMatchInlineSnapshot(`\n      \"export const isLegacy = __VITE_IS_LEGACY__;\n      import.meta.env.UNDEFINED && console.log(import.meta.env.UNDEFINED);\n      \"\n    `)\n  })\n})\n\ndescribe('native definePlugin', () => {\n  test('replaces custom define', async () => {\n    const transform = await createDefinePluginTransform({\n      __APP_VERSION__: JSON.stringify('1.0'),\n    })\n    expect(await transform('export const version = __APP_VERSION__;')).toBe(\n      'const version = \"1.0\";\\nexport { version };\\n',\n    )\n    expect(await transform('export const version = __APP_VERSION__ ;')).toBe(\n      'const version = \"1.0\";\\nexport { version };\\n',\n    )\n  })\n\n  test('should not replace if not defined', async () => {\n    const transform = await createDefinePluginTransform({\n      __APP_VERSION__: JSON.stringify('1.0'),\n    })\n    expect(await transform('export const version = \"1.0\";')).toBe(\n      'const version = \"1.0\";\\nexport { version };\\n',\n    )\n    expect(\n      await transform('export const version = import.meta.SOMETHING'),\n    ).toBe('const version = import.meta.SOMETHING;\\nexport { version };\\n')\n  })\n\n  test('replaces import.meta.env.SSR with false', async () => {\n    const transform = await createDefinePluginTransform()\n    expect(await transform('export const isSSR = import.meta.env.SSR;')).toBe(\n      'const isSSR = false;\\nexport { isSSR };\\n',\n    )\n  })\n\n  test('preserve import.meta.hot with override', async () => {\n    // assert that the default behavior is to replace import.meta.hot with undefined\n    const transform = await createDefinePluginTransform()\n    expect(await transform('export const hot = import.meta.hot;')).toBe(\n      'const hot = void 0;\\nexport { hot };\\n',\n    )\n    // assert that we can specify a user define to preserve import.meta.hot\n    const overrideTransform = await createDefinePluginTransform({\n      'import.meta.hot': 'import.meta.hot',\n    })\n    expect(await overrideTransform('export const hot = import.meta.hot;')).toBe(\n      'const hot = import.meta.hot;\\nexport { hot };\\n',\n    )\n  })\n\n  test('replace import.meta.env.UNKNOWN with undefined', async () => {\n    const transform = await createDefinePluginTransform()\n    expect(await transform('export const foo = import.meta.env.UNKNOWN;')).toBe(\n      'const foo = void 0;\\nexport { foo };\\n',\n    )\n  })\n\n  test('leave import.meta.env[\"UNKNOWN\"] to runtime', async () => {\n    const transform = await createDefinePluginTransform()\n    expect(\n      await transform('export const foo = import.meta.env[\"UNKNOWN\"];'),\n    ).toMatch(/const foo = .*\\[\"UNKNOWN\"\\];\\nexport \\{ foo \\};\\n/s)\n  })\n\n  test('preserve import.meta.env.UNKNOWN with override', async () => {\n    const transform = await createDefinePluginTransform({\n      'import.meta.env.UNKNOWN': 'import.meta.env.UNKNOWN',\n    })\n    expect(await transform('export const foo = import.meta.env.UNKNOWN;')).toBe(\n      'const foo = import.meta.env.UNKNOWN;\\nexport { foo };\\n',\n    )\n  })\n\n  test('replace import.meta.env when it is a invalid json', async () => {\n    const transform = await createDefinePluginTransform({\n      'import.meta.env.LEGACY': '__VITE_IS_LEGACY__',\n    })\n\n    expect(\n      await transform(\n        'export const isLegacy = import.meta.env.LEGACY;\\nimport.meta.env.UNDEFINED && console.log(import.meta.env.UNDEFINED);',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"const isLegacy = __VITE_IS_LEGACY__;\\nexport { isLegacy };\\n\"`,\n    )\n  })\n\n  test('replace bare import.meta.env', async () => {\n    const transform = await createDefinePluginTransform()\n    expect(await transform('export const env = import.meta.env;')).toMatch(\n      /const env = .*;\\nexport \\{ env \\};\\n/s,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/dynamicImportVar/__snapshots__/parse.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`parse positives > ? in url 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mo\\\\\\\\?ds/*.js\", {\"query\":\"?url\",\"import\":\"*\"})), \\`./mo?ds/\\${base ?? foo}.js\\`)\"`;\n\nexports[`parse positives > ? in variables 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mods/*.js\", {\"query\":\"?raw\",\"import\":\"*\"})), \\`./mods/\\${base ?? foo}.js\\`)\"`;\n\nexports[`parse positives > ? in worker 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mo\\\\\\\\?ds/*.js\", {\"query\":\"?worker\",\"import\":\"*\"})), \\`./mo?ds/\\${base ?? foo}.js\\`)\"`;\n\nexports[`parse positives > alias path 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mods/*.js\")), \\`./mods/\\${base}.js\\`)\"`;\n\nexports[`parse positives > alias path with multi ../ 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"../../*.js\")), \\`../../\\${base}.js\\`)\"`;\n\nexports[`parse positives > basic 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mods/*.js\")), \\`./mods/\\${base}.js\\`)\"`;\n\nexports[`parse positives > with ../ and itself 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"../dynamicImportVar/*.js\")), \\`./\\${name}.js\\`)\"`;\n\nexports[`parse positives > with multi ../ and itself 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"../../plugins/dynamicImportVar/*.js\")), \\`./\\${name}.js\\`)\"`;\n\nexports[`parse positives > with query 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mods/*.js\", {\"query\":\"?foo=bar\"})), \\`./mods/\\${base}.js\\`)\"`;\n\nexports[`parse positives > with query raw 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mods/*.js\", {\"query\":\"?raw\",\"import\":\"*\"})), \\`./mods/\\${base}.js\\`)\"`;\n\nexports[`parse positives > with query url 1`] = `\"__variableDynamicImportRuntimeHelper((import.meta.glob(\"./mods/*.js\", {\"query\":\"?url\",\"import\":\"*\"})), \\`./mods/\\${base}.js\\`)\"`;\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hello.js",
    "content": "export function hello() {\n  return 'hello'\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/dynamicImportVar/mods/hi.js",
    "content": "export function hi() {\n  return 'hi'\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/dynamicImportVar/parse.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { describe, expect, it } from 'vitest'\nimport { transformDynamicImport } from '../../../plugins/dynamicImportVars'\nimport { normalizePath } from '../../../utils'\nimport { isWindows } from '../../../../shared/utils'\n\nconst dirname = import.meta.dirname\n\nasync function run(input: string) {\n  const { glob, rawPattern } =\n    (await transformDynamicImport(\n      input,\n      normalizePath(resolve(dirname, 'index.js')),\n      (id) =>\n        id\n          .replace('@', resolve(dirname, './mods/'))\n          .replace('#', resolve(dirname, '../../')),\n      dirname,\n    )) || {}\n  return `__variableDynamicImportRuntimeHelper(${glob}, \\`${rawPattern}\\`)`\n}\n\ndescribe('parse positives', () => {\n  it('basic', async () => {\n    expect(await run('`./mods/${base}.js`')).toMatchSnapshot()\n  })\n\n  it('alias path', async () => {\n    expect(await run('`@/${base}.js`')).toMatchSnapshot()\n  })\n\n  it('alias path with multi ../', async () => {\n    expect(await run('`#/${base}.js`')).toMatchSnapshot()\n  })\n\n  it('with query', async () => {\n    expect(await run('`./mods/${base}.js?foo=bar`')).toMatchSnapshot()\n  })\n\n  it('with query raw', async () => {\n    expect(await run('`./mods/${base}.js?raw`')).toMatchSnapshot()\n  })\n\n  it('with query url', async () => {\n    expect(await run('`./mods/${base}.js?url`')).toMatchSnapshot()\n  })\n\n  it('? in variables', async () => {\n    expect(await run('`./mods/${base ?? foo}.js?raw`')).toMatchSnapshot()\n  })\n\n  // ? is not escaped on windows (? cannot be used as a filename on windows)\n  it.skipIf(isWindows)('? in url', async () => {\n    expect(await run('`./mo?ds/${base ?? foo}.js?url`')).toMatchSnapshot()\n  })\n\n  // ? is not escaped on windows (? cannot be used as a filename on windows)\n  it.skipIf(isWindows)('? in worker', async () => {\n    expect(await run('`./mo?ds/${base ?? foo}.js?worker`')).toMatchSnapshot()\n  })\n\n  it('with ../ and itself', async () => {\n    expect(await run('`../dynamicImportVar/${name}.js`')).toMatchSnapshot()\n  })\n\n  it('with multi ../ and itself', async () => {\n    expect(\n      await run('`../../plugins/dynamicImportVar/${name}.js`'),\n    ).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/esbuild.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport type { ResolvedConfig, UserConfig } from '../../config'\nimport {\n  injectEsbuildHelpers,\n  resolveEsbuildTranspileOptions,\n  transformWithEsbuild,\n} from '../../plugins/esbuild'\nimport { normalizePath } from '../../utils'\n\ndescribe('resolveEsbuildTranspileOptions', () => {\n  test('resolve default', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          target: 'es2020',\n          minify: 'esbuild',\n        },\n        esbuild: {\n          keepNames: true,\n        },\n      }),\n      'es',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: 'es2020',\n      format: 'esm',\n      keepNames: true,\n      minify: true,\n      treeShaking: true,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n\n  test('resolve esnext no minify', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          target: 'esnext',\n          minify: false,\n        },\n        esbuild: {\n          keepNames: true,\n        },\n      }),\n      'es',\n    )\n    expect(options).toEqual(null)\n  })\n\n  test('resolve specific minify options', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          minify: 'esbuild',\n        },\n        esbuild: {\n          keepNames: true,\n          minifyIdentifiers: false,\n        },\n      }),\n      'es',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: undefined,\n      format: 'esm',\n      keepNames: true,\n      minify: false,\n      minifyIdentifiers: false,\n      minifySyntax: true,\n      minifyWhitespace: true,\n      treeShaking: true,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n\n  test('resolve no minify', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          target: 'es2020',\n          minify: false,\n        },\n        esbuild: {\n          keepNames: true,\n        },\n      }),\n      'es',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: 'es2020',\n      format: 'esm',\n      keepNames: true,\n      minify: false,\n      minifyIdentifiers: false,\n      minifySyntax: false,\n      minifyWhitespace: false,\n      treeShaking: false,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n\n  test('resolve es lib', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          minify: 'esbuild',\n          lib: {\n            entry: './somewhere.js',\n          },\n        },\n        esbuild: {\n          keepNames: true,\n        },\n      }),\n      'es',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: undefined,\n      format: 'esm',\n      keepNames: true,\n      minify: false,\n      minifyIdentifiers: true,\n      minifySyntax: true,\n      minifyWhitespace: false,\n      treeShaking: true,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n\n  test('resolve cjs lib', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          minify: 'esbuild',\n          lib: {\n            entry: './somewhere.js',\n          },\n        },\n        esbuild: {\n          keepNames: true,\n        },\n      }),\n      'cjs',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: undefined,\n      format: 'cjs',\n      keepNames: true,\n      minify: true,\n      treeShaking: true,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n\n  test('resolve es lib with specific minify options', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          minify: 'esbuild',\n          lib: {\n            entry: './somewhere.js',\n          },\n        },\n        esbuild: {\n          keepNames: true,\n          minifyIdentifiers: true,\n          minifyWhitespace: true,\n        },\n      }),\n      'es',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: undefined,\n      format: 'esm',\n      keepNames: true,\n      minify: false,\n      minifyIdentifiers: true,\n      minifySyntax: true,\n      minifyWhitespace: false,\n      treeShaking: true,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n\n  test('resolve cjs lib with specific minify options', () => {\n    const options = resolveEsbuildTranspileOptions(\n      defineResolvedConfig({\n        build: {\n          minify: 'esbuild',\n          lib: {\n            entry: './somewhere.js',\n          },\n        },\n        esbuild: {\n          keepNames: true,\n          minifyIdentifiers: true,\n          minifySyntax: false,\n          treeShaking: true,\n        },\n      }),\n      'cjs',\n    )\n    expect(options).toEqual({\n      loader: 'js',\n      target: undefined,\n      format: 'cjs',\n      keepNames: true,\n      minify: false,\n      minifyIdentifiers: true,\n      minifySyntax: false,\n      minifyWhitespace: true,\n      treeShaking: true,\n      supported: {\n        'dynamic-import': true,\n        'import-meta': true,\n      },\n    })\n  })\n})\n\ndescribe('transformWithEsbuild', () => {\n  test('not throw on inline sourcemap', async () => {\n    const result = await transformWithEsbuild(`const foo = 'bar'`, '', {\n      sourcemap: 'inline',\n    })\n    expect(result?.code).toBeTruthy()\n    expect(result?.map).toBeTruthy()\n  })\n\n  test('correctly overrides TS configuration and applies automatic transform', async () => {\n    const jsxImportSource = 'bar'\n    const result = await transformWithEsbuild(\n      'const foo = () => <></>',\n      'baz.jsx',\n      {\n        tsconfigRaw: {\n          compilerOptions: {\n            jsx: 'preserve',\n          },\n        },\n        jsx: 'automatic',\n        jsxImportSource,\n      },\n    )\n    expect(result?.code).toContain(`${jsxImportSource}/jsx-runtime`)\n    expect(result?.code).toContain('/* @__PURE__ */')\n  })\n\n  test('correctly overrides TS configuration and preserves code', async () => {\n    const foo = 'const foo = () => <></>'\n    const result = await transformWithEsbuild(foo, 'baz.jsx', {\n      tsconfigRaw: {\n        compilerOptions: {\n          jsx: 'react-jsx',\n        },\n      },\n      jsx: 'preserve',\n    })\n    expect(result?.code).toContain(foo)\n  })\n\n  test('correctly overrides TS configuration and transforms code', async () => {\n    const jsxFactory = 'h',\n      jsxFragment = 'bar'\n    const result = await transformWithEsbuild(\n      'const foo = () => <></>',\n      'baz.jsx',\n      {\n        tsconfigRaw: {\n          compilerOptions: {\n            jsxFactory: 'g',\n            jsxFragmentFactory: 'foo',\n            jsxImportSource: 'baz',\n          },\n        },\n        jsx: 'transform',\n        jsxFactory,\n        jsxFragment,\n      },\n    )\n    expect(result?.code).toContain(\n      `/* @__PURE__ */ ${jsxFactory}(${jsxFragment}, null)`,\n    )\n  })\n\n  describe('useDefineForClassFields', async () => {\n    const transformClassCode = async (\n      target: string,\n      tsconfigCompilerOptions: {\n        target?: string\n        useDefineForClassFields?: boolean\n      },\n    ) => {\n      const result = await transformWithEsbuild(\n        `\n          class foo {\n            bar = 'bar'\n          }\n        `,\n        normalizePath(path.resolve(import.meta.dirname, 'bar.ts')),\n        {\n          target,\n          tsconfigRaw: { compilerOptions: tsconfigCompilerOptions },\n        },\n      )\n      return result?.code\n    }\n\n    const [\n      defineForClassFieldsTrueTransformedCode,\n      defineForClassFieldsTrueLowerTransformedCode,\n      defineForClassFieldsFalseTransformedCode,\n    ] = await Promise.all([\n      transformClassCode('esnext', {\n        useDefineForClassFields: true,\n      }),\n      transformClassCode('es2021', {\n        useDefineForClassFields: true,\n      }),\n      transformClassCode('esnext', {\n        useDefineForClassFields: false,\n      }),\n    ])\n\n    test('target: esnext and tsconfig.target: esnext => true', async () => {\n      const actual = await transformClassCode('esnext', {\n        target: 'esnext',\n      })\n      expect(actual).toBe(defineForClassFieldsTrueTransformedCode)\n    })\n\n    test('target: es2021 and tsconfig.target: esnext => true', async () => {\n      const actual = await transformClassCode('es2021', {\n        target: 'esnext',\n      })\n      expect(actual).toBe(defineForClassFieldsTrueLowerTransformedCode)\n    })\n\n    test('target: es2021 and tsconfig.target: es2021 => false', async () => {\n      const actual = await transformClassCode('es2021', {\n        target: 'es2021',\n      })\n      expect(actual).toBe(defineForClassFieldsFalseTransformedCode)\n    })\n\n    test('target: esnext and tsconfig.target: es2021 => false', async () => {\n      const actual = await transformClassCode('esnext', {\n        target: 'es2021',\n      })\n      expect(actual).toBe(defineForClassFieldsFalseTransformedCode)\n    })\n\n    test('target: es2022 and tsconfig.target: es2022 => true', async () => {\n      const actual = await transformClassCode('es2022', {\n        target: 'es2022',\n      })\n      expect(actual).toBe(defineForClassFieldsTrueTransformedCode)\n    })\n\n    test('target: es2022 and tsconfig.target: undefined => false', async () => {\n      const actual = await transformClassCode('es2022', {\n        target: undefined,\n      })\n      expect(actual).toBe(defineForClassFieldsFalseTransformedCode)\n    })\n  })\n})\n\ndescribe('injectEsbuildHelpers', () => {\n  test('injects helpers in IIFE format', () => {\n    const esbuildCode =\n      'var $=function(){};var MyLib=(function(){\"use strict\";return 42;})()'\n    const result = injectEsbuildHelpers(esbuildCode, 'iife')\n    expect(result).toBe(\n      'var MyLib=(function(){\"use strict\";var $=function(){};return 42;})()',\n    )\n  })\n\n  test('injects helpers in IIFE format (pre esbuild 0.25.9)', () => {\n    const esbuildCode =\n      'var $=function(){};var MyLib=function(){\"use strict\";return 42;}()'\n    const result = injectEsbuildHelpers(esbuildCode, 'iife')\n    expect(result).toBe(\n      'var MyLib=function(){\"use strict\";var $=function(){};return 42;}()',\n    )\n  })\n\n  test('injects helpers in UMD format', () => {\n    const esbuildCode =\n      'var $=function(){};(function(global){\"use strict\";return 42;})'\n    const result = injectEsbuildHelpers(esbuildCode, 'umd')\n    expect(result).toBe(\n      '(function(global){\"use strict\";var $=function(){};return 42;})',\n    )\n  })\n\n  test('handles helpers with special characters', () => {\n    const esbuildCode =\n      'var $$=function(){};var MyLib=(function(){\"use strict\";return 42;})()'\n    const result = injectEsbuildHelpers(esbuildCode, 'iife')\n    expect(result).toContain('\"use strict\";var $$=function(){};')\n  })\n})\n\n/**\n * Helper for `resolveEsbuildTranspileOptions` to created resolved config with types.\n * Note: The function only uses `build.target`, `build.minify` and `esbuild` options.\n */\nfunction defineResolvedConfig(config: UserConfig): ResolvedConfig {\n  return config as any\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/css-module-compose/css/bar.module.css",
    "content": ".bar {\n  display: block;\n  background: #f0f;\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-licence-cc0/index.js",
    "content": "// Avoid to be inlined completely: https://github.com/rolldown/rolldown/issues/8100\nconsole.log()\n\nexport default 'ok'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-licence-cc0/licence",
    "content": "CC0 1.0 Universal\n\n...\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-licence-cc0/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-licence-cc0\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"license\": \"CC0-1.0\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-mit/index.js",
    "content": "import nestedDep from '@vitejs/test-dep-nested-license-isc'\n\nexport default 'ok' + nestedDep\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-mit/license",
    "content": "MIT License\n\nCopyright (c) ...\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-license-mit/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-license-mit\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@vitejs/test-dep-nested-license-isc\": \"file:../dep-nested-license-isc\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-nested-license-isc/LICENSE",
    "content": "Copyright (c) ...\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-nested-license-isc/index.js",
    "content": "// Avoid to be inlined completely: https://github.com/rolldown/rolldown/issues/8100\nconsole.log()\n\nexport default 'ok'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/dep-nested-license-isc/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-nested-license-isc\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"license\": \"ISC\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/index.html",
    "content": "<script type=\"module\">\n  import dep1 from '@vitejs/test-dep-licence-cc0'\n  import dep2 from '@vitejs/test-dep-license-mit'\n  console.log(dep1, dep2)\n</script>\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/license/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-license\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@vitejs/test-dep-license-mit\": \"file:./dep-license-mit\",\n    \"@vitejs/test-dep-licence-cc0\": \"file:./dep-licence-cc0\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/decorator-metadata/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/empty/tsconfig.json",
    "content": "{}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/jsx-complex-options/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/jsx-preserve/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"jsx\": \"preserve\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/jsx-react-jsx/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"jsxFactory\": \"g\",\n    \"jsxFragmentFactory\": \"foo\",\n    \"jsxImportSource\": \"baz\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/target-es2021/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2021\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/target-es2022/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2022\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/target-esnext/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/use-define-false/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"useDefineForClassFields\": false\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/oxc-tsconfigs/use-define-true/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"useDefineForClassFields\": true\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/worker-url/entry.js",
    "content": "import workerUrl from './worker?worker&url'\nconsole.log(workerUrl)\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/fixtures/worker-url/worker.js",
    "content": "/* global self */\nconst msg = 'hello from worker'\nself.postMessage(msg)\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/hooks.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, onTestFinished, test } from 'vitest'\nimport { build } from '../../build'\nimport type { Plugin } from '../../plugin'\nimport { resolveConfig } from '../../config'\nimport { createServer } from '../../server'\nimport { preview } from '../../preview'\nimport { promiseWithResolvers } from '../../../shared/utils'\n\nconst resolveConfigWithPlugin = (\n  plugin: Plugin,\n  command: 'serve' | 'build' = 'serve',\n) => {\n  return resolveConfig(\n    { configFile: false, plugins: [plugin], logLevel: 'error' },\n    command,\n  )\n}\n\nconst ENTRY_ID = 'entry.js'\nconst RESOLVED_ENTRY_ID = `\\0${ENTRY_ID}`\nconst resolveEntryPlugin: Plugin = {\n  name: 'resolve-entry.js',\n  resolveId(id) {\n    if (id === ENTRY_ID) {\n      return RESOLVED_ENTRY_ID\n    }\n  },\n  load(id) {\n    if (id === RESOLVED_ENTRY_ID) {\n      return 'export default {}'\n    }\n  },\n}\n\nconst createServerWithPlugin = async (plugin: Plugin) => {\n  const server = await createServer({\n    configFile: false,\n    root: import.meta.dirname,\n    plugins: [plugin, resolveEntryPlugin],\n    logLevel: 'error',\n    server: {\n      middlewareMode: true,\n      ws: false,\n    },\n  })\n  onTestFinished(() => server.close())\n  return server\n}\n\nconst createPreviewServerWithPlugin = async (plugin: Plugin) => {\n  const server = await preview({\n    configFile: false,\n    root: import.meta.dirname,\n    plugins: [\n      {\n        name: 'mock-preview',\n        configurePreviewServer({ httpServer }) {\n          // NOTE: make httpServer.listen no-op to avoid starting a server\n          httpServer.listen = () => {\n            const lastListener = httpServer.listeners('listening').at(-1)!\n            lastListener.call(httpServer)\n            return httpServer as any\n          }\n        },\n      },\n      plugin,\n    ],\n    logLevel: 'error',\n  })\n  onTestFinished(() => server.close())\n  return server\n}\n\nconst buildWithPlugin = async (plugin: Plugin) => {\n  await build({\n    root: path.resolve(import.meta.dirname, '../packages/build-project'),\n    logLevel: 'error',\n    build: {\n      write: false,\n    },\n    plugins: [plugin, resolveEntryPlugin],\n  })\n}\n\ndescribe('supports plugin context', () => {\n  test('config hook', async () => {\n    expect.assertions(4)\n\n    await resolveConfigWithPlugin({\n      name: 'test',\n      config() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        // @ts-expect-error watchMode should not exist in types\n        expect(this.meta.watchMode).toBeUndefined()\n      },\n    })\n  })\n\n  test('configEnvironment hook', async () => {\n    expect.assertions(4)\n\n    await resolveConfigWithPlugin({\n      name: 'test',\n      configEnvironment(name) {\n        if (name !== 'client') return\n\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        // @ts-expect-error watchMode should not exist in types\n        expect(this.meta.watchMode).toBeUndefined()\n      },\n    })\n  })\n\n  test('configResolved hook', async () => {\n    expect.assertions(4)\n\n    await resolveConfigWithPlugin({\n      name: 'test',\n      configResolved() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(true)\n      },\n    })\n  })\n\n  test('configureServer hook', async () => {\n    expect.assertions(4)\n\n    await createServerWithPlugin({\n      name: 'test',\n      configureServer() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(true)\n      },\n    })\n  })\n\n  test('configurePreviewServer hook', async () => {\n    expect.assertions(4)\n\n    await createPreviewServerWithPlugin({\n      name: 'test',\n      configurePreviewServer() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(false)\n      },\n    })\n  })\n\n  test('transformIndexHtml hook in dev', async () => {\n    expect.assertions(4)\n\n    const server = await createServerWithPlugin({\n      name: 'test',\n      transformIndexHtml() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(true)\n      },\n    })\n    await server.transformIndexHtml('/index.html', '<html></html>')\n  })\n\n  test('transformIndexHtml hook in build', async () => {\n    expect.assertions(4)\n\n    await buildWithPlugin({\n      name: 'test',\n      transformIndexHtml() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(false)\n      },\n    })\n  })\n\n  test('handleHotUpdate hook', async () => {\n    expect.assertions(4)\n\n    const { promise, resolve } = promiseWithResolvers<void>()\n    const server = await createServerWithPlugin({\n      name: 'test',\n      handleHotUpdate() {\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(true)\n        resolve()\n      },\n    })\n    server.watcher.emit(\n      'change',\n      path.resolve(import.meta.dirname, 'index.html'),\n    )\n\n    await promise\n  })\n\n  test('hotUpdate hook', async () => {\n    expect.assertions(4)\n\n    const { promise, resolve } = promiseWithResolvers<void>()\n    const server = await createServerWithPlugin({\n      name: 'test',\n      hotUpdate() {\n        if (this.environment.name !== 'client') return\n\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n          environment: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(true)\n        resolve()\n      },\n    })\n    server.watcher.emit(\n      'change',\n      path.resolve(import.meta.dirname, 'index.html'),\n    )\n\n    await promise\n  })\n\n  test('transform hook in dev', async () => {\n    expect.assertions(4)\n\n    const server = await createServerWithPlugin({\n      name: 'test',\n      transform(_code, id) {\n        if (id !== RESOLVED_ENTRY_ID) return\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(true)\n      },\n    })\n    await server.transformRequest(ENTRY_ID)\n    await server.close()\n  })\n\n  test('transform hook in build', async () => {\n    expect.assertions(4)\n\n    await buildWithPlugin({\n      name: 'test',\n      transform(_code, id) {\n        if (id !== RESOLVED_ENTRY_ID) return\n        expect(this).toMatchObject({\n          debug: expect.any(Function),\n          info: expect.any(Function),\n          warn: expect.any(Function),\n          error: expect.any(Function),\n          meta: expect.any(Object),\n        })\n        expect(this.meta.rollupVersion).toBeTypeOf('string')\n        expect(this.meta.viteVersion).toBeTypeOf('string')\n        expect(this.meta.watchMode).toBe(false)\n      },\n    })\n  })\n\n  test('this.fs is supported in dev', async () => {\n    expect.hasAssertions()\n\n    const server = await createServerWithPlugin({\n      name: 'test',\n      resolveId(id) {\n        if (id !== ENTRY_ID) return\n        expect(this.fs.readFile).toBeTypeOf('function')\n      },\n    })\n    await server.transformRequest(ENTRY_ID)\n    await server.close()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/import.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { transformCjsImport } from '../../plugins/importAnalysis'\n\ndescribe('runTransform', () => {\n  const config: any = {\n    command: 'serve',\n    logger: {\n      warn: vi.fn(),\n    },\n  }\n\n  function runTransformCjsImport(importExp: string, isNodeMode: boolean) {\n    const result = transformCjsImport(\n      importExp,\n      './node_modules/.vite/deps/react.js',\n      'react',\n      0,\n      'modA',\n      isNodeMode,\n      config,\n    )\n    if (result !== undefined) {\n      expect(result.split('\\n').length, 'result line count').toBe(\n        importExp.split('\\n').length,\n      )\n    }\n    return result?.replaceAll(';', ';\\n')\n  }\n\n  beforeEach(() => {\n    config.logger.warn.mockClear()\n  })\n\n  test('import specifier', () => {\n    expect(\n      runTransformCjsImport(\n        'import { useState, Component, \"👋\" as fake } from \"react\"',\n        false,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const useState = __vite__cjsImport0_react[\"useState\"];\n       const Component = __vite__cjsImport0_react[\"Component\"];\n       const fake = __vite__cjsImport0_react[\"👋\"]\"\n    `)\n    expect(\n      runTransformCjsImport(\n        'import { useState, Component, \"👋\" as fake } from \"react\"',\n        true,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const useState = __vite__cjsImport0_react[\"useState\"];\n       const Component = __vite__cjsImport0_react[\"Component\"];\n       const fake = __vite__cjsImport0_react[\"👋\"]\"\n    `)\n  })\n\n  test('import default specifier', () => {\n    expect(runTransformCjsImport('import React from \"react\"', false))\n      .toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const React = !__vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react : __vite__cjsImport0_react.default\"\n    `)\n    expect(runTransformCjsImport('import React from \"react\"', true))\n      .toMatchInlineSnapshot(`\n        \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n         const React = __vite__cjsImport0_react\"\n      `)\n\n    expect(\n      runTransformCjsImport('import { default as React } from \"react\"', false),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const React = !__vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react : __vite__cjsImport0_react.default\"\n    `)\n  })\n\n  test('import all specifier', () => {\n    expect(runTransformCjsImport('import * as react from \"react\"', false))\n      .toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const react = ((m, n) => n || !m?.__esModule ? {\t...typeof m === \"object\" && !Array.isArray(m) || typeof m === \"function\" ? m : {},\tdefault: m} : m)(__vite__cjsImport0_react, 0)\"\n    `)\n    expect(runTransformCjsImport('import * as react from \"react\"', true))\n      .toMatchInlineSnapshot(`\n        \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n         const react = ((m, n) => n || !m?.__esModule ? {\t...typeof m === \"object\" && !Array.isArray(m) || typeof m === \"function\" ? m : {},\tdefault: m} : m)(__vite__cjsImport0_react, 1)\"\n      `)\n  })\n\n  test('export all specifier', () => {\n    expect(\n      runTransformCjsImport('export * from \"react\"', false),\n    ).toMatchInlineSnapshot(`undefined`)\n    expect(\n      runTransformCjsImport('export * from \"react\"', true),\n    ).toMatchInlineSnapshot(`undefined`)\n\n    expect(config.logger.warn).toBeCalledWith(\n      expect.stringContaining(`export * from \"react\"\\` in modA`),\n    )\n\n    expect(\n      runTransformCjsImport('export * as react from \"react\"', false),\n    ).toMatchInlineSnapshot(`undefined`)\n\n    expect(config.logger.warn).toBeCalledTimes(2)\n  })\n\n  test('export name specifier', () => {\n    expect(\n      runTransformCjsImport(\n        'export { useState, Component, \"👋\" } from \"react\"',\n        false,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const __vite__cjsExportI_useState = __vite__cjsImport0_react[\"useState\"];\n       const __vite__cjsExportI_Component = __vite__cjsImport0_react[\"Component\"];\n       const __vite__cjsExportL_1d0452e3 = __vite__cjsImport0_react[\"👋\"];\n       export { __vite__cjsExportI_useState as useState, __vite__cjsExportI_Component as Component, __vite__cjsExportL_1d0452e3 as \"👋\" }\"\n    `)\n    expect(\n      runTransformCjsImport(\n        'export { useState, Component, \"👋\" } from \"react\"',\n        true,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const __vite__cjsExportI_useState = __vite__cjsImport0_react[\"useState\"];\n       const __vite__cjsExportI_Component = __vite__cjsImport0_react[\"Component\"];\n       const __vite__cjsExportL_1d0452e3 = __vite__cjsImport0_react[\"👋\"];\n       export { __vite__cjsExportI_useState as useState, __vite__cjsExportI_Component as Component, __vite__cjsExportL_1d0452e3 as \"👋\" }\"\n    `)\n\n    expect(\n      runTransformCjsImport(\n        'export { useState as useStateAlias, Component as ComponentAlias, \"👋\" as \"👍\" } from \"react\"',\n        false,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const __vite__cjsExportI_useStateAlias = __vite__cjsImport0_react[\"useState\"];\n       const __vite__cjsExportI_ComponentAlias = __vite__cjsImport0_react[\"Component\"];\n       const __vite__cjsExportL_5d57d39e = __vite__cjsImport0_react[\"👋\"];\n       export { __vite__cjsExportI_useStateAlias as useStateAlias, __vite__cjsExportI_ComponentAlias as ComponentAlias, __vite__cjsExportL_5d57d39e as \"👍\" }\"\n    `)\n  })\n\n  test('export default specifier', () => {\n    expect(runTransformCjsImport('export { default } from \"react\"', false))\n      .toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const __vite__cjsExportDefault_0 = !__vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react : __vite__cjsImport0_react.default;\n       export default __vite__cjsExportDefault_0\"\n    `)\n    expect(runTransformCjsImport('export { default } from \"react\"', true))\n      .toMatchInlineSnapshot(`\n        \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n         const __vite__cjsExportDefault_0 = __vite__cjsImport0_react;\n         export default __vite__cjsExportDefault_0\"\n      `)\n\n    expect(\n      runTransformCjsImport('export { default as React} from \"react\"', false),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const __vite__cjsExportI_React = !__vite__cjsImport0_react.__esModule ? __vite__cjsImport0_react : __vite__cjsImport0_react.default;\n       export { __vite__cjsExportI_React as React }\"\n    `)\n\n    expect(\n      runTransformCjsImport(\n        'export { Component as default } from \"react\"',\n        false,\n      ),\n    ).toMatchInlineSnapshot(`\n      \"import __vite__cjsImport0_react from \"./node_modules/.vite/deps/react.js\";\n       const __vite__cjsExportDefault_0 = __vite__cjsImport0_react[\"Component\"];\n       export default __vite__cjsExportDefault_0\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/__snapshots__/fixture.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`fixture > transform 1`] = `\n\"import * as __vite_glob_3_0 from \"./modules/a.ts\";import * as __vite_glob_3_1 from \"./modules/b.ts\";import * as __vite_glob_3_2 from \"./modules/index.ts\";import * as __vite_glob_5_0 from \"./modules/a.ts\";import * as __vite_glob_5_1 from \"./modules/b.ts\";import * as __vite_glob_5_2 from \"./modules/index.ts\";import { name as __vite_glob_9_0 } from \"./modules/a.ts\";import { name as __vite_glob_9_1 } from \"./modules/b.ts\";import { name as __vite_glob_9_2 } from \"./modules/index.ts\";import { name as __vite_glob_11_0 } from \"./modules/a.ts\";import { name as __vite_glob_11_1 } from \"./modules/b.ts\";import { name as __vite_glob_11_2 } from \"./modules/index.ts\";import { default as __vite_glob_15_0 } from \"./modules/a.ts?raw\";import { default as __vite_glob_15_1 } from \"./modules/b.ts?raw\";import * as __vite_glob_28_0 from \"./.foo/test.ts\";import \"../../../../../../types/importMeta\";\nexport const basic = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\"),\"./modules/index.ts\": () => import(\"./modules/index.ts\")});\nexport const basicWithObjectKeys = Object.keys({\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0});\nexport const basicWithObjectValues = Object.values([() => import(\"./modules/a.ts\"),() => import(\"./modules/b.ts\"),() => import(\"./modules/index.ts\")]);\nexport const basicEager = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": __vite_glob_3_0,\"./modules/b.ts\": __vite_glob_3_1,\"./modules/index.ts\": __vite_glob_3_2\n\n});\nexport const basicEagerWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0\n\n}\n);\nexport const basicEagerWithObjectValues = Object.values(\n  [__vite_glob_5_0,__vite_glob_5_1,__vite_glob_5_2\n\n]\n);\nexport const ignore = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\")});\nexport const ignoreWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0}\n);\nexport const ignoreWithObjectValues = Object.values(\n  [() => import(\"./modules/a.ts\"),() => import(\"./modules/b.ts\")]\n);\nexport const namedEager = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": __vite_glob_9_0,\"./modules/b.ts\": __vite_glob_9_1,\"./modules/index.ts\": __vite_glob_9_2\n\n\n});\nexport const namedEagerWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0\n\n\n}\n);\nexport const namedEagerWithObjectValues = Object.values(\n  [__vite_glob_11_0,__vite_glob_11_1,__vite_glob_11_2\n\n\n]\n);\nexport const namedDefault = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\").then(m => m[\"default\"]),\"./modules/b.ts\": () => import(\"./modules/b.ts\").then(m => m[\"default\"]),\"./modules/index.ts\": () => import(\"./modules/index.ts\").then(m => m[\"default\"])\n\n});\nexport const namedDefaultWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0\n\n}\n);\nexport const namedDefaultWithObjectValues = Object.values(\n  [() => import(\"./modules/a.ts\").then(m => m[\"default\"]),() => import(\"./modules/b.ts\").then(m => m[\"default\"]),() => import(\"./modules/index.ts\").then(m => m[\"default\"])\n\n]\n);\nexport const eagerAs = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": __vite_glob_15_0,\"./modules/b.ts\": __vite_glob_15_1\n\n\n});\nexport const rawImportModule = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts?raw\"),\"./modules/b.ts\": () => import(\"./modules/b.ts?raw\")\n\n\n});\nexport const excludeSelf = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts\")\n\n\n\n\n\n});\nexport const excludeSelfRaw = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts?raw\")});\nexport const customQueryString = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts?custom\")});\nexport const customQueryObject = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts?foo=bar&raw=true\")\n\n\n\n\n});\nexport const parent = /* #__PURE__ */ Object.assign({\n\n\n});\nexport const rootMixedRelative = /* #__PURE__ */ Object.assign({\"/fixture-b/a.ts\": () => import(\"../fixture-b/a.ts?url\").then(m => m[\"default\"]),\"/fixture-b/b.ts\": () => import(\"../fixture-b/b.ts?url\").then(m => m[\"default\"]),\"/fixture-b/index.ts\": () => import(\"../fixture-b/index.ts?url\").then(m => m[\"default\"]),\"/fixture.spec.ts\": () => import(\"../fixture.spec.ts?url\").then(m => m[\"default\"]),\"/parse.spec.ts\": () => import(\"../parse.spec.ts?url\").then(m => m[\"default\"]),\"/utils.spec.ts\": () => import(\"../utils.spec.ts?url\").then(m => m[\"default\"])\n\n\n});\nexport const cleverCwd1 = /* #__PURE__ */ Object.assign({\"./node_modules/framework/pages/hello.page.js\": () => import(\"./node_modules/framework/pages/hello.page.js\")\n\n});\nexport const cleverCwd2 = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\"),\"../fixture-b/a.ts\": () => import(\"../fixture-b/a.ts\"),\"../fixture-b/b.ts\": () => import(\"../fixture-b/b.ts\")\n\n\n\n});\nexport const customBase = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\"),\"./modules/index.ts\": () => import(\"./modules/index.ts\"),\"./sibling.ts\": () => import(\"./sibling.ts\")});\nexport const customRootBase = /* #__PURE__ */ Object.assign({\"./a.ts\": () => import(\"/fixture-b/a.ts\"),\"./b.ts\": () => import(\"/fixture-b/b.ts\"),\"./index.ts\": () => import(\"/fixture-b/index.ts\")\n\n});\nexport const customBaseParent = /* #__PURE__ */ Object.assign({\"../fixture-b/a.ts\": () => import(\"/fixture-b/a.ts\"),\"../fixture-b/b.ts\": () => import(\"/fixture-b/b.ts\"),\"../fixture-b/index.ts\": () => import(\"/fixture-b/index.ts\")\n\n});\nexport const dotFolder = /* #__PURE__ */ Object.assign({\"./.foo/test.ts\": __vite_glob_28_0});\n\"\n`;\n\nexports[`fixture > transform with restoreQueryExtension 1`] = `\n\"import * as __vite_glob_3_0 from \"./modules/a.ts\";import * as __vite_glob_3_1 from \"./modules/b.ts\";import * as __vite_glob_3_2 from \"./modules/index.ts\";import * as __vite_glob_5_0 from \"./modules/a.ts\";import * as __vite_glob_5_1 from \"./modules/b.ts\";import * as __vite_glob_5_2 from \"./modules/index.ts\";import { name as __vite_glob_9_0 } from \"./modules/a.ts\";import { name as __vite_glob_9_1 } from \"./modules/b.ts\";import { name as __vite_glob_9_2 } from \"./modules/index.ts\";import { name as __vite_glob_11_0 } from \"./modules/a.ts\";import { name as __vite_glob_11_1 } from \"./modules/b.ts\";import { name as __vite_glob_11_2 } from \"./modules/index.ts\";import { default as __vite_glob_15_0 } from \"./modules/a.ts?raw\";import { default as __vite_glob_15_1 } from \"./modules/b.ts?raw\";import * as __vite_glob_28_0 from \"./.foo/test.ts\";import \"../../../../../../types/importMeta\";\nexport const basic = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\"),\"./modules/index.ts\": () => import(\"./modules/index.ts\")});\nexport const basicWithObjectKeys = Object.keys({\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0});\nexport const basicWithObjectValues = Object.values([() => import(\"./modules/a.ts\"),() => import(\"./modules/b.ts\"),() => import(\"./modules/index.ts\")]);\nexport const basicEager = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": __vite_glob_3_0,\"./modules/b.ts\": __vite_glob_3_1,\"./modules/index.ts\": __vite_glob_3_2\n\n});\nexport const basicEagerWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0\n\n}\n);\nexport const basicEagerWithObjectValues = Object.values(\n  [__vite_glob_5_0,__vite_glob_5_1,__vite_glob_5_2\n\n]\n);\nexport const ignore = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\")});\nexport const ignoreWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0}\n);\nexport const ignoreWithObjectValues = Object.values(\n  [() => import(\"./modules/a.ts\"),() => import(\"./modules/b.ts\")]\n);\nexport const namedEager = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": __vite_glob_9_0,\"./modules/b.ts\": __vite_glob_9_1,\"./modules/index.ts\": __vite_glob_9_2\n\n\n});\nexport const namedEagerWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0\n\n\n}\n);\nexport const namedEagerWithObjectValues = Object.values(\n  [__vite_glob_11_0,__vite_glob_11_1,__vite_glob_11_2\n\n\n]\n);\nexport const namedDefault = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\").then(m => m[\"default\"]),\"./modules/b.ts\": () => import(\"./modules/b.ts\").then(m => m[\"default\"]),\"./modules/index.ts\": () => import(\"./modules/index.ts\").then(m => m[\"default\"])\n\n});\nexport const namedDefaultWithObjectKeys = Object.keys(\n  {\"./modules/a.ts\": 0,\"./modules/b.ts\": 0,\"./modules/index.ts\": 0\n\n}\n);\nexport const namedDefaultWithObjectValues = Object.values(\n  [() => import(\"./modules/a.ts\").then(m => m[\"default\"]),() => import(\"./modules/b.ts\").then(m => m[\"default\"]),() => import(\"./modules/index.ts\").then(m => m[\"default\"])\n\n]\n);\nexport const eagerAs = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": __vite_glob_15_0,\"./modules/b.ts\": __vite_glob_15_1\n\n\n});\nexport const rawImportModule = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts?raw\"),\"./modules/b.ts\": () => import(\"./modules/b.ts?raw\")\n\n\n});\nexport const excludeSelf = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts\")\n\n\n\n\n\n});\nexport const excludeSelfRaw = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts?raw\")});\nexport const customQueryString = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts?custom&lang.ts\")});\nexport const customQueryObject = /* #__PURE__ */ Object.assign({\"./sibling.ts\": () => import(\"./sibling.ts?foo=bar&raw=true&lang.ts\")\n\n\n\n\n});\nexport const parent = /* #__PURE__ */ Object.assign({\n\n\n});\nexport const rootMixedRelative = /* #__PURE__ */ Object.assign({\"/fixture-b/a.ts\": () => import(\"../fixture-b/a.ts?url&lang.ts\").then(m => m[\"default\"]),\"/fixture-b/b.ts\": () => import(\"../fixture-b/b.ts?url&lang.ts\").then(m => m[\"default\"]),\"/fixture-b/index.ts\": () => import(\"../fixture-b/index.ts?url&lang.ts\").then(m => m[\"default\"]),\"/fixture.spec.ts\": () => import(\"../fixture.spec.ts?url&lang.ts\").then(m => m[\"default\"]),\"/parse.spec.ts\": () => import(\"../parse.spec.ts?url&lang.ts\").then(m => m[\"default\"]),\"/utils.spec.ts\": () => import(\"../utils.spec.ts?url&lang.ts\").then(m => m[\"default\"])\n\n\n});\nexport const cleverCwd1 = /* #__PURE__ */ Object.assign({\"./node_modules/framework/pages/hello.page.js\": () => import(\"./node_modules/framework/pages/hello.page.js\")\n\n});\nexport const cleverCwd2 = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\"),\"../fixture-b/a.ts\": () => import(\"../fixture-b/a.ts\"),\"../fixture-b/b.ts\": () => import(\"../fixture-b/b.ts\")\n\n\n\n});\nexport const customBase = /* #__PURE__ */ Object.assign({\"./modules/a.ts\": () => import(\"./modules/a.ts\"),\"./modules/b.ts\": () => import(\"./modules/b.ts\"),\"./modules/index.ts\": () => import(\"./modules/index.ts\"),\"./sibling.ts\": () => import(\"./sibling.ts\")});\nexport const customRootBase = /* #__PURE__ */ Object.assign({\"./a.ts\": () => import(\"/fixture-b/a.ts\"),\"./b.ts\": () => import(\"/fixture-b/b.ts\"),\"./index.ts\": () => import(\"/fixture-b/index.ts\")\n\n});\nexport const customBaseParent = /* #__PURE__ */ Object.assign({\"../fixture-b/a.ts\": () => import(\"/fixture-b/a.ts\"),\"../fixture-b/b.ts\": () => import(\"/fixture-b/b.ts\"),\"../fixture-b/index.ts\": () => import(\"/fixture-b/index.ts\")\n\n});\nexport const dotFolder = /* #__PURE__ */ Object.assign({\"./.foo/test.ts\": __vite_glob_28_0});\n\"\n`;\n\nexports[`fixture > virtual modules 1`] = `\n\"/* #__PURE__ */ Object.assign({\"/modules/a.ts\": () => import(\"/modules/a.ts\"),\"/modules/b.ts\": () => import(\"/modules/b.ts\"),\"/modules/index.ts\": () => import(\"/modules/index.ts\")})\n/* #__PURE__ */ Object.assign({\"/../fixture-b/a.ts\": () => import(\"/../fixture-b/a.ts\"),\"/../fixture-b/b.ts\": () => import(\"/../fixture-b/b.ts\"),\"/../fixture-b/index.ts\": () => import(\"/../fixture-b/index.ts\")})\n/* #__PURE__ */ Object.assign({\"./a.ts\": () => import(\"/modules/a.ts\"),\"./b.ts\": () => import(\"/modules/b.ts\"),\"./index.ts\": () => import(\"/modules/index.ts\")})\"\n`;\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/.foo/test.ts",
    "content": "export const msg = 'dot-folder-test'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/.gitignore",
    "content": "!/node_modules/\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/index.ts",
    "content": "// NOTE: `#types/importMeta` does not work as `src/node/__tests__/package.json` shadows the root\n// `package.json` and does not declare the subpath import.\nimport '../../../../../../types/importMeta'\n\nexport interface ModuleType {\n  name: string\n}\n\nexport const basic = import.meta.glob<ModuleType>('./modules/*.ts')\n// prettier-ignore\nexport const basicWithObjectKeys = Object.keys(import.meta.glob<ModuleType>('./modules/*.ts'))\n// prettier-ignore\nexport const basicWithObjectValues = Object.values(import.meta.glob<ModuleType>('./modules/*.ts'))\n\nexport const basicEager = import.meta.glob<ModuleType>('./modules/*.ts', {\n  eager: true,\n})\nexport const basicEagerWithObjectKeys = Object.keys(\n  import.meta.glob<ModuleType>('./modules/*.ts', {\n    eager: true,\n  }),\n)\nexport const basicEagerWithObjectValues = Object.values(\n  import.meta.glob<ModuleType>('./modules/*.ts', {\n    eager: true,\n  }),\n)\n\nexport const ignore = import.meta.glob(['./modules/*.ts', '!**/index.ts'])\nexport const ignoreWithObjectKeys = Object.keys(\n  import.meta.glob(['./modules/*.ts', '!**/index.ts']),\n)\nexport const ignoreWithObjectValues = Object.values(\n  import.meta.glob(['./modules/*.ts', '!**/index.ts']),\n)\n\nexport const namedEager = import.meta.glob<string>('./modules/*.ts', {\n  eager: true,\n  import: 'name',\n})\nexport const namedEagerWithObjectKeys = Object.keys(\n  import.meta.glob<string>('./modules/*.ts', {\n    eager: true,\n    import: 'name',\n  }),\n)\nexport const namedEagerWithObjectValues = Object.values(\n  import.meta.glob<string>('./modules/*.ts', {\n    eager: true,\n    import: 'name',\n  }),\n)\n\nexport const namedDefault = import.meta.glob<string>('./modules/*.ts', {\n  import: 'default',\n})\nexport const namedDefaultWithObjectKeys = Object.keys(\n  import.meta.glob<string>('./modules/*.ts', {\n    import: 'default',\n  }),\n)\nexport const namedDefaultWithObjectValues = Object.values(\n  import.meta.glob<string>('./modules/*.ts', {\n    import: 'default',\n  }),\n)\n\nexport const eagerAs = import.meta.glob<ModuleType>(\n  ['./modules/*.ts', '!**/index.ts'],\n  { eager: true, query: '?raw', import: 'default' },\n)\n\nexport const rawImportModule = import.meta.glob(\n  ['./modules/*.ts', '!**/index.ts'],\n  { query: '?raw', import: '*' },\n)\n\nexport const excludeSelf = import.meta.glob(\n  './*.ts',\n  // for test: annotation contain \")\"\n  /*\n   * for test: annotation contain \")\"\n   * */\n)\nexport const excludeSelfRaw = import.meta.glob('./*.ts', { query: '?raw' })\n\nexport const customQueryString = import.meta.glob('./*.ts', { query: 'custom' })\n\nexport const customQueryObject = import.meta.glob('./*.ts', {\n  query: {\n    foo: 'bar',\n    raw: true,\n  },\n})\n\nexport const parent = import.meta.glob('../../playground/src/*.ts', {\n  query: '?url',\n  import: 'default',\n})\n\nexport const rootMixedRelative = import.meta.glob(\n  ['/*.ts', '../fixture-b/*.ts'],\n  { query: '?url', import: 'default' },\n)\n\nexport const cleverCwd1 = import.meta.glob(\n  './node_modules/framework/**/*.page.js',\n)\n\nexport const cleverCwd2 = import.meta.glob([\n  './modules/*.ts',\n  '../fixture-b/*.ts',\n  '!**/index.ts',\n])\n\nexport const customBase = import.meta.glob('./**/*.ts', { base: './' })\n\nexport const customRootBase = import.meta.glob('./**/*.ts', {\n  base: '/fixture-b',\n})\n\nexport const customBaseParent = import.meta.glob('/fixture-b/**/*.ts', {\n  base: '/fixture-a',\n})\n\nexport const dotFolder = import.meta.glob('./.foo/*.ts', { eager: true })\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/modules/a.ts",
    "content": "export const name = 'a'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/modules/b.ts",
    "content": "export const name = 'b'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/modules/index.ts",
    "content": "export { name as a } from './a'\nexport { name as b } from './b'\n\nexport const name = 'index'\n\nexport default 'indexDefault'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-a/sibling.ts",
    "content": "export const name = 'I am your sibling!'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-b/a.ts",
    "content": "export const name = 'a'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-b/b.ts",
    "content": "export const name = 'b'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture-b/index.ts",
    "content": "export { name as a } from './a'\nexport { name as b } from './b'\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/fixture.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { promises as fs } from 'node:fs'\nimport { describe, expect, it } from 'vitest'\nimport { transformGlobImport } from '../../../plugins/importMetaGlob'\nimport { transformWithEsbuild } from '../../../plugins/esbuild'\n\ndescribe('fixture', async () => {\n  const resolveId = (id: string) => id\n  const root = import.meta.dirname\n\n  it('transform', async () => {\n    const id = resolve(import.meta.dirname, './fixture-a/index.ts')\n    const code = (\n      await transformWithEsbuild(await fs.readFile(id, 'utf-8'), id)\n    ).code\n\n    expect(\n      (await transformGlobImport(code, id, root, resolveId))?.s.toString(),\n    ).toMatchSnapshot()\n  })\n\n  it('preserve line count', async () => {\n    const getTransformedLineCount = async (code: string) =>\n      (await transformGlobImport(code, 'virtual:module', root, resolveId))?.s\n        .toString()\n        .split('\\n').length\n\n    expect(await getTransformedLineCount(\"import.meta.glob('./*.js')\")).toBe(1)\n    expect(\n      await getTransformedLineCount(\n        `\n          import.meta.glob(\n            './*.js'\n          )\n        `.trim(),\n      ),\n    ).toBe(3)\n  })\n\n  it('virtual modules', async () => {\n    const root = resolve(import.meta.dirname, './fixture-a')\n    const code = [\n      \"import.meta.glob('/modules/*.ts')\",\n      \"import.meta.glob(['/../fixture-b/*.ts'])\",\n      \"import.meta.glob(['./*.ts'], { base: '/modules' })\",\n    ].join('\\n')\n    expect(\n      (\n        await transformGlobImport(code, 'virtual:module', root, resolveId)\n      )?.s.toString(),\n    ).toMatchSnapshot()\n\n    try {\n      await transformGlobImport(\n        \"import.meta.glob('./modules/*.ts')\",\n        'virtual:module',\n        root,\n        resolveId,\n      )\n      expect('no error').toBe('should throw an error')\n    } catch (err) {\n      expect(err).toMatchInlineSnapshot(\n        \"[Error: In virtual modules, all globs must start with '/']\",\n      )\n    }\n  })\n\n  it('transform with restoreQueryExtension', async () => {\n    const id = resolve(import.meta.dirname, './fixture-a/index.ts')\n    const code = (\n      await transformWithEsbuild(await fs.readFile(id, 'utf-8'), id)\n    ).code\n\n    expect(\n      (\n        await transformGlobImport(code, id, root, resolveId, true)\n      )?.s.toString(),\n    ).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/parse.spec.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { parseImportGlob } from '../../../plugins/importMetaGlob'\n\nasync function run(input: string) {\n  const items = await parseImportGlob(\n    input,\n    process.cwd(),\n    process.cwd(),\n    (id) => id,\n  )\n  return items.map((i) => ({\n    globs: i.globs,\n    options: i.options,\n    start: i.start,\n  }))\n}\n\nasync function runError(input: string) {\n  try {\n    await run(input)\n  } catch (e) {\n    return e\n  }\n}\n\ndescribe('parse positives', async () => {\n  it('basic', async () => {\n    expect(\n      await run(`\n    import.meta.glob('./modules/*.ts')\n    `),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"./modules/*.ts\",\n          ],\n          \"options\": {},\n          \"start\": 5,\n        },\n      ]\n    `)\n  })\n\n  it('array', async () => {\n    expect(\n      await run(`\n    import.meta.glob(['./modules/*.ts', './dir/*.{js,ts}'])\n    `),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"./modules/*.ts\",\n            \"./dir/*.{js,ts}\",\n          ],\n          \"options\": {},\n          \"start\": 5,\n        },\n      ]\n    `)\n  })\n\n  it('options with multilines', async () => {\n    expect(\n      await run(`\n    import.meta.glob([\n      './modules/*.ts',\n      \"!./dir/*.{js,ts}\"\n    ], {\n      eager: true,\n      import: 'named'\n    })\n    `),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"./modules/*.ts\",\n            \"!./dir/*.{js,ts}\",\n          ],\n          \"options\": {\n            \"eager\": true,\n            \"import\": \"named\",\n          },\n          \"start\": 5,\n        },\n      ]\n    `)\n  })\n\n  it('options with multilines', async () => {\n    expect(\n      await run(`\n    const modules = import.meta.glob(\n      '/dir/**'\n      // for test: annotation contain \")\"\n      /*\n       * for test: annotation contain \")\"\n       * */\n    )\n    `),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"/dir/**\",\n          ],\n          \"options\": {},\n          \"start\": 21,\n        },\n      ]\n    `)\n  })\n\n  it('options query', async () => {\n    expect(\n      await run(`\n    const modules = import.meta.glob(\n      '/dir/**',\n      {\n        query: {\n          foo: 'bar',\n          raw: true,\n        }\n      }\n    )\n    `),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"/dir/**\",\n          ],\n          \"options\": {\n            \"query\": \"?foo=bar&raw=true\",\n          },\n          \"start\": 21,\n        },\n      ]\n    `)\n  })\n\n  it('options with base', async () => {\n    expect(\n      await run(`\n    import.meta.glob('./**/dir/*.md', {\n      base: './path/to/base'\n    })\n    `),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"./**/dir/*.md\",\n          ],\n          \"options\": {\n            \"base\": \"./path/to/base\",\n          },\n          \"start\": 5,\n        },\n      ]\n    `)\n  })\n\n  it('object properties - 1', async () => {\n    expect(\n      await run(`\n    export const pageFiles = {\n      '.page': import.meta.glob('/**/*.page.*([a-zA-Z0-9])')\n};`),\n    ).toMatchInlineSnapshot(`\n  [\n    {\n      \"globs\": [\n        \"/**/*.page.*([a-zA-Z0-9])\",\n      ],\n      \"options\": {},\n      \"start\": 47,\n    },\n  ]\n`)\n  })\n\n  it('object properties - 2', async () => {\n    expect(\n      await run(`\n    export const pageFiles = {\n      '.page': import.meta.glob('/**/*.page.*([a-zA-Z0-9])'),\n};`),\n    ).toMatchInlineSnapshot(`\n  [\n    {\n      \"globs\": [\n        \"/**/*.page.*([a-zA-Z0-9])\",\n      ],\n      \"options\": {},\n      \"start\": 47,\n    },\n  ]\n`)\n  })\n\n  it('object properties - 3', async () => {\n    expect(\n      await run(`\n    export const pageFiles = {\n      '.page.client': import.meta.glob('/**/*.page.client.*([a-zA-Z0-9])'),\n      '.page.server': import.meta.glob('/**/*.page.server.*([a-zA-Z0-9])'),\n};`),\n    ).toMatchInlineSnapshot(`\n  [\n    {\n      \"globs\": [\n        \"/**/*.page.client.*([a-zA-Z0-9])\",\n      ],\n      \"options\": {},\n      \"start\": 54,\n    },\n    {\n      \"globs\": [\n        \"/**/*.page.server.*([a-zA-Z0-9])\",\n      ],\n      \"options\": {},\n      \"start\": 130,\n    },\n  ]\n`)\n  })\n\n  it('array item', async () => {\n    expect(\n      await run(`\n    export const pageFiles = [\n      import.meta.glob('/**/*.page.client.*([a-zA-Z0-9])'),\n      import.meta.glob('/**/*.page.server.*([a-zA-Z0-9])'),\n    ]`),\n    ).toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"/**/*.page.client.*([a-zA-Z0-9])\",\n          ],\n          \"options\": {},\n          \"start\": 38,\n        },\n        {\n          \"globs\": [\n            \"/**/*.page.server.*([a-zA-Z0-9])\",\n          ],\n          \"options\": {},\n          \"start\": 98,\n        },\n      ]\n    `)\n  })\n})\n\ndescribe('parse negatives', async () => {\n  it('syntax error', async () => {\n    expect(await runError('import.meta.glob(')).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Close parenthesis not found]',\n    )\n  })\n\n  it('empty', async () => {\n    expect(await runError('import.meta.glob()')).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Expected 1-2 arguments, but got 0]',\n    )\n  })\n\n  it('3 args', async () => {\n    expect(\n      await runError('import.meta.glob(\"\", {}, {})'),\n    ).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Expected 1-2 arguments, but got 3]',\n    )\n  })\n\n  it('in string', async () => {\n    expect(await runError('\"import.meta.glob()\"')).toBeUndefined()\n  })\n\n  it('variable', async () => {\n    expect(await runError('import.meta.glob(hey)')).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Could only use literals]',\n    )\n  })\n\n  it('template', async () => {\n    expect(\n      await runError('import.meta.glob(`hi ${hey}`)'),\n    ).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Expected glob to be a string, but got dynamic template literal]',\n    )\n  })\n\n  it('template with unicode', async () => {\n    expect(await run('import.meta.glob(`/\\u0068\\u0065\\u006c\\u006c\\u006f`)'))\n      .toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"/hello\",\n          ],\n          \"options\": {},\n          \"start\": 0,\n        },\n      ]\n    `)\n  })\n\n  it('template without expressions', async () => {\n    expect(await run('import.meta.glob(`/**/*.page.client.*([a-zA-Z0-9])`)'))\n      .toMatchInlineSnapshot(`\n      [\n        {\n          \"globs\": [\n            \"/**/*.page.client.*([a-zA-Z0-9])\",\n          ],\n          \"options\": {},\n          \"start\": 0,\n        },\n      ]\n    `)\n  })\n\n  it('be string', async () => {\n    expect(await runError('import.meta.glob(1)')).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Expected glob to be a string, but got \"number\"]',\n    )\n  })\n\n  it('be array variable', async () => {\n    expect(await runError('import.meta.glob([hey])')).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Could only use literals]',\n    )\n    expect(\n      await runError('import.meta.glob([\"1\", hey])'),\n    ).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Could only use literals]',\n    )\n  })\n\n  it('options', async () => {\n    expect(\n      await runError('import.meta.glob(\"hey\", hey)'),\n    ).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Expected the second argument to be an object literal, but got \"Identifier\"]',\n    )\n    expect(await runError('import.meta.glob(\"hey\", [])')).toMatchInlineSnapshot(\n      '[Error: Invalid glob import syntax: Expected the second argument to be an object literal, but got \"ArrayExpression\"]',\n    )\n  })\n\n  it('options props', async () => {\n    expect(\n      await runError('import.meta.glob(\"hey\", { hey: 1 })'),\n    ).toMatchInlineSnapshot('[Error: Unknown glob option \"hey\"]')\n    expect(\n      await runError('import.meta.glob(\"hey\", { import: hey })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Vite is unable to parse the glob options as the value is not static]',\n    )\n    expect(\n      await runError('import.meta.glob(\"hey\", { eager: 123 })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Expected glob option \"eager\" to be of type boolean, but got number]',\n    )\n  })\n\n  it('options query', async () => {\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { as: \"raw\", query: \"hi\" })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Options \"as\" and \"query\" cannot be used together]',\n    )\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { query: 123 })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Expected glob option \"query\" to be of type object or string, but got number]',\n    )\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { query: { foo: {} } })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Expected glob option \"query.foo\" to be of type string, number, or boolean, but got object]',\n    )\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { query: { foo: hey } })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Vite is unable to parse the glob options as the value is not static]',\n    )\n    expect(\n      await runError(\n        'import.meta.glob(\"./*.js\", { query: { foo: 123, ...a } })',\n      ),\n    ).toMatchInlineSnapshot(\n      '[Error: Vite is unable to parse the glob options as the value is not static]',\n    )\n  })\n\n  it('options base', async () => {\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { base: 1 })'),\n    ).toMatchInlineSnapshot(\n      '[Error: Expected glob option \"base\" to be of type string, but got number]',\n    )\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { base: \"foo\" })'),\n    ).toMatchInlineSnapshot(\n      \"[Error: Option \\\"base\\\" must start with '/', './' or '../', but got \\\"foo\\\"]\",\n    )\n    expect(\n      await runError('import.meta.glob(\"./*.js\", { base: \"!/foo\" })'),\n    ).toMatchInlineSnapshot('[Error: Option \"base\" cannot start with \"!\"]')\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/importGlob/utils.spec.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { getCommonBase } from '../../../plugins/importMetaGlob'\n\ndescribe('getCommonBase()', async () => {\n  it('basic', () => {\n    expect(getCommonBase(['/a/b/*.js', '/a/c/*.js'])).toBe('/a')\n  })\n  it('common base', () => {\n    expect(getCommonBase(['/a/b/**/*.vue', '/a/b/**/*.jsx'])).toBe('/a/b')\n  })\n  it('static file', () => {\n    expect(\n      getCommonBase(['/a/b/**/*.vue', '/a/b/**/*.jsx', '/a/b/foo.js']),\n    ).toBe('/a/b')\n    expect(getCommonBase(['/a/b/**/*.vue', '/a/b/**/*.jsx', '/a/foo.js'])).toBe(\n      '/a',\n    )\n  })\n  it('correct `scan()`', () => {\n    expect(getCommonBase(['/a/*.vue'])).toBe('/a')\n    expect(getCommonBase(['/a/some.vue'])).toBe('/a')\n    expect(getCommonBase(['/a/b/**/c/foo.vue', '/a/b/c/**/*.jsx'])).toBe('/a/b')\n  })\n  it('single', () => {\n    expect(getCommonBase(['/a/b/c/*.vue'])).toBe('/a/b/c')\n    expect(getCommonBase(['/a/b/c/foo.vue'])).toBe('/a/b/c')\n  })\n  it('no common base', () => {\n    expect(getCommonBase(['/a/b/*.js', '/c/a/b/*.js'])).toBe('/')\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/index.spec.ts",
    "content": "import { RUNTIME_MODULE_ID } from 'rolldown'\nimport { exactRegex } from 'rolldown/filter'\nimport { afterAll, describe, expect, test, vi } from 'vitest'\nimport { type InlineConfig, type Plugin, build, createServer } from '../..'\n\nconst getConfigWithPlugin = (\n  plugins: Plugin[],\n  input?: string[],\n): InlineConfig => {\n  return {\n    configFile: false,\n    server: { middlewareMode: true, ws: false },\n    optimizeDeps: { noDiscovery: true, include: [] },\n    build: { rollupOptions: { input }, write: false },\n    plugins,\n    logLevel: 'silent',\n  }\n}\n\ndescribe('hook filter with plugin container', async () => {\n  const resolveId = vi.fn()\n  const load = vi.fn()\n  const transformWithId = vi.fn()\n  const transformWithCode = vi.fn()\n  const any = expect.toSatisfy(() => true) // anything including undefined and null\n  const config = getConfigWithPlugin([\n    {\n      name: 'test',\n      resolveId: {\n        filter: { id: /\\.js$/ },\n        handler: resolveId,\n      },\n      load: {\n        filter: { id: '**/*.js' },\n        handler: load,\n      },\n      transform: {\n        filter: { id: '**/*.js' },\n        handler: transformWithId,\n      },\n    },\n    {\n      name: 'test2',\n      transform: {\n        filter: { code: 'import.meta' },\n        handler: transformWithCode,\n      },\n    },\n  ])\n  const server = await createServer(config)\n  afterAll(async () => {\n    await server.close()\n  })\n  const pluginContainer = server.environments.ssr.pluginContainer\n\n  test('resolveId', async () => {\n    await pluginContainer.resolveId('foo.js')\n    await pluginContainer.resolveId('foo.ts')\n    expect(resolveId).toHaveBeenCalledTimes(1)\n    expect(resolveId).toHaveBeenCalledWith('foo.js', any, any)\n  })\n\n  test('load', async () => {\n    await pluginContainer.load('foo.js')\n    await pluginContainer.load('foo.ts')\n    expect(load).toHaveBeenCalledTimes(1)\n    expect(load).toHaveBeenCalledWith('foo.js', any)\n  })\n\n  test('transform', async () => {\n    await server.environments.ssr.moduleGraph.ensureEntryFromUrl('foo.js')\n    await server.environments.ssr.moduleGraph.ensureEntryFromUrl('foo.ts')\n\n    await pluginContainer.transform('import_meta', 'foo.js')\n    await pluginContainer.transform('import.meta', 'foo.ts')\n    expect(transformWithId).toHaveBeenCalledTimes(1)\n    expect(transformWithId).toHaveBeenCalledWith(\n      expect.stringContaining('import_meta'),\n      'foo.js',\n      any,\n    )\n    expect(transformWithCode).toHaveBeenCalledTimes(1)\n    expect(transformWithCode).toHaveBeenCalledWith(\n      expect.stringContaining('import.meta'),\n      'foo.ts',\n      any,\n    )\n  })\n})\n\ndescribe('hook filter with build', async () => {\n  const resolveId = vi.fn()\n  const load = vi.fn()\n  const transformWithId = vi.fn()\n  const transformWithCode = vi.fn()\n  const any = expect.anything()\n  const config = getConfigWithPlugin(\n    [\n      {\n        name: 'test',\n        resolveId: {\n          filter: { id: /\\.js$/ },\n          handler: resolveId,\n        },\n        load: {\n          filter: { id: '**/*.js' },\n          handler: load,\n        },\n        transform: {\n          filter: {\n            id: {\n              include: '**/*.js',\n              exclude: exactRegex(RUNTIME_MODULE_ID),\n            },\n          },\n          handler: transformWithId,\n        },\n      },\n      {\n        name: 'test2',\n        transform: {\n          filter: { code: 'import.meta' },\n          handler: transformWithCode,\n        },\n      },\n      {\n        name: 'resolver',\n        resolveId(id) {\n          return id\n        },\n        load(id) {\n          if (id === 'foo.js') {\n            return 'import \"foo.ts\"\\n' + 'import_meta'\n          }\n          if (id === 'foo.ts') {\n            return 'import.meta'\n          }\n        },\n      },\n    ],\n    ['foo.js', 'foo.ts'],\n  )\n  await build(config)\n\n  test('resolveId', async () => {\n    expect(resolveId).toHaveBeenCalledTimes(1)\n    expect(resolveId).toHaveBeenCalledWith('foo.js', undefined, any)\n  })\n\n  test('load', async () => {\n    expect(load).toHaveBeenCalledTimes(1)\n    expect(load).toHaveBeenCalledWith('foo.js', any)\n  })\n\n  test('transform', async () => {\n    expect(transformWithId).toHaveBeenCalledTimes(1)\n    expect(transformWithId).toHaveBeenCalledWith(\n      expect.stringContaining('import_meta'),\n      'foo.js',\n      any,\n    )\n    expect(transformWithCode).toHaveBeenCalledTimes(1)\n    expect(transformWithCode).toHaveBeenCalledWith(\n      expect.stringContaining('import.meta'),\n      'foo.ts',\n      any,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/license.spec.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport type { OutputAsset, RollupOutput } from 'rollup'\nimport { expect, test } from 'vitest'\nimport { build } from '../../build'\n\ntest('markdown', async () => {\n  const result = (await build({\n    root: fileURLToPath(new URL('./fixtures/license', import.meta.url)),\n    logLevel: 'silent',\n    build: {\n      write: false,\n      license: true,\n    },\n  })) as RollupOutput\n  const licenseAsset = result.output.find(\n    (asset) => asset.fileName === '.vite/license.md',\n  ) as OutputAsset | undefined\n  expect(licenseAsset).toBeDefined()\n  expect(licenseAsset?.source).toMatchSnapshot()\n})\n\ntest('json', async () => {\n  const result = (await build({\n    root: fileURLToPath(new URL('./fixtures/license', import.meta.url)),\n    logLevel: 'silent',\n    build: {\n      write: false,\n      license: {\n        fileName: '.vite/license.json',\n      },\n    },\n  })) as RollupOutput\n  const licenseAsset = result.output.find(\n    (asset) => asset.fileName === '.vite/license.json',\n  ) as OutputAsset | undefined\n  expect(licenseAsset).toBeDefined()\n  expect(licenseAsset?.source).toMatchSnapshot()\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/modulePreloadPolyfill/__snapshots__/modulePreloadPolyfill.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`load > doesn't load modulepreload polyfill when format is cjs 1`] = `\"\"`;\n\nexports[`load > loads modulepreload polyfill 1`] = `\n\"//#region \\\\0vite/modulepreload-polyfill.js\n(function polyfill() {\n\tconst relList = document.createElement(\"link\").relList;\n\tif (relList && relList.supports && relList.supports(\"modulepreload\")) return;\n\tfor (const link of document.querySelectorAll(\"link[rel=\\\\\"modulepreload\\\\\"]\")) processPreload(link);\n\tnew MutationObserver((mutations) => {\n\t\tfor (const mutation of mutations) {\n\t\t\tif (mutation.type !== \"childList\") continue;\n\t\t\tfor (const node of mutation.addedNodes) if (node.tagName === \"LINK\" && node.rel === \"modulepreload\") processPreload(node);\n\t\t}\n\t}).observe(document, {\n\t\tchildList: true,\n\t\tsubtree: true\n\t});\n\tfunction getFetchOpts(link) {\n\t\tconst fetchOpts = {};\n\t\tif (link.integrity) fetchOpts.integrity = link.integrity;\n\t\tif (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;\n\t\tif (link.crossOrigin === \"use-credentials\") fetchOpts.credentials = \"include\";\n\t\telse if (link.crossOrigin === \"anonymous\") fetchOpts.credentials = \"omit\";\n\t\telse fetchOpts.credentials = \"same-origin\";\n\t\treturn fetchOpts;\n\t}\n\tfunction processPreload(link) {\n\t\tif (link.ep) return;\n\t\tlink.ep = true;\n\t\tconst fetchOpts = getFetchOpts(link);\n\t\tfetch(link.href, fetchOpts);\n\t}\n})();\n//#endregion\n\"\n`;\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/modulePreloadPolyfill/modulePreloadPolyfill.spec.ts",
    "content": "import { describe, it } from 'vitest'\nimport type { ModuleFormat, RolldownOutput } from 'rolldown'\nimport { build } from '../../../build'\nimport { modulePreloadPolyfillId } from '../../../plugins/modulePreloadPolyfill'\n\nconst buildProject = ({ format = 'es' as ModuleFormat } = {}) =>\n  build({\n    logLevel: 'silent',\n    build: {\n      write: false,\n      rollupOptions: {\n        input: 'main.js',\n        output: {\n          format,\n        },\n        treeshake: {\n          moduleSideEffects: false,\n        },\n      },\n      minify: false,\n    },\n    plugins: [\n      {\n        name: 'test',\n        resolveId(id) {\n          if (id === 'main.js') {\n            return `\\0${id}`\n          }\n        },\n        load(id) {\n          if (id === '\\0main.js') {\n            return `import '${modulePreloadPolyfillId}'`\n          }\n        },\n      },\n    ],\n  }) as Promise<RolldownOutput>\n\ndescribe('load', () => {\n  it('loads modulepreload polyfill', async ({ expect }) => {\n    const { output } = await buildProject()\n    expect(output).toHaveLength(1)\n    expect(output[0].code).toMatchSnapshot()\n  })\n\n  it(\"doesn't load modulepreload polyfill when format is cjs\", async ({\n    expect,\n  }) => {\n    const { output } = await buildProject({ format: 'cjs' })\n    expect(output).toHaveLength(1)\n    expect(output[0].code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/oxc.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { transformWithOxc } from '../../plugins/oxc'\n\ndescribe('transformWithOxc', () => {\n  test('correctly overrides TS configuration and applies automatic transform', async () => {\n    const jsxImportSource = 'bar'\n    const result = await transformWithOxc(\n      'const foo = () => <></>',\n      path.resolve(\n        import.meta.dirname,\n        './fixtures/oxc-tsconfigs/jsx-preserve/baz.jsx',\n      ),\n      {\n        jsx: {\n          runtime: 'automatic',\n          importSource: jsxImportSource,\n        },\n      },\n    )\n    expect(result?.code).toContain(`${jsxImportSource}/jsx-runtime`)\n    expect(result?.code).toContain('/* @__PURE__ */')\n  })\n\n  test('correctly overrides TS configuration and preserves code', async () => {\n    const foo = 'const foo = () => <></>'\n    const result = await transformWithOxc(\n      foo,\n      path.resolve(\n        import.meta.dirname,\n        './fixtures/oxc-tsconfigs/jsx-react-jsx/baz.jsx',\n      ),\n      {\n        jsx: 'preserve',\n      },\n    )\n    expect(result?.code).toContain(foo)\n  })\n\n  test('correctly overrides TS configuration and transforms code', async () => {\n    const jsxFactory = 'h',\n      jsxFragment = 'bar'\n    const result = await transformWithOxc(\n      'const foo = () => <></>',\n      path.resolve(\n        import.meta.dirname,\n        './fixtures/oxc-tsconfigs/jsx-complex-options/baz.jsx',\n      ),\n      {\n        jsx: {\n          runtime: 'classic',\n          pragma: jsxFactory,\n          pragmaFrag: jsxFragment,\n        },\n      },\n    )\n    expect(result?.code).toContain(\n      `/* @__PURE__ */ ${jsxFactory}(${jsxFragment}, null)`,\n    )\n  })\n\n  describe('useDefineForClassFields', async () => {\n    const transformClassCode = async (target: string, tsconfigDir: string) => {\n      const result = await transformWithOxc(\n        `\n          class foo {\n            bar = 'bar'\n          }\n        `,\n        path.resolve(import.meta.dirname, tsconfigDir, './bar.ts'),\n        { target },\n      )\n      return result?.code\n    }\n\n    const [\n      defineForClassFieldsTrueTransformedCode,\n      defineForClassFieldsTrueLowerTransformedCode,\n      defineForClassFieldsFalseTransformedCode,\n    ] = await Promise.all([\n      transformClassCode('esnext', './fixtures/oxc-tsconfigs/use-define-true'),\n      transformClassCode('es2021', './fixtures/oxc-tsconfigs/use-define-true'),\n      transformClassCode('esnext', './fixtures/oxc-tsconfigs/use-define-false'),\n    ])\n\n    test('target: esnext and tsconfig.target: esnext => true', async () => {\n      const actual = await transformClassCode(\n        'esnext',\n        './fixtures/oxc-tsconfigs/target-esnext',\n      )\n      expect(actual).toBe(defineForClassFieldsTrueTransformedCode)\n    })\n\n    test('target: es2021 and tsconfig.target: esnext => true', async () => {\n      const actual = await transformClassCode(\n        'es2021',\n        './fixtures/oxc-tsconfigs/target-esnext',\n      )\n      expect(actual).toBe(defineForClassFieldsTrueLowerTransformedCode)\n    })\n\n    test('target: es2021 and tsconfig.target: es2021 => false', async () => {\n      const actual = await transformClassCode(\n        'es2021',\n        './fixtures/oxc-tsconfigs/target-es2021',\n      )\n      expect(actual).toBe(defineForClassFieldsFalseTransformedCode)\n    })\n\n    test('target: esnext and tsconfig.target: es2021 => false', async () => {\n      const actual = await transformClassCode(\n        'esnext',\n        './fixtures/oxc-tsconfigs/target-es2021',\n      )\n      expect(actual).toBe(defineForClassFieldsFalseTransformedCode)\n    })\n\n    test('target: es2022 and tsconfig.target: es2022 => true', async () => {\n      const actual = await transformClassCode(\n        'es2022',\n        './fixtures/oxc-tsconfigs/target-es2022',\n      )\n      expect(actual).toBe(defineForClassFieldsTrueTransformedCode)\n    })\n\n    test('target: es2022 and tsconfig.target: undefined => false', async () => {\n      const actual = await transformClassCode(\n        'es2022',\n        './fixtures/oxc-tsconfigs/empty',\n      )\n      expect(actual).toBe(defineForClassFieldsFalseTransformedCode)\n    })\n  })\n\n  test('supports emitDecoratorMetadata: true', async () => {\n    const result = await transformWithOxc(\n      `\n          function LogMethod(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) {\n            console.log(target, propertyKey, descriptor);\n          }\n\n          class Demo {\n            @LogMethod\n            public foo(bar: number) {}\n          }\n\n          const demo = new Demo();\n        `,\n      path.resolve(\n        import.meta.dirname,\n        './fixtures/oxc-tsconfigs/decorator-metadata/bar.ts',\n      ),\n    )\n    expect(result?.code).toContain('_decorateMetadata(\"design:type\"')\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/pluginFilter.spec.ts",
    "content": "import util from 'node:util'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport type { ModuleTypeFilter } from 'rolldown'\nimport {\n  type StringFilter,\n  createCodeFilter,\n  createFilterForTransform,\n  createIdFilter,\n} from '../../plugins/pluginFilter'\n\ndescribe('createIdFilter', () => {\n  const filters = [\n    { inputFilter: undefined, cases: undefined },\n    {\n      inputFilter: 'foo.js',\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'foo.ts', expected: false },\n        { id: '\\0foo.js', expected: false },\n        { id: '\\0' + path.resolve('foo.js'), expected: false },\n      ],\n    },\n    {\n      inputFilter: ['foo.js'],\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'foo.ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: 'foo.js' },\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'foo.ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: '*.js' },\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'foo.ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: /\\.js$/ },\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'foo.ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: /\\/foo\\.js$/ },\n      cases: [\n        { id: 'a/foo.js', expected: true },\n        ...(process.platform === 'win32'\n          ? [{ id: 'a\\\\foo.js', expected: true }]\n          : []),\n        { id: 'a_foo.js', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: [/\\.js$/] },\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'foo.ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: { exclude: 'foo.js' },\n      cases: [\n        { id: 'foo.js', expected: false },\n        { id: 'foo.ts', expected: true },\n      ],\n    },\n    {\n      inputFilter: { exclude: '*.js' },\n      cases: [\n        { id: 'foo.js', expected: false },\n        { id: 'foo.ts', expected: true },\n      ],\n    },\n    {\n      inputFilter: { exclude: /\\.js$/ },\n      cases: [\n        { id: 'foo.js', expected: false },\n        { id: 'foo.ts', expected: true },\n      ],\n    },\n    {\n      inputFilter: { exclude: [/\\.js$/] },\n      cases: [\n        { id: 'foo.js', expected: false },\n        { id: 'foo.ts', expected: true },\n      ],\n    },\n    {\n      inputFilter: { include: 'foo.js', exclude: 'bar.js' },\n      cases: [\n        { id: 'foo.js', expected: true },\n        { id: 'bar.js', expected: false },\n        { id: 'baz.js', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: '*.js', exclude: 'foo.*' },\n      cases: [\n        { id: 'foo.js', expected: false }, // exclude has higher priority\n        { id: 'bar.js', expected: true },\n        { id: 'foo.ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: '/virtual/foo',\n      cases: [{ id: '/virtual/foo', expected: true }],\n    },\n  ]\n\n  for (const filter of filters) {\n    test(`${util.inspect(filter.inputFilter)}`, () => {\n      const idFilter = createIdFilter(filter.inputFilter, '')\n      if (!filter.cases) {\n        expect(idFilter).toBeUndefined()\n        return\n      }\n      expect(idFilter).not.toBeUndefined()\n\n      for (const testCase of filter.cases) {\n        const { id, expected } = testCase\n        expect(idFilter!(id), id).toBe(expected)\n      }\n    })\n  }\n})\n\ndescribe('createCodeFilter', () => {\n  const filters = [\n    { inputFilter: undefined, cases: undefined },\n    {\n      inputFilter: 'import.meta',\n      cases: [\n        { code: 'import.meta', expected: true },\n        { code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: ['import.meta'],\n      cases: [\n        { code: 'import.meta', expected: true },\n        { code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: 'import.meta' },\n      cases: [\n        { code: 'import.meta', expected: true },\n        { code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: /import\\.\\w+/ },\n      cases: [\n        { code: 'import.meta', expected: true },\n        { code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: [/import\\.\\w+/] },\n      cases: [\n        { code: 'import.meta', expected: true },\n        { code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: { exclude: 'import.meta' },\n      cases: [\n        { code: 'import.meta', expected: false },\n        { code: 'import_meta', expected: true },\n      ],\n    },\n    {\n      inputFilter: { exclude: /import\\.\\w+/ },\n      cases: [\n        { code: 'import.meta', expected: false },\n        { code: 'import_meta', expected: true },\n      ],\n    },\n    {\n      inputFilter: { exclude: [/import\\.\\w+/] },\n      cases: [\n        { code: 'import.meta', expected: false },\n        { code: 'import_meta', expected: true },\n      ],\n    },\n    {\n      inputFilter: { include: 'import.meta', exclude: 'import_meta' },\n      cases: [\n        { code: 'import.meta', expected: true },\n        { code: 'import_meta', expected: false },\n        { code: 'importmeta', expected: false },\n      ],\n    },\n    {\n      inputFilter: { include: /import\\.\\w+/, exclude: /\\w+\\.meta/ },\n      cases: [\n        { code: 'import.meta', expected: false }, // exclude has higher priority\n        { code: 'import.foo', expected: true },\n        { code: 'foo.meta', expected: false },\n      ],\n    },\n  ]\n\n  for (const filter of filters) {\n    test(`${util.inspect(filter.inputFilter)}`, () => {\n      const codeFilter = createCodeFilter(filter.inputFilter)\n      if (!filter.cases) {\n        expect(codeFilter).toBeUndefined()\n        return\n      }\n      expect(codeFilter).not.toBeUndefined()\n\n      for (const testCase of filter.cases) {\n        const { code, expected } = testCase\n        expect(codeFilter!(code), code).toBe(expected)\n      }\n    })\n  }\n})\n\ndescribe('createFilterForTransform', () => {\n  type Filters = {\n    inputFilter: [\n      idFilter: StringFilter | undefined,\n      codeFilter: StringFilter | undefined,\n      moduleTypeFilter?: ModuleTypeFilter | undefined,\n    ]\n    cases:\n      | {\n          id: string\n          code: string\n          moduleType?: string\n          expected: boolean\n        }[]\n      | undefined\n  }[]\n  const filters: Filters = [\n    { inputFilter: [undefined, undefined], cases: undefined },\n    {\n      inputFilter: ['*.js', undefined],\n      cases: [\n        { id: 'foo.js', code: 'foo', expected: true },\n        { id: 'foo.ts', code: 'foo', expected: false },\n      ],\n    },\n    {\n      inputFilter: [undefined, 'import.meta'],\n      cases: [\n        { id: 'foo.js', code: 'import.meta', expected: true },\n        { id: 'foo.js', code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: [{ exclude: '*.js' }, 'import.meta'],\n      cases: [\n        { id: 'foo.js', code: 'import.meta', expected: false },\n        { id: 'foo.js', code: 'import_meta', expected: false },\n        { id: 'foo.ts', code: 'import.meta', expected: true },\n        { id: 'foo.ts', code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: [{ include: 'foo.ts', exclude: '*.js' }, 'import.meta'],\n      cases: [\n        { id: 'foo.js', code: 'import.meta', expected: false },\n        { id: 'foo.js', code: 'import_meta', expected: false },\n        { id: 'foo.ts', code: 'import.meta', expected: true },\n        { id: 'foo.ts', code: 'import_meta', expected: false },\n      ],\n    },\n    {\n      inputFilter: [\n        { include: 'a*', exclude: '*b' },\n        { include: 'a', exclude: 'b' },\n      ],\n      cases: [\n        { id: 'ab', code: '', expected: false },\n        { id: 'a', code: 'b', expected: false },\n        { id: 'a', code: '', expected: false },\n        { id: 'c', code: 'a', expected: false },\n        { id: 'a', code: 'a', expected: true },\n      ],\n    },\n    {\n      inputFilter: [{ include: 'a*', exclude: '*b' }, { exclude: 'b' }],\n      cases: [\n        { id: 'ab', code: '', expected: false },\n        { id: 'a', code: 'b', expected: false },\n        { id: 'a', code: '', expected: true },\n        { id: 'c', code: 'a', expected: false },\n        { id: 'a', code: 'a', expected: true },\n      ],\n    },\n    {\n      inputFilter: [undefined, undefined, ['js']],\n      cases: [\n        { id: 'foo.js', code: 'foo', moduleType: 'js', expected: true },\n        { id: 'foo.ts', code: 'foo', moduleType: 'ts', expected: false },\n      ],\n    },\n    {\n      inputFilter: [undefined, undefined, { include: ['js'] }],\n      cases: [\n        { id: 'foo.js', code: 'foo', moduleType: 'js', expected: true },\n        { id: 'foo.ts', code: 'foo', moduleType: 'ts', expected: false },\n      ],\n    },\n  ]\n\n  for (const filter of filters) {\n    test(`${util.inspect(filter.inputFilter)}`, () => {\n      const [idFilter, codeFilter, moduleTypeFilter] = filter.inputFilter\n      const filterForTransform = createFilterForTransform(\n        idFilter,\n        codeFilter,\n        moduleTypeFilter,\n        '',\n      )\n      if (!filter.cases) {\n        expect(filterForTransform).toBeUndefined()\n        return\n      }\n      expect(filterForTransform).not.toBeUndefined()\n\n      for (const testCase of filter.cases) {\n        const { id, code, moduleType, expected } = testCase\n        expect(\n          filterForTransform!(id, code, moduleType ?? 'js'),\n          util.inspect({ id, code, moduleType }),\n        ).toBe(expected)\n      }\n    })\n  }\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/terser.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { build } from 'vite'\nimport type { RollupOutput } from 'rollup'\nimport type { TerserOptions } from '../../plugins/terser'\n\ndescribe('terser', () => {\n  const run = async (terserOptions: TerserOptions) => {\n    const result = (await build({\n      root: resolve(import.meta.dirname, '../packages/build-project'),\n      logLevel: 'silent',\n      build: {\n        write: false,\n        minify: 'terser',\n        terserOptions,\n      },\n      plugins: [\n        {\n          name: 'test',\n          resolveId(id) {\n            if (id === 'entry.js') {\n              return '\\0' + id\n            }\n          },\n          load(id) {\n            if (id === '\\0entry.js') {\n              return `\n                const foo = 1;\n                console.log(foo);\n                const bar = { hello: 1, [\"world\"]: 2 };\n                console.log(bar.hello + bar[\"world\"]);\n              `\n            }\n          },\n        },\n      ],\n    })) as RollupOutput\n    return result.output[0].code\n  }\n\n  test('basic', async () => {\n    await run({})\n  })\n\n  test('nth', async () => {\n    const resultCode = await run({\n      mangle: {\n        nth_identifier: {\n          get: (n) => {\n            return 'prefix_' + n.toString()\n          },\n        },\n      },\n    })\n    expect(resultCode).toContain('prefix_')\n  })\n\n  test('nameCache', async () => {\n    const nameCache = {}\n\n    await run({\n      compress: false,\n      mangle: {\n        properties: {\n          keep_quoted: true,\n        },\n      },\n      nameCache,\n    })\n\n    expect(nameCache).toHaveProperty('props.props.$hello')\n    expect(nameCache).not.toHaveProperty('props.props.$world')\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/wasm.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { assetUrlRE } from '../../plugins/asset'\n\ndescribe('wasm plugin assetUrlRE usage', () => {\n  // Regression test: assetUrlRE has the /g flag, which makes .test()\n  // stateful via lastIndex. When the wasm plugin called assetUrlRE.test()\n  // on consecutive asset URLs without resetting lastIndex, the second call\n  // would fail because lastIndex was already past the end of the string.\n  // This caused a non-deterministic bug where ~half of wasm files would\n  // miss the __VITE_ASSET__ -> __VITE_WASM_INIT__ replacement in SSR\n  // builds, leading to ENOENT errors at runtime.\n  test('assetUrlRE.test() fails on second call without lastIndex reset', () => {\n    const url1 = '__VITE_ASSET__abc123__'\n    const url2 = '__VITE_ASSET__def456__'\n\n    // Simulate the bug: two consecutive .test() calls without resetting lastIndex\n    assetUrlRE.lastIndex = 0\n    expect(assetUrlRE.test(url1)).toBe(true)\n    // After the first successful match, lastIndex is advanced past the string\n    expect(assetUrlRE.lastIndex).toBeGreaterThan(0)\n    // The second call fails because lastIndex > url2.length\n    expect(assetUrlRE.test(url2)).toBe(false)\n\n    // Clean up\n    assetUrlRE.lastIndex = 0\n  })\n\n  test('assetUrlRE.test() succeeds on consecutive calls with lastIndex reset', () => {\n    const url1 = '__VITE_ASSET__abc123__'\n    const url2 = '__VITE_ASSET__def456__'\n\n    assetUrlRE.lastIndex = 0\n    expect(assetUrlRE.test(url1)).toBe(true)\n\n    // The fix: reset lastIndex before the next call\n    assetUrlRE.lastIndex = 0\n    expect(assetUrlRE.test(url2)).toBe(true)\n\n    // Clean up\n    assetUrlRE.lastIndex = 0\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/worker.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { expect, test } from 'vitest'\nimport type { OutputChunk, RolldownOutput } from 'rolldown'\nimport { build } from '../../build'\n\nconst fixturesDir = resolve(import.meta.dirname, 'fixtures')\n\ntest('?worker&url should produce the same hash in client and SSR builds', async () => {\n  const root = resolve(fixturesDir, 'worker-url')\n\n  const clientResult = (await build({\n    root,\n    logLevel: 'silent',\n    build: {\n      write: false,\n      rolldownOptions: {\n        input: resolve(root, 'entry.js'),\n      },\n    },\n  })) as RolldownOutput\n\n  const ssrResult = (await build({\n    root,\n    logLevel: 'silent',\n    build: {\n      write: false,\n      ssr: resolve(root, 'entry.js'),\n    },\n  })) as RolldownOutput\n\n  // Extract the worker URL from both builds.\n  // The entry chunk will contain the worker asset URL as a string.\n  const clientEntry = clientResult.output.find(\n    (o): o is OutputChunk => o.type === 'chunk' && o.isEntry,\n  )!\n  const ssrEntry = ssrResult.output.find(\n    (o): o is OutputChunk => o.type === 'chunk' && o.isEntry,\n  )!\n\n  const workerUrlPattern = /assets\\/worker-[\\w-]+\\.js/g\n  const clientWorkerUrls = clientEntry.code.match(workerUrlPattern) ?? []\n  const ssrWorkerUrls = ssrEntry.code.match(workerUrlPattern) ?? []\n\n  expect(clientWorkerUrls.length).toBeGreaterThan(0)\n  expect(ssrWorkerUrls.length).toBeGreaterThan(0)\n  expect(ssrWorkerUrls).toEqual(clientWorkerUrls)\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/plugins/workerImportMetaUrl.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { parseAst } from 'rollup/parseAst'\nimport { workerImportMetaUrlPlugin } from '../../plugins/workerImportMetaUrl'\nimport { resolveConfig } from '../../config'\nimport { PartialEnvironment } from '../../baseEnvironment'\n\nasync function createWorkerImportMetaUrlPluginTransform() {\n  const config = await resolveConfig({ configFile: false }, 'serve')\n  const instance = workerImportMetaUrlPlugin(config)\n  const environment = new PartialEnvironment('client', config)\n\n  return async (code: string) => {\n    // @ts-expect-error transform.handler should exist\n    const result = await instance.transform.handler.call(\n      { environment, parse: parseAst },\n      code,\n      'foo.ts',\n    )\n    return result?.code || result\n  }\n}\n\ndescribe('workerImportMetaUrlPlugin', async () => {\n  const transform = await createWorkerImportMetaUrlPluginTransform()\n\n  test('without worker options', async () => {\n    expect(\n      await transform('new Worker(new URL(\"./worker.js\", import.meta.url))'),\n    ).toMatchInlineSnapshot(\n      `\"new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=classic\", '' + import.meta.url))\"`,\n    )\n  })\n\n  test('with shared worker', async () => {\n    expect(\n      await transform(\n        'new SharedWorker(new URL(\"./worker.js\", import.meta.url))',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new SharedWorker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=classic\", '' + import.meta.url))\"`,\n    )\n  })\n\n  test('with static worker options and identifier properties', async () => {\n    expect(\n      await transform(\n        'new Worker(new URL(\"./worker.js\", import.meta.url), { type: \"module\", name: \"worker1\" })',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url), { type: \"module\", name: \"worker1\" })\"`,\n    )\n  })\n\n  test('with static worker options and literal properties', async () => {\n    expect(\n      await transform(\n        'new Worker(new URL(\"./worker.js\", import.meta.url), { \"type\": \"module\", \"name\": \"worker1\" })',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url), { \"type\": \"module\", \"name\": \"worker1\" })\"`,\n    )\n  })\n\n  test('with dynamic name field in worker options', async () => {\n    expect(\n      await transform(\n        'const id = 1; new Worker(new URL(\"./worker.js\", import.meta.url), { name: \"worker\" + id })',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"const id = 1; new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=classic\", '' + import.meta.url), { name: \"worker\" + id })\"`,\n    )\n  })\n\n  test('with interpolated dynamic name field in worker options', async () => {\n    expect(\n      await transform(\n        'const id = 1; new Worker(new URL(\"./worker.js\", import.meta.url), { name: `worker-${id}` })',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"const id = 1; new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=classic\", '' + import.meta.url), { name: \\`worker-\\${id}\\` })\"`,\n    )\n  })\n\n  test('with dynamic name field and static type in worker options', async () => {\n    expect(\n      await transform(\n        'const id = 1; new Worker(new URL(\"./worker.js\", import.meta.url), { name: \"worker\" + id, type: \"module\" })',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"const id = 1; new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url), { name: \"worker\" + id, type: \"module\" })\"`,\n    )\n  })\n\n  test('with interpolated dynamic name field and static type in worker options', async () => {\n    expect(\n      await transform(\n        'const id = 1; new Worker(new URL(\"./worker.js\", import.meta.url), { name: `worker-${id}`, type: \"module\" })',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"const id = 1; new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url), { name: \\`worker-\\${id}\\`, type: \"module\" })\"`,\n    )\n  })\n\n  test('with parenthesis inside of worker options', async () => {\n    expect(\n      await transform(\n        'const worker = new Worker(new URL(\"./worker.js\", import.meta.url), { name: genName(), type: \"module\"})',\n      ),\n    ).toMatchInlineSnapshot(\n      `\"const worker = new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url), { name: genName(), type: \"module\"})\"`,\n    )\n  })\n\n  test('with multi-line code and worker options', async () => {\n    expect(\n      await transform(`\nconst worker = new Worker(new URL(\"./worker.js\", import.meta.url), {\n    name: genName(),\n    type: \"module\",\n  },\n)\n\nworker.addEventListener('message', (ev) => text('.simple-worker-url', JSON.stringify(ev.data)))\n`),\n    ).toMatchInlineSnapshot(`\n      \"\n      const worker = new Worker(new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url), {\n          name: genName(),\n          type: \"module\",\n        },\n      )\n\n      worker.addEventListener('message', (ev) => text('.simple-worker-url', JSON.stringify(ev.data)))\n      \"\n    `)\n  })\n\n  test('trailing comma', async () => {\n    expect(\n      await transform(`\nnew Worker(\n  new URL('./worker.js', import.meta.url),\n  {\n    type: 'module'\n  }, // },\n)\n`),\n    ).toMatchInlineSnapshot(`\n      \"\n      new Worker(\n        new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url),\n        {\n          type: 'module'\n        }, // },\n      )\n      \"\n    `)\n  })\n\n  test('throws an error when non-static worker options are provided', async () => {\n    await expect(\n      transform(\n        'new Worker(new URL(\"./worker.js\", import.meta.url), myWorkerOptions)',\n      ),\n    ).rejects.toThrow(\n      'Vite is unable to parse the worker options as the value is not static. To ignore this error, please use /* @vite-ignore */ in the worker options.',\n    )\n  })\n\n  test('throws an error when worker options are not an object', async () => {\n    await expect(\n      transform(\n        'new Worker(new URL(\"./worker.js\", import.meta.url), \"notAnObject\")',\n      ),\n    ).rejects.toThrow('Expected worker options to be an object, got string')\n  })\n\n  test('throws an error when non-literal type field in worker options', async () => {\n    await expect(\n      transform(\n        'const type = \"module\"; new Worker(new URL(\"./worker.js\", import.meta.url), { type })',\n      ),\n    ).rejects.toThrow(\n      'Expected worker options type property to be a literal value.',\n    )\n  })\n\n  test('throws an error when spread operator used without the type field', async () => {\n    await expect(\n      transform(\n        'const options = { name: \"worker1\" }; new Worker(new URL(\"./worker.js\", import.meta.url), { ...options })',\n      ),\n    ).rejects.toThrow(\n      'Expected object spread to be used before the definition of the type property. Vite needs a static value for the type property to correctly infer it.',\n    )\n  })\n\n  test('throws an error when spread operator used after definition of type field', async () => {\n    await expect(\n      transform(\n        'const options = { name: \"worker1\" }; new Worker(new URL(\"./worker.js\", import.meta.url), { type: \"module\", ...options })',\n      ),\n    ).rejects.toThrow(\n      'Expected object spread to be used before the definition of the type property. Vite needs a static value for the type property to correctly infer it.',\n    )\n  })\n\n  test('find closing parenthesis correctly', async () => {\n    expect(\n      await transform(\n        `(() => { new Worker(new URL('./worker', import.meta.url)); repro({ test: \"foo\", }); })();`,\n      ),\n    ).toMatchInlineSnapshot(\n      `\"(() => { new Worker(new URL(/* @vite-ignore */ \"/worker?worker_file&type=classic\", '' + import.meta.url)); repro({ test: \"foo\", }); })();\"`,\n    )\n    expect(\n      await transform(\n        `repro(new Worker(new URL('./worker', import.meta.url)), { type: \"module\" })`,\n      ),\n    ).toMatchInlineSnapshot(\n      `\"repro(new Worker(new URL(/* @vite-ignore */ \"/worker?worker_file&type=classic\", '' + import.meta.url)), { type: \"module\" })\"`,\n    )\n  })\n\n  test('with multi-line new URL and trailing comma', async () => {\n    expect(\n      await transform(`new Worker(\n  new URL(\n    \"./worker.js\",\n    import.meta.url,\n  )\n)`),\n    ).toMatchInlineSnapshot(`\n      \"new Worker(\n        new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=classic\", '' + import.meta.url)\n      )\"\n    `)\n  })\n\n  test('with multi-line new URL, trailing comma, and worker options', async () => {\n    expect(\n      await transform(`const worker = new Worker(\n  new URL(\n    \"./worker.js\",\n    import.meta.url,\n  ),\n  { type: \"module\" },\n)`),\n    ).toMatchInlineSnapshot(`\n      \"const worker = new Worker(\n        new URL(/* @vite-ignore */ \"/worker.js?worker_file&type=module\", '' + import.meta.url),\n        { type: \"module\" },\n      )\"\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/resolve.spec.ts",
    "content": "import { join } from 'node:path'\nimport { describe, expect, onTestFinished, test, vi } from 'vitest'\nimport { createServer } from '../server'\nimport { createServerModuleRunner } from '../ssr/runtime/serverModuleRunner'\nimport type { EnvironmentOptions, InlineConfig } from '../config'\nimport { build } from '../build'\n\ndescribe('import and resolveId', () => {\n  async function createTestServer() {\n    const server = await createServer({\n      configFile: false,\n      root: import.meta.dirname,\n      logLevel: 'error',\n      server: {\n        middlewareMode: true,\n        ws: false,\n      },\n    })\n    onTestFinished(() => server.close())\n    const runner = createServerModuleRunner(server.environments.ssr, {\n      hmr: {\n        logger: false,\n      },\n      sourcemapInterceptor: false,\n    })\n    return { server, runner }\n  }\n\n  test('import first', async () => {\n    const { server, runner } = await createTestServer()\n    const mod = await runner.import(\n      '/fixtures/test-dep-conditions-app/entry-with-module',\n    )\n    const resolved = await server.environments.ssr.pluginContainer.resolveId(\n      '@vitejs/test-dep-conditions/with-module',\n    )\n    expect([mod.default, resolved?.id]).toEqual([\n      'dir/index.default.js',\n      expect.stringContaining('dir/index.module.js'),\n    ])\n  })\n\n  test('resolveId first', async () => {\n    const { server, runner } = await createTestServer()\n    const resolved = await server.environments.ssr.pluginContainer.resolveId(\n      '@vitejs/test-dep-conditions/with-module',\n    )\n    const mod = await runner.import(\n      '/fixtures/test-dep-conditions-app/entry-with-module',\n    )\n    expect([mod.default, resolved?.id]).toEqual([\n      'dir/index.default.js',\n      expect.stringContaining('dir/index.module.js'),\n    ])\n  })\n})\n\ndescribe('file url', () => {\n  const fileUrl = new URL('./fixtures/file-url/entry.js', import.meta.url)\n\n  function getConfig(): InlineConfig {\n    return {\n      configFile: false,\n      root: join(import.meta.dirname, 'fixtures/file-url'),\n      logLevel: 'error',\n      server: {\n        middlewareMode: true,\n      },\n      plugins: [\n        {\n          name: 'virtual-file-url',\n          resolveId(source) {\n            if (source.startsWith('virtual:test-dep/')) {\n              return '\\0' + source\n            }\n          },\n          load(id) {\n            if (id === '\\0virtual:test-dep/static') {\n              return `\n                import * as dep from ${JSON.stringify(fileUrl.href)};\n                export default dep;\n              `\n            }\n            if (id === '\\0virtual:test-dep/static-postfix') {\n              return `\n                import * as dep from ${JSON.stringify(fileUrl.href + '?query=test')};\n                export default dep;\n              `\n            }\n            if (id === '\\0virtual:test-dep/non-static') {\n              return `\n                const dep = await import(/* @vite-ignore */ String(${JSON.stringify(fileUrl.href)}));\n                export default dep;\n              `\n            }\n            if (id === '\\0virtual:test-dep/non-static-postfix') {\n              return `\n                const dep = await import(/* @vite-ignore */ String(${JSON.stringify(fileUrl.href + '?query=test')}));\n                export default dep;\n              `\n            }\n          },\n        },\n      ],\n    }\n  }\n\n  test('dev', async () => {\n    const server = await createServer(getConfig())\n    onTestFinished(() => server.close())\n\n    const runner = createServerModuleRunner(server.environments.ssr, {\n      hmr: {\n        logger: false,\n      },\n      sourcemapInterceptor: false,\n    })\n\n    const mod = await runner.import('/entry.js')\n    expect(mod.default).toEqual('ok')\n\n    const mod2 = await runner.import(fileUrl.href)\n    expect(mod2).toBe(mod)\n\n    const mod3 = await runner.import('virtual:test-dep/static')\n    expect(mod3.default).toBe(mod)\n\n    const mod4 = await runner.import('virtual:test-dep/non-static')\n    expect(mod4.default).toBe(mod)\n\n    const mod5 = await runner.import(fileUrl.href + '?query=test')\n    expect(mod5).toEqual(mod)\n    expect(mod5).not.toBe(mod)\n\n    const mod6 = await runner.import('virtual:test-dep/static-postfix')\n    expect(mod6.default).toEqual(mod)\n    expect(mod6.default).not.toBe(mod)\n    expect(mod6.default).toBe(mod5)\n\n    const mod7 = await runner.import('virtual:test-dep/non-static-postfix')\n    expect(mod7.default).toEqual(mod)\n    expect(mod7.default).not.toBe(mod)\n    expect(mod7.default).toBe(mod5)\n  })\n\n  describe('environment builtins', () => {\n    function getConfig(\n      targetEnv: 'client' | 'ssr' | string,\n      builtins: NonNullable<EnvironmentOptions['resolve']>['builtins'],\n    ): InlineConfig {\n      return {\n        configFile: false,\n        root: join(import.meta.dirname, 'fixtures/file-url'),\n        logLevel: 'error',\n        server: {\n          middlewareMode: true,\n        },\n        environments: {\n          [targetEnv]: {\n            resolve: {\n              builtins,\n            },\n          },\n        },\n      }\n    }\n\n    async function run({\n      builtins,\n      targetEnv = 'custom',\n      testEnv = 'custom',\n      idToResolve,\n    }: {\n      builtins?: NonNullable<EnvironmentOptions['resolve']>['builtins']\n      targetEnv?: 'client' | 'ssr' | string\n      testEnv?: 'client' | 'ssr' | string\n      idToResolve: string\n    }) {\n      const server = await createServer(getConfig(targetEnv, builtins))\n      vi.spyOn(server.config.logger, 'warn').mockImplementationOnce(\n        (message) => {\n          throw new Error(message)\n        },\n      )\n      onTestFinished(() => server.close())\n\n      return server.environments[testEnv]?.pluginContainer.resolveId(\n        idToResolve,\n      )\n    }\n\n    test('declared builtin string', async () => {\n      const resolved = await run({\n        builtins: ['my-env:custom-builtin'],\n        idToResolve: 'my-env:custom-builtin',\n      })\n      expect(resolved?.external).toBe(true)\n    })\n\n    test('declared builtin regexp', async () => {\n      const resolved = await run({\n        builtins: [/^my-env:\\w/],\n        idToResolve: 'my-env:custom-builtin',\n      })\n      expect(resolved?.external).toBe(true)\n    })\n\n    test('non declared builtin', async () => {\n      const resolved = await run({\n        builtins: [\n          /* empty */\n        ],\n        idToResolve: 'my-env:custom-builtin',\n      })\n      expect(resolved).toBeNull()\n    })\n\n    test('non declared node builtin', async () => {\n      await expect(\n        run({\n          builtins: [\n            /* empty */\n          ],\n          idToResolve: 'node:fs',\n        }),\n      ).rejects.toThrowError(\n        /warning: Automatically externalized node built-in module \"node:fs\"/,\n      )\n    })\n\n    test('default to node-like builtins', async () => {\n      const resolved = await run({\n        idToResolve: 'node:fs',\n      })\n      expect(resolved?.external).toBe(true)\n    })\n\n    test('default to node-like builtins for ssr environment', async () => {\n      const resolved = await run({\n        idToResolve: 'node:fs',\n        testEnv: 'ssr',\n      })\n      expect(resolved?.external).toBe(true)\n    })\n\n    test('no default to node-like builtins for client environment', async () => {\n      const resolved = await run({\n        idToResolve: 'node:fs',\n        testEnv: 'client',\n      })\n      expect(resolved?.id).toEqual('__vite-browser-external:node:fs')\n    })\n\n    test('no builtins overriding for client environment', async () => {\n      const resolved = await run({\n        idToResolve: 'node:fs',\n        testEnv: 'client',\n        targetEnv: 'client',\n      })\n      expect(resolved?.id).toEqual('__vite-browser-external:node:fs')\n    })\n\n    test('declared node builtin', async () => {\n      const resolved = await run({\n        builtins: [/^node:/],\n        idToResolve: 'node:fs',\n      })\n      expect(resolved?.external).toBe(true)\n    })\n\n    test('declared builtin string in different environment', async () => {\n      const resolved = await run({\n        builtins: ['my-env:custom-builtin'],\n        idToResolve: 'my-env:custom-builtin',\n        targetEnv: 'custom',\n        testEnv: 'ssr',\n      })\n      expect(resolved).toBe(null)\n    })\n  })\n\n  test('build', async () => {\n    await build({\n      ...getConfig(),\n      build: {\n        ssr: true,\n        outDir: 'dist/basic',\n        rollupOptions: {\n          input: { index: fileUrl.href },\n        },\n      },\n    })\n    const mod1 = await import(\n      join(import.meta.dirname, 'fixtures/file-url/dist/basic/index.js')\n    )\n    expect(mod1.default).toBe('ok')\n\n    await build({\n      ...getConfig(),\n      build: {\n        ssr: true,\n        outDir: 'dist/virtual',\n        rollupOptions: {\n          input: { index: 'virtual:test-dep/static' },\n        },\n      },\n    })\n    const mod2 = await import(\n      join(import.meta.dirname, 'fixtures/file-url/dist/virtual/index.js')\n    )\n    expect(mod2.default.default).toBe('ok')\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/runnerImport.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { loadConfigFromFile } from 'vite'\nimport { runnerImport } from '../ssr/runnerImport'\nimport { slash } from '../../shared/utils'\n\n// eslint-disable-next-line n/no-unsupported-features/node-builtins\nconst isTypeStrippingSupported = !!process.features.typescript\n\ndescribe('importing files using inlined environment', () => {\n  const fixture = (name: string) =>\n    resolve(import.meta.dirname, './fixtures/runner-import', name)\n\n  test('importing a basic file works', async () => {\n    const { module } = await runnerImport<\n      typeof import('./fixtures/runner-import/basic')\n    >(fixture('basic'))\n    expect(module.test).toEqual({\n      field: true,\n    })\n  })\n\n  test(\"cannot import cjs, 'runnerImport' doesn't support CJS syntax at all\", async () => {\n    await expect(() =>\n      runnerImport<typeof import('./fixtures/runner-import/basic')>(\n        fixture('cjs.js'),\n      ),\n    ).rejects.toThrow('module is not defined')\n  })\n\n  test('can import vite config', async () => {\n    const { module, dependencies } = await runnerImport<\n      typeof import('./fixtures/runner-import/vite.config')\n    >(fixture('vite.config'))\n    expect(module.default).toEqual({\n      root: './test',\n      plugins: [\n        {\n          name: 'test',\n        },\n      ],\n    })\n    expect(dependencies).toEqual([slash(fixture('plugin.ts'))])\n  })\n\n  test('can import vite config that imports a TS external module', async () => {\n    const { module, dependencies } = await runnerImport<\n      typeof import('./fixtures/runner-import/vite.config.outside-pkg-import.mjs')\n    >(fixture('vite.config.outside-pkg-import.mts'))\n\n    expect(module.default.__injected).toBe(true)\n    expect(dependencies).toEqual([\n      slash(resolve(import.meta.dirname, './packages/parent/index.ts')),\n    ])\n\n    // confirm that it fails with a bundle approach\n    if (!isTypeStrippingSupported) {\n      await expect(async () => {\n        const root = resolve(import.meta.dirname, './fixtures/runner-import')\n        await loadConfigFromFile(\n          { mode: 'production', command: 'serve' },\n          resolve(root, './vite.config.outside-pkg-import.mts'),\n          root,\n          'silent',\n        )\n      }).rejects.toThrow('Unknown file extension \".ts\"')\n    }\n  })\n\n  test('dynamic import', async () => {\n    const { module } = await runnerImport<any>(fixture('dynamic-import.ts'))\n    await expect(() => module.default()).rejects.toMatchInlineSnapshot(\n      `[Error: Vite module runner has been closed.]`,\n    )\n    // const dep = await module.default();\n    // expect(dep.default).toMatchInlineSnapshot(`\"ok\"`)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/scan.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { commentRE, importsRE, scriptRE } from '../optimizer/scan'\nimport { multilineCommentsRE, singlelineCommentsRE } from '../utils'\nimport { createServer, createServerModuleRunner } from '..'\n\ndescribe('optimizer-scan:script-test', () => {\n  const scriptContent = `import { defineComponent } from 'vue'\n      import ScriptDevelopPane from './ScriptDevelopPane.vue';\n      export default defineComponent({\n        components: {\n          ScriptDevelopPane\n        }\n      })`\n\n  test('component return value test', () => {\n    scriptRE.lastIndex = 0\n    const [, tsOpenTag, tsContent] = scriptRE.exec(\n      `<script lang=\"ts\">${scriptContent}</script>`,\n    )!\n    expect(tsOpenTag).toEqual('<script lang=\"ts\">')\n    expect(tsContent).toEqual(scriptContent)\n\n    scriptRE.lastIndex = 0\n    const [, openTag, content] = scriptRE.exec(\n      `<script>${scriptContent}</script>`,\n    )!\n    expect(openTag).toEqual('<script>')\n    expect(content).toEqual(scriptContent)\n  })\n\n  test('include comments test', () => {\n    scriptRE.lastIndex = 0\n    const ret = scriptRE.exec(\n      `<template>\n        <!--  <script >var test1 = null</script> -->\n        <!--  <script >var test2 = null</script> -->\n      </template>`.replace(commentRE, ''),\n    )\n    expect(ret).toEqual(null)\n  })\n\n  test('components with script keyword test', () => {\n    scriptRE.lastIndex = 0\n    let ret = scriptRE.exec(`<template><script-develop-pane/></template>`)\n    expect(ret).toBe(null)\n\n    scriptRE.lastIndex = 0\n    ret = scriptRE.exec(\n      `<template><script-develop-pane></script-develop-pane></template>`,\n    )\n    expect(ret).toBe(null)\n\n    scriptRE.lastIndex = 0\n    ret = scriptRE.exec(\n      `<template><script-develop-pane  > content </script-develop-pane></template>`,\n    )\n    expect(ret).toBe(null)\n  })\n\n  test('ordinary script tag test', () => {\n    scriptRE.lastIndex = 0\n    const [, tag, content] = scriptRE.exec(\n      `<script  >var test = null</script>`,\n    )!\n    expect(tag).toEqual('<script  >')\n    expect(content).toEqual('var test = null')\n\n    scriptRE.lastIndex = 0\n    const [, tag1, content1] = scriptRE.exec(\n      `<script>var test = null</script>`,\n    )!\n    expect(tag1).toEqual('<script>')\n    expect(content1).toEqual('var test = null')\n  })\n\n  test('imports regex should work', () => {\n    const shouldMatchArray = [\n      `import 'vue'`,\n      `import { foo } from 'vue'`,\n      `import foo from 'vue'`,\n      `;import foo from 'vue'`,\n      `   import foo from 'vue'`,\n      `import { foo\n      } from 'vue'`,\n      `import bar, { foo } from 'vue'`,\n      `import foo from 'vue';`,\n      `*/ import foo from 'vue';`,\n      `import foo from 'vue';//comment`,\n      `import foo from 'vue';/*comment\n      */`,\n      // Skipped, false negatives with current regex\n      // `import typescript from 'typescript'`,\n      // import type, {foo} from 'vue'\n    ]\n\n    shouldMatchArray.forEach((str) => {\n      importsRE.lastIndex = 0\n      expect(importsRE.exec(str)![1]).toEqual(\"'vue'\")\n    })\n\n    const shouldFailArray = [\n      `testMultiline(\"import\", {\n        body: \"ok\" });`,\n      `//;import foo from 'vue'`,\n      `import type { Bar } from 'foo'`,\n      `import type{ Bar } from 'foo'`,\n      `import type Bar from 'foo'`,\n    ]\n    shouldFailArray.forEach((str) => {\n      importsRE.lastIndex = 0\n      expect(importsRE.test(str)).toBe(false)\n    })\n  })\n\n  test('script comments test', () => {\n    multilineCommentsRE.lastIndex = 0\n    let ret = `/*\n      export default { }\n      */`.replace(multilineCommentsRE, '')\n    expect(ret).not.toContain('export default')\n\n    singlelineCommentsRE.lastIndex = 0\n    ret = `//export default { }`.replace(singlelineCommentsRE, '')\n    expect(ret).not.toContain('export default')\n  })\n})\n\ntest('scan jsx-runtime', async (ctx) => {\n  const server = await createServer({\n    configFile: false,\n    logLevel: 'error',\n    root: path.join(import.meta.dirname, 'fixtures', 'scan-jsx-runtime'),\n    environments: {\n      client: {\n        // silence client optimizer\n        optimizeDeps: {\n          noDiscovery: true,\n        },\n      },\n      ssr: {\n        resolve: {\n          noExternal: true,\n        },\n        optimizeDeps: {\n          force: true,\n          noDiscovery: false,\n          entries: ['./entry-jsx.tsx', './entry-no-jsx.js'],\n        },\n      },\n    },\n  })\n\n  // start server to ensure optimizer run\n  await server.listen()\n  ctx.onTestFinished(() => server.close())\n\n  const runner = createServerModuleRunner(server.environments.ssr, {\n    hmr: { logger: false },\n  })\n\n  // flush initial optimizer by importing any file\n  await runner.import('./entry-no-jsx.js')\n\n  // verify jsx won't trigger optimizer re-run\n  const mod1 = await runner.import('./entry-jsx.js')\n  const mod2 = await runner.import('./entry-jsx.js')\n  expect((globalThis as any).__test_scan_jsx_runtime).toBe(1)\n  expect(mod1).toBe(mod2)\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/shortcuts.spec.ts",
    "content": "import type { Mock } from 'vitest'\nimport { describe, expect, test, vi } from 'vitest'\nimport { createServer } from '../server'\nimport { preview } from '../preview'\nimport { bindCLIShortcuts } from '../shortcuts'\n\ndescribe('bindCLIShortcuts', () => {\n  test.each([\n    ['dev server', () => createServer()],\n    ['preview server', () => preview()],\n  ])('binding custom shortcuts with the %s', async (_, startServer) => {\n    const server = await startServer()\n\n    try {\n      const xAction = vi.fn()\n      const yAction = vi.fn()\n\n      bindCLIShortcuts(\n        server,\n        {\n          customShortcuts: [\n            { key: 'x', description: 'test x', action: xAction },\n            { key: 'y', description: 'test y', action: yAction },\n          ],\n        },\n        true,\n      )\n\n      expect.assert(\n        server._shortcutsState?.rl,\n        'The readline interface should be defined after binding shortcuts.',\n      )\n      expect(xAction).not.toHaveBeenCalled()\n\n      server._shortcutsState.rl.emit('line', 'x')\n      await vi.waitFor(() => expect(xAction).toHaveBeenCalledOnce())\n\n      const xUpdatedAction = vi.fn()\n      const zAction = vi.fn()\n\n      bindCLIShortcuts(\n        server,\n        {\n          customShortcuts: [\n            { key: 'x', description: 'test x updated', action: xUpdatedAction },\n            { key: 'z', description: 'test z', action: zAction },\n          ],\n        },\n        true,\n      )\n\n      expect(xUpdatedAction).not.toHaveBeenCalled()\n      server._shortcutsState.rl.emit('line', 'x')\n      await vi.waitFor(() => expect(xUpdatedAction).toHaveBeenCalledOnce())\n\n      // Ensure original xAction is not called again\n      expect(xAction).toHaveBeenCalledOnce()\n\n      expect(yAction).not.toHaveBeenCalled()\n      server._shortcutsState.rl.emit('line', 'y')\n      await vi.waitFor(() => expect(yAction).toHaveBeenCalledOnce())\n\n      expect(zAction).not.toHaveBeenCalled()\n      server._shortcutsState.rl.emit('line', 'z')\n      await vi.waitFor(() => expect(zAction).toHaveBeenCalledOnce())\n    } finally {\n      await server.close()\n    }\n  })\n\n  test('rebinds shortcuts after server restart', async () => {\n    const manualShortcutAction = vi.fn()\n    const pluginShortcutActions: Array<Mock<any>> = []\n\n    const server = await createServer({\n      plugins: [\n        {\n          name: 'custom-shortcut-plugin',\n          configureServer(viteDevServer) {\n            const action = vi.fn()\n\n            // Keep track of actions created by the plugin\n            // To verify if they are overwritten on server restart\n            pluginShortcutActions.push(action)\n\n            // Bind custom shortcut from plugin\n            bindCLIShortcuts(\n              viteDevServer,\n              {\n                customShortcuts: [\n                  {\n                    key: 'y',\n                    description: 'plugin shortcut',\n                    action,\n                  },\n                ],\n              },\n              true,\n            )\n          },\n        },\n      ],\n    })\n\n    try {\n      const readline = server._shortcutsState?.rl\n\n      expect.assert(\n        readline,\n        'The readline interface should be defined after binding shortcuts.',\n      )\n\n      readline.emit('line', 'y')\n      await vi.waitFor(() => {\n        expect(pluginShortcutActions).toHaveLength(1)\n        expect(pluginShortcutActions[0]).toHaveBeenCalledOnce()\n      })\n\n      // Manually bind another custom shortcut\n      bindCLIShortcuts(\n        server,\n        {\n          customShortcuts: [\n            {\n              key: 'x',\n              description: 'manual shortcut',\n              action: manualShortcutAction,\n            },\n          ],\n        },\n        true,\n      )\n\n      readline.emit('line', 'x')\n      await vi.waitFor(() =>\n        expect(manualShortcutAction).toHaveBeenCalledOnce(),\n      )\n\n      // Check the order of shortcuts before restart\n      expect(\n        server._shortcutsState?.options.customShortcuts?.map((s) => s.key),\n      ).toEqual(['x', 'y'])\n\n      // Restart the server\n      await server.restart()\n\n      // Shortcut orders should be preserved after restart\n      expect(\n        server._shortcutsState?.options.customShortcuts?.map((s) => s.key),\n      ).toEqual(['x', 'y'])\n\n      expect.assert(\n        server._shortcutsState?.rl === readline,\n        'The readline interface should be preserved.',\n      )\n\n      // Shortcuts should still work after restart\n      readline.emit('line', 'x')\n      await vi.waitFor(() =>\n        expect(manualShortcutAction).toHaveBeenCalledTimes(2),\n      )\n\n      readline.emit('line', 'y')\n      await vi.waitFor(() => {\n        expect(pluginShortcutActions).toHaveLength(2)\n        expect(pluginShortcutActions[1]).toHaveBeenCalledOnce()\n        expect(pluginShortcutActions[0]).toHaveBeenCalledOnce()\n      })\n    } finally {\n      await server.close()\n    }\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests__/utils/isFileReadable/permission-test-file",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/__tests__/utils.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { describe, expect, test } from 'vitest'\nimport { fileURLToPath } from 'mlly'\nimport {\n  asyncFlatten,\n  bareImportRE,\n  combineSourcemaps,\n  extractHostnamesFromCerts,\n  extractHostnamesFromSubjectAltName,\n  flattenId,\n  generateCodeFrame,\n  getHash,\n  getLocalhostAddressIfDiffersFromDNS,\n  getServerUrlByHost,\n  injectQuery,\n  isFileReadable,\n  isParentDirectory,\n  mergeWithDefaults,\n  normalizePath,\n  numberToPos,\n  posToNumber,\n  processSrcSetSync,\n  resolveHostname,\n  resolveServerUrls,\n} from '../utils'\nimport { isWindows } from '../../shared/utils'\nimport type { CommonServerOptions, ResolvedServerUrls } from '..'\n\n// Test certificate for SAN parsing (localhost, foo.localhost, *.vite.localhost)\n// Generate once:\n// openssl req -x509 -nodes -newkey rsa:2048 -days 365 -subj \"/CN=example.org\" \\\n//   -addext \"subjectAltName=DNS:localhost,DNS:foo.localhost,DNS:*.vite.localhost\" \\\n//   -keyout /tmp/test.key -out /tmp/test.crt\n// Paste /tmp/test.crt below.\nconst WORKING_TEST_CERT = `\n-----BEGIN CERTIFICATE-----\nMIID7zCCAtegAwIBAgIJS9D2rIN7tA8mMA0GCSqGSIb3DQEBCwUAMGkxFDASBgNV\nBAMTC2V4YW1wbGUub3JnMQswCQYDVQQGEwJVUzERMA8GA1UECBMIVmlyZ2luaWEx\nEzARBgNVBAcTCkJsYWNrc2J1cmcxDTALBgNVBAoTBFRlc3QxDTALBgNVBAsTBFRl\nc3QwHhcNMjUwMTMwMDQxNTI1WhcNMjUwMzAxMDQxNTI1WjBpMRQwEgYDVQQDEwtl\neGFtcGxlLm9yZzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYD\nVQQHEwpCbGFja3NidXJnMQ0wCwYDVQQKEwRUZXN0MQ0wCwYDVQQLEwRUZXN0MIIB\nIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxNPlCqTmUZ7/F7GyFWDopqZ6\nw19Y7/98B10JEeFGTAQIj/RP2UgZNcTABQDUvtkF7y+bOeoVJW7Zz8ozQYhRaDp8\nCN2gXMcYeTUku/pKLXyCzHHVrOPAXTeU7sMRgLvPCrrJtx5OjvndW+O/PhohPRi3\niEpPvpM8gi7MVRGhnWVSx0/Ynx5c0+/vqyBTzrM2OX7Ufg8Nv7LaTXpCAnmIQp+f\nSqq7HZ7t6Y7laS4RApityvlnFHZ4f2cEibAKv/vXLED7bgAlGb8R1viPRdMtAPuI\nMYvHBgGFjyX1fmq6Mz3aqlAscJILtbQlwty1oYyaENE0lq8+nZXQ+t6I+CIVLQID\nAQABo4GZMIGWMAsGA1UdDwQEAwIC9DAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYB\nBQUHAwIGCCsGAQUFBwMDBggrBgEFBQcDCDBUBgNVHREETTBLgglsb2NhbGhvc3SC\nDWZvby5sb2NhbGhvc3SCECoudml0ZS5sb2NhbGhvc3SCBVs6OjFdhwR/AAABhxD+\ngAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQBi302qLCgxWsUalgc2\nolFxVKob1xCciS8yUVX6HX0vza0WJ7oGW6qZsBbQtfgDwB/dHv7rwsfpjRWvFhmq\ngEUrewa1h0TIC+PPTYYz4M0LOwcLIWZLZr4am1eI7YP9NDgRdhfAfM4hw20vjf2a\nkYLKyRTC5+3/ly5opMq+CGLQ8/gnFxhP3ho8JYrRnqLeh3KCTGen3kmbAhD4IOJ9\nlxMwFPTTWLFFjxbXjXmt5cEiL2mpcq13VCF2HmheCen37CyYIkrwK9IfLhBd5QQh\nWEIBLwjKCAscrtyayXWp6zUTmgvb8PQf//3Mh2DiEngAi3WI/nL+8Y0RkqbvxBar\nX2JN\n-----END CERTIFICATE-----\n`.trim()\n\ndescribe('bareImportRE', () => {\n  test('should work with normal package name', () => {\n    expect(bareImportRE.test('vite')).toBe(true)\n  })\n  test('should work with scoped package name', () => {\n    expect(bareImportRE.test('@vitejs/plugin-vue')).toBe(true)\n  })\n\n  test('should work with absolute paths', () => {\n    expect(bareImportRE.test('/foo')).toBe(false)\n    expect(bareImportRE.test('C:/foo')).toBe(false)\n    expect(bareImportRE.test('C:\\\\foo')).toBe(false)\n  })\n  test('should work with relative path', () => {\n    expect(bareImportRE.test('./foo')).toBe(false)\n    expect(bareImportRE.test('.\\\\foo')).toBe(false)\n  })\n})\n\ndescribe('isParentDirectory', () => {\n  const cases = {\n    '/parent': {\n      '/parent': false,\n      '/parenta': false,\n      '/parent/': true,\n      '/parent/child': true,\n      '/parent/child/child2': true,\n    },\n    '/parent/': {\n      '/parent': false,\n      '/parenta': false,\n      '/parent/': true,\n      '/parent/child': true,\n      '/parent/child/child2': true,\n    },\n  }\n\n  for (const [parent, children] of Object.entries(cases)) {\n    for (const [child, expected] of Object.entries(children)) {\n      test(`isParentDirectory(\"${parent}\", \"${child}\")`, () => {\n        expect(isParentDirectory(parent, child)).toBe(expected)\n      })\n    }\n  }\n})\n\ndescribe('injectQuery', () => {\n  if (isWindows) {\n    // this test will work incorrectly on unix systems\n    test('normalize windows path', () => {\n      expect(injectQuery('C:\\\\User\\\\Vite\\\\Project', 'direct')).toEqual(\n        'C:/User/Vite/Project?direct',\n      )\n    })\n\n    test('absolute file path', () => {\n      expect(injectQuery('C:\\\\test-file.vue', 'direct')).toEqual(\n        'C:/test-file.vue?direct',\n      )\n    })\n\n    test('absolute file path with parameters', () => {\n      expect(\n        injectQuery('C:\\\\test-file.vue?vue&type=template&lang.js', 'direct'),\n      ).toEqual('C:/test-file.vue?direct&vue&type=template&lang.js')\n    })\n  }\n\n  test('relative path', () => {\n    expect(injectQuery('usr/vite/%20a%20', 'direct')).toEqual(\n      'usr/vite/%20a%20?direct',\n    )\n    expect(injectQuery('./usr/vite/%20a%20', 'direct')).toEqual(\n      './usr/vite/%20a%20?direct',\n    )\n    expect(injectQuery('../usr/vite/%20a%20', 'direct')).toEqual(\n      '../usr/vite/%20a%20?direct',\n    )\n  })\n\n  test('path with hash', () => {\n    expect(injectQuery('/usr/vite/path with space/#1?2/', 'direct')).toEqual(\n      '/usr/vite/path with space/?direct#1?2/',\n    )\n  })\n\n  test('path with protocol', () => {\n    expect(injectQuery('file:///usr/vite/%20a%20', 'direct')).toMatch(\n      'file:///usr/vite/%20a%20?direct',\n    )\n    expect(injectQuery('http://usr.vite/%20a%20', 'direct')).toMatch(\n      'http://usr.vite/%20a%20?direct',\n    )\n  })\n\n  test('path with multiple spaces', () => {\n    expect(injectQuery('/usr/vite/path with space', 'direct')).toEqual(\n      '/usr/vite/path with space?direct',\n    )\n  })\n\n  test('path with multiple % characters', () => {\n    expect(injectQuery('/usr/vite/not%20a%20space', 'direct')).toEqual(\n      '/usr/vite/not%20a%20space?direct',\n    )\n  })\n\n  test('path with %25', () => {\n    expect(injectQuery('/usr/vite/%25hello%25', 'direct')).toEqual(\n      '/usr/vite/%25hello%25?direct',\n    )\n  })\n\n  test('path with Unicode', () => {\n    expect(injectQuery('/usr/vite/東京', 'direct')).toEqual(\n      '/usr/vite/東京?direct',\n    )\n  })\n\n  test('path with Unicode, space, and %', () => {\n    expect(injectQuery('/usr/vite/東京 %20 hello', 'direct')).toEqual(\n      '/usr/vite/東京 %20 hello?direct',\n    )\n  })\n\n  test('path with url-encoded path as query parameter', () => {\n    const src = '/src/module.ts?url=https%3A%2F%2Fusr.vite%2F'\n    const expected = '/src/module.ts?t=1234&url=https%3A%2F%2Fusr.vite%2F'\n    expect(injectQuery(src, 't=1234')).toEqual(expected)\n  })\n})\n\ndescribe('resolveHostname', () => {\n  test('defaults to localhost', async () => {\n    const resolved = await getLocalhostAddressIfDiffersFromDNS()\n\n    expect(await resolveHostname(undefined)).toEqual({\n      host: 'localhost',\n      name: resolved ?? 'localhost',\n    })\n  })\n\n  test('accepts localhost', async () => {\n    const resolved = await getLocalhostAddressIfDiffersFromDNS()\n\n    expect(await resolveHostname('localhost')).toEqual({\n      host: 'localhost',\n      name: resolved ?? 'localhost',\n    })\n  })\n\n  test('accepts 0.0.0.0', async () => {\n    expect(await resolveHostname('0.0.0.0')).toEqual({\n      host: '0.0.0.0',\n      name: 'localhost',\n    })\n  })\n\n  test('accepts ::', async () => {\n    expect(await resolveHostname('::')).toEqual({\n      host: '::',\n      name: 'localhost',\n    })\n  })\n\n  test('accepts 0000:0000:0000:0000:0000:0000:0000:0000', async () => {\n    expect(\n      await resolveHostname('0000:0000:0000:0000:0000:0000:0000:0000'),\n    ).toEqual({\n      host: '0000:0000:0000:0000:0000:0000:0000:0000',\n      name: 'localhost',\n    })\n  })\n})\n\ndescribe('extractHostnamesFromSubjectAltName', () => {\n  const testCases = [\n    ['DNS:localhost', ['localhost']],\n    ['DNS:localhost, DNS:foo.localhost', ['localhost', 'foo.localhost']],\n    ['DNS:*.localhost', ['vite.localhost']],\n    ['DNS:[::1]', []], // [::1] is skipped\n    ['DNS:*.192.168.0.152, DNS:192.168.0.152', ['192.168.0.152']], // *.192.168.0.152 is skipped\n    ['othername:\"foo,bar\", DNS:localhost', ['localhost']], // handle quoted correctly\n  ] as const\n\n  for (const [input, expected] of testCases) {\n    test(`should extract names from subjectAltName: ${input}`, () => {\n      expect(extractHostnamesFromSubjectAltName(input)).toStrictEqual(expected)\n    })\n  }\n\n  test('should extract names from actual certificate', () => {\n    const cert = new crypto.X509Certificate(WORKING_TEST_CERT)\n    expect(\n      extractHostnamesFromSubjectAltName(cert.subjectAltName ?? ''),\n    ).toStrictEqual([\n      'localhost',\n      'foo.localhost',\n      'vite.vite.localhost', // *.vite.localhost\n    ])\n  })\n})\n\ndescribe('posToNumber', () => {\n  test('simple', () => {\n    const actual = posToNumber('a\\nb', { line: 2, column: 0 })\n    expect(actual).toBe(2)\n  })\n  test('pass though pos', () => {\n    const actual = posToNumber('a\\nb', 2)\n    expect(actual).toBe(2)\n  })\n  test('empty line', () => {\n    const actual = posToNumber('a\\n\\nb', { line: 3, column: 0 })\n    expect(actual).toBe(3)\n  })\n  test('out of range', () => {\n    const actual = posToNumber('a\\nb', { line: 4, column: 0 })\n    expect(actual).toBe(4)\n  })\n})\n\ndescribe('numberToPos', () => {\n  test('simple', () => {\n    const actual = numberToPos('a\\nb', 2)\n    expect(actual).toEqual({ line: 2, column: 0 })\n  })\n  test('pass though pos', () => {\n    const actual = numberToPos('a\\nb', { line: 2, column: 0 })\n    expect(actual).toEqual({ line: 2, column: 0 })\n  })\n  test('empty line', () => {\n    const actual = numberToPos('a\\n\\nb', 3)\n    expect(actual).toEqual({ line: 3, column: 0 })\n  })\n  test('middle of line', () => {\n    const actual = numberToPos('abc\\ndef', 5)\n    expect(actual).toEqual({ line: 2, column: 1 })\n  })\n  test('end of line', () => {\n    const actual = numberToPos('abc\\ndef', 3)\n    expect(actual).toEqual({ line: 1, column: 3 })\n  })\n  test('out of range', () => {\n    expect(() => numberToPos('a\\nb', 5)).toThrowError(\n      'offset is longer than source length',\n    )\n  })\n})\n\ndescribe('generateCodeFrames', () => {\n  const source = `\nimport foo from './foo'\nfoo()\n`.trim()\n  const sourceCrLf = source.replaceAll('\\n', '\\r\\n')\n  const longSource = `\nimport foo from './foo'\n\nfoo()\n// 1\n// 2\n// 3\n`.trim()\n  const veryLongSource = Array.from({ length: 2000 }, (_, i) => `// ${i}`).join(\n    '\\n',\n  )\n\n  const expectSnapshot = (value: string) => {\n    try {\n      // add new line to make snapshot easier to read\n      expect('\\n' + value + '\\n').toMatchSnapshot()\n    } catch (e) {\n      // don't include this function in stacktrace\n      Error.captureStackTrace(e, expectSnapshot)\n      throw e\n    }\n  }\n\n  test('start with number', () => {\n    expectSnapshot(generateCodeFrame(source, -1))\n    expectSnapshot(generateCodeFrame(source, 0))\n    expectSnapshot(generateCodeFrame(source, 1))\n    expectSnapshot(generateCodeFrame(source, 24))\n  })\n\n  test('start with position', () => {\n    expectSnapshot(generateCodeFrame(source, { line: 1, column: 0 }))\n    expectSnapshot(generateCodeFrame(source, { line: 1, column: 1 }))\n    expectSnapshot(generateCodeFrame(source, { line: 2, column: 0 }))\n  })\n\n  test('works with CRLF', () => {\n    expectSnapshot(generateCodeFrame(sourceCrLf, { line: 2, column: 0 }))\n  })\n\n  test('end', () => {\n    expectSnapshot(generateCodeFrame(source, 0, 0))\n    expectSnapshot(generateCodeFrame(source, 0, 23))\n    expectSnapshot(generateCodeFrame(source, 0, 29))\n    expectSnapshot(generateCodeFrame(source, 0, source.length))\n    expectSnapshot(generateCodeFrame(source, 0, source.length + 1))\n    expectSnapshot(generateCodeFrame(source, 0, source.length + 100))\n  })\n\n  test('range', () => {\n    expectSnapshot(generateCodeFrame(longSource, { line: 3, column: 0 }))\n    expectSnapshot(\n      generateCodeFrame(\n        longSource,\n        { line: 3, column: 0 },\n        { line: 4, column: 0 },\n      ),\n    )\n  })\n\n  test('invalid start > end', () => {\n    expectSnapshot(generateCodeFrame(source, 2, 0))\n  })\n\n  test('supports more than 1000 lines', () => {\n    expectSnapshot(generateCodeFrame(veryLongSource, { line: 1200, column: 0 }))\n  })\n\n  test('long line (start)', () => {\n    const longLine = 'a'.repeat(60) + 'b'.repeat(60) + 'c'.repeat(60)\n    const src = `${longLine}\\nshort line\\n${longLine}`\n    const frame = generateCodeFrame(\n      src,\n      { line: 1, column: 0 },\n      { line: 1, column: 30 },\n    )\n    expectSnapshot(frame)\n  })\n\n  test('long line (center)', () => {\n    const longLine = 'a'.repeat(60) + 'b'.repeat(60) + 'c'.repeat(60)\n    const src = `${longLine}\\nshort line\\n${longLine}`\n    const frame = generateCodeFrame(\n      src,\n      { line: 1, column: 90 },\n      { line: 1, column: 120 },\n    )\n    expectSnapshot(frame)\n  })\n\n  test('long line (end)', () => {\n    const longLine = 'a'.repeat(60) + 'b'.repeat(60) + 'c'.repeat(60)\n    const src = `${longLine}\\nshort line\\n${longLine}`\n    const frame = generateCodeFrame(\n      src,\n      { line: 1, column: 150 },\n      { line: 1, column: 180 },\n    )\n    expectSnapshot(frame)\n  })\n\n  test('long line (whole)', () => {\n    const longLine = 'a'.repeat(60) + 'b'.repeat(60) + 'c'.repeat(60)\n    const src = `${longLine}\\nshort line\\n${longLine}`\n    const frame = generateCodeFrame(\n      src,\n      { line: 1, column: 0 },\n      { line: 1, column: 180 },\n    )\n    expectSnapshot(frame)\n  })\n\n  test('long line (multiline 1)', () => {\n    const longLine = 'a'.repeat(60) + 'b'.repeat(60) + 'c'.repeat(60)\n    const src = `${longLine}\\nshort line\\n${longLine}`\n    const frame = generateCodeFrame(\n      src,\n      { line: 1, column: 170 },\n      { line: 2, column: 5 },\n    )\n    expectSnapshot(frame)\n  })\n\n  test('long line (multiline 2)', () => {\n    const longLine = 'a'.repeat(60) + 'b'.repeat(60) + 'c'.repeat(60)\n    const src = `${longLine}\\nshort line\\n${longLine}`\n    const frame = generateCodeFrame(\n      src,\n      { line: 2, column: 5 },\n      { line: 3, column: 30 },\n    )\n    expectSnapshot(frame)\n  })\n})\n\ndescribe('getHash', () => {\n  test('8-digit hex', () => {\n    const hash = getHash(Buffer.alloc(0))\n    expect(hash).toMatch(/^[\\da-f]{8}$/)\n  })\n})\n\ndescribe('asyncFlatten', () => {\n  test('plain array', async () => {\n    const arr = await asyncFlatten([1, 2, 3])\n    expect(arr).toEqual([1, 2, 3])\n  })\n\n  test('nested array', async () => {\n    const arr = await asyncFlatten([1, 2, 3, [4, 5, 6]])\n    expect(arr).toEqual([1, 2, 3, 4, 5, 6])\n  })\n\n  test('nested falsy array', async () => {\n    const arr = await asyncFlatten([1, 2, false, [4, null, undefined]])\n    expect(arr).toEqual([1, 2, false, 4, null, undefined])\n  })\n\n  test('plain promise array', async () => {\n    const arr = await asyncFlatten([1, 2, Promise.resolve(3)])\n    expect(arr).toEqual([1, 2, 3])\n  })\n\n  test('nested promise array', async () => {\n    const arr = await asyncFlatten([\n      1,\n      2,\n      Promise.resolve(3),\n      Promise.resolve([4, 5, 6]),\n    ])\n    expect(arr).toEqual([1, 2, 3, 4, 5, 6])\n  })\n\n  test('2x nested promise array', async () => {\n    const arr = await asyncFlatten([\n      1,\n      2,\n      Promise.resolve(3),\n      Promise.resolve([4, 5, Promise.resolve(6), Promise.resolve([7, 8, 9])]),\n    ])\n    expect(arr).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9])\n  })\n})\n\ndescribe('isFileReadable', () => {\n  test(\"file doesn't exist\", async () => {\n    expect(isFileReadable('/does_not_exist')).toBe(false)\n  })\n\n  const testFile =\n    require.resolve('./utils/isFileReadable/permission-test-file')\n  test('file with normal permission', async () => {\n    expect(isFileReadable(testFile)).toBe(true)\n  })\n\n  if (process.platform !== 'win32') {\n    test('file with read-only permission', async () => {\n      fs.chmodSync(testFile, '400')\n      expect(isFileReadable(testFile)).toBe(true)\n    })\n    test.runIf(process.getuid && process.getuid() !== 0)(\n      'file without read permission',\n      async () => {\n        fs.chmodSync(testFile, '044')\n        expect(isFileReadable(testFile)).toBe(false)\n        fs.chmodSync(testFile, '644')\n      },\n    )\n  }\n})\n\ndescribe('processSrcSetSync', () => {\n  test('prepend base URL to srcset', async () => {\n    const devBase = '/base/'\n    expect(\n      processSrcSetSync(\n        './nested/asset.png 1x, ./nested/asset.png 2x',\n        ({ url }) => path.posix.join(devBase, url),\n      ),\n    ).toBe('/base/nested/asset.png 1x, /base/nested/asset.png 2x')\n  })\n\n  test('prepend base URL to srcset 2', async () => {\n    const devBase = '/base/'\n    expect(\n      processSrcSetSync(\n        './nested/asset.png 1x,./nested/asset.png 2x',\n        ({ url }) => path.posix.join(devBase, url),\n      ),\n    ).toBe('/base/nested/asset.png 1x, /base/nested/asset.png 2x')\n  })\n\n  test('prepend base URL to srcset 3', async () => {\n    const devBase = '/base/'\n    expect(\n      processSrcSetSync(\n        '\"./nested/asset.png\" 1x,\"./nested/asset.png\" 2x',\n        ({ url }) => `\"${path.posix.join(devBase, url.slice(1, -1))}\"`,\n      ),\n    ).toBe('\"/base/nested/asset.png\" 1x, \"/base/nested/asset.png\" 2x')\n  })\n\n  test('should not split the comma inside base64 value', async () => {\n    const base64 =\n      'data:image/avif;base64,aA+/0= 400w, data:image/avif;base64,bB+/9= 800w'\n    expect(processSrcSetSync(base64, ({ url }) => url)).toBe(base64)\n  })\n\n  test('should not split the comma inside image URI', async () => {\n    const imageURIWithComma =\n      'asset.png?param1=true,param2=false 400w, asset.png?param1=true,param2=false 800w'\n    expect(processSrcSetSync(imageURIWithComma, ({ url }) => url)).toBe(\n      imageURIWithComma,\n    )\n  })\n\n  test('should handle srcset when descriptor is not present', async () => {\n    const srcsetNoDescriptor = 'asset.png, test.png 400w'\n    const result = 'asset.png, test.png 400w'\n    expect(processSrcSetSync(srcsetNoDescriptor, ({ url }) => url)).toBe(result)\n  })\n\n  test('should not break a regular URL in srcSet', async () => {\n    const source = 'https://anydomain/image.jpg'\n    expect(\n      processSrcSetSync('https://anydomain/image.jpg', ({ url }) => url),\n    ).toBe(source)\n  })\n\n  test('should not break URLs with commas in srcSet', async () => {\n    const source = `\n      \\thttps://example.com/dpr_1,f_auto,fl_progressive,q_auto,w_100/v1/img   1x,\n      \\thttps://example.com/dpr_2,f_auto,fl_progressive,q_auto,w_100/v1/img\\t\\t2x\n    `\n    const result =\n      'https://example.com/dpr_1,f_auto,fl_progressive,q_auto,w_100/v1/img 1x, https://example.com/dpr_2,f_auto,fl_progressive,q_auto,w_100/v1/img 2x'\n    expect(processSrcSetSync(source, ({ url }) => url)).toBe(result)\n  })\n\n  test('should not break URLs with commas in image-set-options', async () => {\n    const source = `url(https://example.com/dpr_1,f_auto,fl_progressive,q_auto,w_100/v1/img)   1x,\n      url(\"https://example.com/dpr_2,f_auto,fl_progressive,q_auto,w_100/v1/img\")\\t\\t2x\n    `\n    const result =\n      'url(https://example.com/dpr_1,f_auto,fl_progressive,q_auto,w_100/v1/img) 1x, url(\"https://example.com/dpr_2,f_auto,fl_progressive,q_auto,w_100/v1/img\") 2x'\n    expect(processSrcSetSync(source, ({ url }) => url)).toBe(result)\n  })\n\n  test('should parse image-set-options with resolution', async () => {\n    const source = ` \"foo.png\" 1x,\n                     \"foo-2x.png\" 2x,\n                     \"foo-print.png\" 600dpi`\n    const result = '\"foo.png\" 1x, \"foo-2x.png\" 2x, \"foo-print.png\" 600dpi'\n    expect(processSrcSetSync(source, ({ url }) => url)).toBe(result)\n  })\n\n  test('should parse image-set-options with type', async () => {\n    const source = ` \"foo.avif\" type(\"image/avif\"),\n                     \"foo.jpg\" type(\"image/jpeg\") `\n    const result = '\"foo.avif\" type(\"image/avif\"), \"foo.jpg\" type(\"image/jpeg\")'\n    expect(processSrcSetSync(source, ({ url }) => url)).toBe(result)\n  })\n\n  test('should parse image-set-options with linear-gradient', async () => {\n    const source = `linear-gradient(cornflowerblue, white) 1x,\n                    url(\"detailed-gradient.png\") 3x`\n    const result =\n      'linear-gradient(cornflowerblue, white) 1x, url(\"detailed-gradient.png\") 3x'\n    expect(processSrcSetSync(source, ({ url }) => url)).toBe(result)\n  })\n\n  test('should parse image-set-options with resolution and type specified', async () => {\n    const source = `url(\"picture.png\")\\t1x\\t type(\"image/jpeg\"), url(\"picture.png\")\\t type(\"image/jpeg\")\\t2x`\n    const result =\n      'url(\"picture.png\") 1x type(\"image/jpeg\"), url(\"picture.png\") type(\"image/jpeg\") 2x'\n    expect(processSrcSetSync(source, ({ url }) => url)).toBe(result)\n  })\n\n  test('should capture whole image set options', async () => {\n    const source = `linear-gradient(cornflowerblue, white) 1x,\n                    url(\"detailed-gradient.png\") 3x`\n    const expected = [\n      'linear-gradient(cornflowerblue, white)',\n      'url(\"detailed-gradient.png\")',\n    ]\n    const result: string[] = []\n    processSrcSetSync(source, ({ url }) => {\n      result.push(url)\n      return url\n    })\n    expect(result).toEqual(expected)\n  })\n})\n\ndescribe('flattenId', () => {\n  test('should limit id to 170 characters', () => {\n    const tenChars = '1234567890'\n    let id = ''\n\n    for (let i = 0; i < 17; i++) {\n      id += tenChars\n    }\n    expect(id).toHaveLength(170)\n\n    const result = flattenId(id)\n    expect(result).toHaveLength(170)\n\n    id += tenChars\n    const result2 = flattenId(id)\n    expect(result2).toHaveLength(170)\n  })\n\n  test('should replace + symbols in package subpath exports', () => {\n    // Packages like ravelinjs use + in their subpath exports\n    const id = 'ravelinjs/core+track+encrypt+promise'\n    const result = flattenId(id)\n    expect(result).not.toContain('+')\n    expect(result).toBe('ravelinjs_core_____track_____encrypt_____promise')\n  })\n})\n\ndescribe('mergeWithDefaults', () => {\n  test('merges with defaults', () => {\n    const actual = mergeWithDefaults(\n      {\n        useDefault: 1,\n        useValueIfNull: 2,\n        replaceArray: [0, 1],\n        nested: {\n          foo: 'bar',\n        },\n      },\n      {\n        useDefault: undefined,\n        useValueIfNull: null,\n        useValueIfNoDefault: 'foo',\n        replaceArray: [2, 3],\n        nested: {\n          foo2: 'bar2',\n        },\n      },\n    )\n    expect(actual).toStrictEqual({\n      useDefault: 1,\n      useValueIfNull: null,\n      useValueIfNoDefault: 'foo',\n      replaceArray: [2, 3],\n      nested: {\n        foo: 'bar',\n        foo2: 'bar2',\n      },\n    })\n\n    const defaults = {\n      object: {},\n      array: [],\n      regex: /foo/,\n      function: () => {},\n    }\n    const actual2 = mergeWithDefaults(defaults, {})\n    expect(actual2.object).toStrictEqual({})\n    expect(actual2.array).toStrictEqual([])\n    expect(actual2.regex).toStrictEqual(/foo/)\n    expect(actual2.function).toStrictEqual(expect.any(Function))\n    // cloned\n    expect(actual2.object).not.toBe(defaults.object)\n    expect(actual2.array).not.toBe(defaults.array)\n  })\n})\n\ndescribe('combineSourcemaps', () => {\n  const _dirname = path.dirname(fileURLToPath(import.meta.url))\n  const resolveFile = (file: string) => {\n    return normalizePath(path.resolve(_dirname, file))\n  }\n\n  test('should combine sourcemaps with single sources', () => {\n    const sourcemaps = [\n      // processed with magic-string\n      // https://evanw.github.io/source-map-visualization/#MzQALyogY29tbWVudCAqLwpjb25zb2xlLmxvZygiZm9vIik7CjE1NgB7InZlcnNpb24iOjMsInNvdXJjZXMiOlsiL3NyYy9mb28uanMiXSwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coXCJmb29cIik7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQzsifQo=\n      {\n        version: 3 as const,\n        mappings: ';AAAA,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;',\n        names: [],\n        sources: [resolveFile('./src/foo.js')],\n      },\n      // processed with esbuild\n      // https://evanw.github.io/source-map-visualization/#MjAAY29uc29sZS5sb2coImZvbyIpOwoxNDgAewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiL3NyYy9mb28uanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnNvbGUubG9nKFwiZm9vXCIpIl0sCiAgIm1hcHBpbmdzIjogIkFBQUEsUUFBUSxJQUFJLEtBQUs7IiwKICAibmFtZXMiOiBbXQp9Cg==\n      {\n        version: 3 as const,\n        mappings: 'AAAA,QAAQ,IAAI,KAAK;',\n        names: [],\n        sources: [resolveFile('./src/foo.js')],\n      },\n    ]\n    const combined = combineSourcemaps(resolveFile('./src/foo.js'), sourcemaps)\n    expect(combined).toStrictEqual(\n      expect.objectContaining({\n        version: 3,\n        file: resolveFile('./src/foo.js'),\n        mappings: ';AAAA,QAAQ,IAAI,KAAK',\n        sources: [resolveFile('./src/foo.js')],\n      }),\n    )\n  })\n\n  test('should combine sourcemaps with multiple sources', () => {\n    const sourcemaps = [\n      // processed with magic-string\n      // https://evanw.github.io/source-map-visualization/#NzcALyogY29tbWVudCAqLwovLyBiLmpzCmNvbnNvbGUubG9nKCIuL2IuanMiKTsKCi8vIGEuanMKY29uc29sZS5sb2coIi4vYS5qcyIpOwozMzkAeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9hLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIGIuanNcbmNvbnNvbGUubG9nKFwiLi9iLmpzXCIpO1xuXG4vLyBhLmpzXG5jb25zb2xlLmxvZyhcIi4vYS5qc1wiKTtcblxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7T0FDRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7O0FBRXJCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztPQUNFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQzs7In0K\n      {\n        version: 3 as const,\n        mappings:\n          ';AAAA,CAAC,CAAC,CAAC,CAAC,CAAC;OACE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;;AAErB,CAAC,CAAC,CAAC,CAAC,CAAC;OACE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;;',\n        names: [],\n        sources: [resolveFile('./src/a.js')],\n      },\n      // processed with esbuild\n      // https://evanw.github.io/source-map-visualization/#NjMALy8gYi5qcwpjb25zb2xlLmxvZygiLi9iLmpzIik7CgovLyBhLmpzCmNvbnNvbGUubG9nKCIuL2EuanMiKTsKMjIwAHsKICAidmVyc2lvbiI6IDMsCiAgInNvdXJjZXMiOiBbImIuanMiLCAiYS5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiY29uc29sZS5sb2coJy4vYi5qcycpXG4iLCAiaW1wb3J0ICcuL2IuanMnXG5jb25zb2xlLmxvZygnLi9hLmpzJylcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBQSxRQUFRLElBQUksUUFBUTs7O0FDQ3BCLFFBQVEsSUFBSSxRQUFROyIsCiAgIm5hbWVzIjogW10KfQo=\n      {\n        version: 3 as const,\n        mappings: ';AAAA,QAAQ,IAAI,QAAQ;;;ACCpB,QAAQ,IAAI,QAAQ;',\n        names: [],\n        sources: [resolveFile('./src/b.js'), resolveFile('./src/a.js')],\n      },\n    ]\n    const combined = combineSourcemaps(resolveFile('./src/a.js'), sourcemaps)\n    expect(combined).toStrictEqual(\n      expect.objectContaining({\n        version: 3,\n        file: resolveFile('./src/a.js'),\n        mappings: ';;OAAA,CAAQ,IAAI,QAAQ;;;OCCpB,CAAQ,IAAI,QAAQ',\n        sources: [resolveFile('./src/b.js'), resolveFile('./src/a.js')],\n      }),\n    )\n  })\n\n  test('should combine sourcemaps with multiple sources 2', () => {\n    const sourcemaps = [\n      // processed with sass\n      // https://evanw.github.io/source-map-visualization/#NTYALmltcG9ydGVkMiB7CiAgY29sb3I6IHJlZAp9CgouaW1wb3J0ZWQgewogIGNvbG9yOiByZWQKfQoyNzAAewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsKICAgICIvaW1wb3J0ZWQyLnNhc3MiLAogICAgIi9Gb28udnVlIgogIF0sCiAgIm5hbWVzIjogW10sCiAgIm1hcHBpbmdzIjogIkFBQUE7RUFDRTs7O0FDRUY7RUFDRSIsCiAgImZpbGUiOiAiL0Zvby52dWUiLAogICJzb3VyY2VzQ29udGVudCI6IFsKICAgICIuaW1wb3J0ZWQyXG4gIGNvbG9yOiByZWRcbiIsCiAgICAiXG5AdXNlICcuL2ltcG9ydGVkMidcblxuLmltcG9ydGVkXG4gIGNvbG9yOiByZWRcbiIKICBdCn0K\n      {\n        version: 3 as const,\n        file: resolveFile('./src/Foo.vue'),\n        mappings: 'AAAA;EACE;;;ACEF;EACE',\n        names: [],\n        sources: [\n          resolveFile('./src/imported2.sass'),\n          resolveFile('./src/Foo.vue'),\n        ],\n      },\n      // processed with vue\n      // https://evanw.github.io/source-map-visualization/#NDQACkB1c2UgJy4vaW1wb3J0ZWQyJwoKLmltcG9ydGVkCiAgY29sb3I6IHJlZAo0OTQAewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsKICAgICIvRm9vLnZ1ZSIKICBdLAogICJuYW1lcyI6IFtdLAogICJtYXBwaW5ncyI6ICI7QUFNQSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOztBQUVqQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7RUFDTixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMiLAogICJmaWxlIjogIi9Gb28udnVlIiwKICAic291cmNlc0NvbnRlbnQiOiBbCiAgICAiPHRlbXBsYXRlPlxuICA8cCBjbGFzcz1cImltcG9ydGVkXCI+Zm9vPC9wPlxuICA8cCBjbGFzcz1cImltcG9ydGVkMlwiPmJhcjwvcD5cbjwvdGVtcGxhdGU+XG5cbjxzdHlsZSBsYW5nPVwic2Fzc1wiPlxuQHVzZSAnLi9pbXBvcnRlZDInXG5cbi5pbXBvcnRlZFxuICBjb2xvcjogcmVkXG48L3N0eWxlPlxuIgogIF0KfQo=\n      {\n        version: 3 as const,\n        file: resolveFile('./src/Foo.vue'),\n        sources: [resolveFile('./src/Foo.vue')],\n        names: [],\n        mappings:\n          ';AAMA,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;;AAEjB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;EACN,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC',\n      },\n    ]\n    const combined = combineSourcemaps(resolveFile('./src/Foo.vue'), sourcemaps)\n    expect(combined).toStrictEqual(\n      expect.objectContaining({\n        version: 3,\n        file: resolveFile('./src/Foo.vue'),\n        mappings: 'AAAA;EACE;;;ACOF;EACE',\n        sources: [\n          resolveFile('./src/imported2.sass'),\n          resolveFile('./src/Foo.vue'),\n        ],\n      }),\n    )\n  })\n\n  test('should combine sourcemaps with multiple sources without matched source', () => {\n    const sourcemaps = [\n      // processed with postcss\n      // https://evanw.github.io/source-map-visualization/#NjYALmZvbyB7CiAgb3ZlcmZsb3c6IHNjcm9sbDsKICAtd2Via2l0LW92ZXJmbG93LXNjcm9sbGluZzogdG91Y2g7Cn0KMjU1AHsKICAiZmlsZSI6ICIvc3JjL3Nhc3Mvc3R5bGUuc2FzcyIsCiAgIm1hcHBpbmdzIjogIkFBQUE7RUFDRSxnQkFBZ0I7RUNEbEIsa0NBQUE7QURFQSIsCiAgIm5hbWVzIjogW10sCiAgInNvdXJjZXMiOiBbCiAgICAiL3NyYy9zYXNzL3N0eWxlLnNhc3MiLAogICAgIlx1MDAwMDxubyBzb3VyY2U+IgogIF0sCiAgInNvdXJjZXNDb250ZW50IjogWyAiLmZvbyB7XG4gIG92ZXJmbG93OiBzY3JvbGw7XG59IiwgbnVsbCBdLAogICJ2ZXJzaW9uIjogMwp9Cg==\n      {\n        version: 3 as const,\n        file: resolveFile('./src/sass/style.sass'),\n        mappings: 'AAAA;EACE,gBAAgB;ECDlB,kCAAA;ADEA',\n        names: [],\n        sources: [\n          resolveFile('./src/sass/style.sass'),\n          '\\x00<no source>', // postcss virtual file\n        ],\n      },\n      // processed with sass\n      // https://evanw.github.io/source-map-visualization/#MjkALmZvbyB7CiAgb3ZlcmZsb3c6IHNjcm9sbDsKfQoyMDcAewogICJmaWxlIjogIi9zcmMvc2Fzcy9zdHlsZS5zYXNzIiwKICAibWFwcGluZ3MiOiAiQUFBQTtFQUNFIiwKICAibmFtZXMiOiBbXSwKICAic291cmNlcyI6IFsKICAgICIvc3JjL3Nhc3MvdmVuZG9yL2luZGV4LnNjc3MiCiAgXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi5mb28ge1xuICBvdmVyZmxvdzogc2Nyb2xsO1xufVxuIl0sCiAgInZlcnNpb24iOiAzCn0K\n      {\n        version: 3 as const,\n        sources: [resolveFile('./src/sass/vendor/index.scss')],\n        names: [],\n        mappings: 'AAAA;EACE',\n      },\n    ]\n    const combined = combineSourcemaps(\n      resolveFile('./src/sass/style.sass'),\n      sourcemaps,\n    )\n    expect(combined).toStrictEqual(\n      expect.objectContaining({\n        version: 3,\n        file: resolveFile('./src/sass/style.sass'),\n        mappings: 'AAAA;EACE;ECDF',\n        sources: [\n          resolveFile('./src/sass/vendor/index.scss'),\n          '\\x00<no source>',\n        ],\n      }),\n    )\n  })\n})\n\ndescribe('getServerUrlByHost', () => {\n  const urls: ResolvedServerUrls = {\n    local: ['http://localhost:5173'],\n    network: ['http://foo.example.com:5173'],\n  }\n  const cases = [\n    {\n      name: 'when host is undefined',\n      urls,\n      host: undefined,\n      expected: 'http://localhost:5173',\n    },\n    {\n      name: 'when host is true',\n      urls,\n      host: true,\n      expected: 'http://localhost:5173',\n    },\n    {\n      name: 'when host is explicit string',\n      urls,\n      host: 'foo.example.com',\n      expected: 'http://foo.example.com:5173',\n    },\n    {\n      name: 'when host is 0.0.0.0',\n      urls,\n      host: '0.0.0.0',\n      expected: 'http://localhost:5173',\n    },\n    {\n      name: 'when host is ::1',\n      urls,\n      host: '::1',\n      expected: 'http://localhost:5173',\n    },\n  ] satisfies ReadonlyArray<{\n    name: string\n    urls: ResolvedServerUrls\n    host: CommonServerOptions['host']\n    expected: string | undefined\n  }>\n\n  for (const { name, urls, host, expected } of cases) {\n    test(name, () => {\n      const actual = getServerUrlByHost(urls, host)\n      expect(actual).toBe(expected)\n    })\n  }\n})\n\ndescribe('extractHostnamesFromCerts', () => {\n  test('should extract hostnames from certificate', () => {\n    const certs = [WORKING_TEST_CERT]\n    const result = extractHostnamesFromCerts(certs)\n    expect(result).toStrictEqual([\n      'localhost',\n      'foo.localhost',\n      'vite.vite.localhost',\n    ])\n  })\n\n  test('should extract hostnames from multiple certificates', () => {\n    const certs = [WORKING_TEST_CERT, WORKING_TEST_CERT]\n    const result = extractHostnamesFromCerts(certs)\n    expect(result).toStrictEqual([\n      'localhost',\n      'foo.localhost',\n      'vite.vite.localhost',\n    ])\n  })\n})\n\ndescribe('resolveServerUrls', () => {\n  const createMockServer = (\n    family: 'IPv4' | 'IPv6' = 'IPv4',\n    address: string = '127.0.0.1',\n  ) =>\n    ({\n      address: () => ({ port: 3000, address, family }),\n    }) as any\n\n  const createTestConfig = () => ({\n    options: { https: true } as any,\n    hostname: { host: '127.0.0.1', name: 'localhost' } as any,\n    config: { rawBase: '/' } as any,\n  })\n\n  test('should handle no certificate', () => {\n    const mockServer = createMockServer()\n    const { options, hostname, config } = createTestConfig()\n    const httpsOptions = {}\n\n    const result = resolveServerUrls(\n      mockServer,\n      options,\n      hostname,\n      httpsOptions,\n      config,\n    )\n\n    expect(result.local).toContain('https://localhost:3000/')\n  })\n\n  test('should handle IPv4 single certificate', () => {\n    const mockServer = createMockServer()\n    const { options, hostname, config } = createTestConfig()\n    const httpsOptions = { cert: [WORKING_TEST_CERT] }\n\n    const result = resolveServerUrls(\n      mockServer,\n      options,\n      hostname,\n      httpsOptions,\n      config,\n    )\n\n    expect(result.local).toContain('https://localhost:3000/')\n    expect(result.local).toContain('https://foo.localhost:3000/')\n    expect(result.local).toContain('https://vite.vite.localhost:3000/')\n  })\n\n  test('should handle IPv4 multiple certificates', () => {\n    const mockServer = createMockServer()\n    const { options, hostname, config } = createTestConfig()\n    const httpsOptions = { cert: [WORKING_TEST_CERT, WORKING_TEST_CERT] }\n\n    const result = resolveServerUrls(\n      mockServer,\n      options,\n      hostname,\n      httpsOptions,\n      config,\n    )\n\n    expect(result.local).toContain('https://localhost:3000/')\n    expect(result.local).toContain('https://foo.localhost:3000/')\n    expect(result.local).toContain('https://vite.vite.localhost:3000/')\n  })\n\n  test('should handle IPv6 single certificate', () => {\n    const mockServer = createMockServer('IPv6', '::1')\n    const { options, hostname, config } = createTestConfig()\n    const httpsOptions = { cert: [WORKING_TEST_CERT] }\n\n    const result = resolveServerUrls(\n      mockServer,\n      options,\n      hostname,\n      httpsOptions,\n      config,\n    )\n\n    expect(result.local).toContain('https://localhost:3000/')\n    expect(result.local).toContain('https://foo.localhost:3000/')\n    expect(result.local).toContain('https://vite.vite.localhost:3000/')\n  })\n\n  test('should handle IPv6 multiple certificates', () => {\n    const mockServer = createMockServer('IPv6', '::1')\n    const { options, hostname, config } = createTestConfig()\n    const httpsOptions = { cert: [WORKING_TEST_CERT, WORKING_TEST_CERT] }\n\n    const result = resolveServerUrls(\n      mockServer,\n      options,\n      hostname,\n      httpsOptions,\n      config,\n    )\n\n    expect(result.local).toContain('https://localhost:3000/')\n    expect(result.local).toContain('https://foo.localhost:3000/')\n    expect(result.local).toContain('https://vite.vite.localhost:3000/')\n  })\n\n  test('should handle invalid certificate', () => {\n    const mockServer = createMockServer()\n    const { options, hostname, config } = createTestConfig()\n    const httpsOptions = { cert: ['invalid-cert'] }\n\n    const result = resolveServerUrls(\n      mockServer,\n      options,\n      hostname,\n      httpsOptions,\n      config,\n    )\n\n    expect(result.local).toContain('https://localhost:3000/')\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/__tests_dts__/config.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type { Equal, ExpectTrue } from '@type-challenges/utils'\nimport {\n  type UserConfig,\n  type UserConfigExport,\n  type UserConfigFn,\n  type UserConfigFnObject,\n  type UserConfigFnPromise,\n  defineConfig,\n} from '../config'\nimport { mergeConfig } from '../utils'\n\nconst configObjectDefined = defineConfig({})\nconst configObjectPromiseDefined = defineConfig(Promise.resolve({}))\nconst configFnObjectDefined = defineConfig(() => ({}))\nconst configFnPromiseDefined = defineConfig(async () => ({}))\nconst configFnDefined = defineConfig(() =>\n  // TypeScript requires both non-promise config and\n  // promise config to have at least one property\n  Math.random() > 0.5 ? { base: '' } : Promise.resolve({ base: '/' }),\n)\nconst configExportDefined = defineConfig({} as UserConfigExport)\n\nexport type cases1 = [\n  ExpectTrue<Equal<typeof configObjectDefined, UserConfig>>,\n  ExpectTrue<Equal<typeof configObjectPromiseDefined, Promise<UserConfig>>>,\n  ExpectTrue<Equal<typeof configFnObjectDefined, UserConfigFnObject>>,\n  ExpectTrue<Equal<typeof configFnPromiseDefined, UserConfigFnPromise>>,\n  ExpectTrue<Equal<typeof configFnDefined, UserConfigFn>>,\n  ExpectTrue<Equal<typeof configExportDefined, UserConfigExport>>,\n]\n\ndefineConfig({\n  base: '',\n  build: {\n    minify: 'oxc', // `as const` is not needed\n  },\n  server: {\n    proxy: {\n      '/test': {\n        bypass: () => false,\n      },\n    },\n  },\n  // @ts-expect-error --- invalid option should error\n  unknownProperty: 1,\n})\n\ndefineConfig(() => ({\n  base: '',\n  build: {\n    minify: 'oxc' as const, // ideally we don't want to require `as const` here\n  },\n  server: {\n    proxy: {\n      '/test': {\n        bypass: () => false as const, // ideally we don't want to require `as const` here\n      },\n    },\n  },\n  unknownProperty: 1, // we cannot catch invalid option for this case, ideally we should\n}))\n\n// @ts-expect-error --- nested invalid option `build.unknown` should error\ndefineConfig(() => ({\n  base: '',\n  build: {\n    unknown: 1,\n  },\n}))\n\ndefineConfig(async () => ({\n  base: '',\n  build: {\n    minify: 'oxc' as const, // ideally we don't want to require `as const` here\n  },\n  server: {\n    proxy: {\n      '/test': {\n        bypass: () => false as const, // ideally we don't want to require `as const` here\n      },\n    },\n  },\n  unknownProperty: 1, // we cannot catch invalid option for this case, ideally we should\n}))\n\n// @ts-expect-error --- nested invalid option `build.unknown` should error\ndefineConfig(async () => ({\n  base: '',\n  build: {\n    unknown: 1,\n  },\n}))\n\nmergeConfig(defineConfig({}), defineConfig({}))\nmergeConfig(\n  // @ts-expect-error\n  defineConfig(() => ({})),\n  defineConfig({}),\n)\n\nexport {}\n"
  },
  {
    "path": "packages/vite/src/node/__tests_dts__/plugin.ts",
    "content": "/**\n * This is a development only file for testing types.\n */\nimport type { Plugin as RolldownPlugin } from 'rolldown'\nimport type { Equal, ExpectExtends, ExpectTrue } from '@type-challenges/utils'\nimport type { Plugin as RollupPlugin } from 'rollup'\nimport type { Plugin, PluginContextExtension, PluginOption } from '../plugin'\nimport type { ROLLUP_HOOKS } from '../constants'\nimport type {\n  GetHookContextMap,\n  NonNeverKeys,\n  RollupPluginHooks,\n} from '../typeUtils'\n\ntype EnvironmentPluginHooksContext = GetHookContextMap<Plugin>\ntype EnvironmentPluginHooksContextMatched = {\n  [K in keyof EnvironmentPluginHooksContext]: EnvironmentPluginHooksContext[K] extends PluginContextExtension\n    ? never\n    : false\n}\n\ntype HooksMissingExtension = NonNeverKeys<EnvironmentPluginHooksContextMatched>\ntype HooksMissingInConstants = Exclude<\n  RollupPluginHooks,\n  (typeof ROLLUP_HOOKS)[number]\n>\n\nexport type cases = [\n  // Ensure environment plugin hooks are superset of rollup plugin hooks\n  ExpectTrue<ExpectExtends<RolldownPlugin, Plugin>>,\n\n  // Ensure all Rollup hooks have Vite's plugin context extension\n  ExpectTrue<Equal<HooksMissingExtension, never>>,\n\n  // Ensure the `ROLLUP_HOOKS` constant is up-to-date\n  ExpectTrue<Equal<HooksMissingInConstants, never>>,\n\n  // Ensure all Vite plugins, Rolldown plugins, and Rollup plugins can be assigned to `plugins` option\n  ExpectTrue<ExpectExtends<PluginOption, RolldownPlugin>>,\n  ExpectTrue<ExpectExtends<PluginOption, RollupPlugin>>,\n  ExpectTrue<ExpectExtends<PluginOption, Plugin>>,\n]\n\nexport {}\n"
  },
  {
    "path": "packages/vite/src/node/__tests_dts__/tsconfig.json",
    "content": "{\n  \"extends\": \"../../../tsconfig.base.json\",\n  \"compilerOptions\": {\n    \"isolatedDeclarations\": false,\n    \"declaration\": false\n  },\n  \"include\": [\"../\", \"../../types\"],\n  \"exclude\": [\"../**/__tests__\"]\n}\n"
  },
  {
    "path": "packages/vite/src/node/__tests_dts__/typeOptions.ts",
    "content": "// This file tests `ViteTypeOptions` in `packages/vite/types/importMeta.d.ts`\nimport type { ExpectFalse, ExpectTrue } from '@type-challenges/utils'\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ninterface TypeOptions1 {}\ninterface TypeOptions2 {\n  strictImportMetaEnv: unknown\n}\ninterface TypeOptions3 {\n  unknownKey: unknown\n}\n\ntype IsEnabled<Opts, Key extends string> = Key extends keyof Opts ? true : false\n\nexport type cases = [\n  ExpectFalse<IsEnabled<TypeOptions1, 'strictImportMetaEnv'>>,\n  ExpectTrue<IsEnabled<TypeOptions2, 'strictImportMetaEnv'>>,\n  ExpectFalse<IsEnabled<TypeOptions3, 'strictImportMetaEnv'>>,\n]\n\nexport {}\n"
  },
  {
    "path": "packages/vite/src/node/__tests_dts__/utils.ts",
    "content": "/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type { Equal, ExpectTrue } from '@type-challenges/utils'\nimport { mergeWithDefaults } from '../utils'\n\nconst useDefaultTypeForUndefined1 = mergeWithDefaults(\n  {\n    foo: 1,\n  },\n  {},\n)\n\nconst useDefaultTypeForUndefined2 = mergeWithDefaults(\n  {\n    foo: 1,\n  },\n  {\n    foo: 2 as number | undefined,\n  },\n)\n\nconst includeKeyNotIncludedInDefault1 = mergeWithDefaults(\n  {},\n  {\n    foo: 2,\n  },\n)\n\nconst extendTypeWithValueType = mergeWithDefaults(\n  {\n    foo: 1,\n  },\n  {\n    foo: 'string' as string | number,\n  },\n)\n\nconst plainObject = mergeWithDefaults({ foo: { bar: 1 } }, { foo: { baz: 2 } })\n\nconst nonPlainObject = mergeWithDefaults(\n  { foo: ['foo'] },\n  { foo: [0] as number[] | undefined },\n)\n\nconst optionalNested = mergeWithDefaults({ foo: { bar: true } }, {\n  foo: { bar: false },\n} as { foo?: { bar?: boolean } })\n\nexport type cases1 = [\n  ExpectTrue<Equal<typeof useDefaultTypeForUndefined1, { foo: number }>>,\n  ExpectTrue<Equal<typeof useDefaultTypeForUndefined2, { foo: number }>>,\n  ExpectTrue<Equal<typeof includeKeyNotIncludedInDefault1, { foo: number }>>,\n  ExpectTrue<Equal<typeof extendTypeWithValueType, { foo: string | number }>>,\n  ExpectTrue<Equal<typeof plainObject, { foo: { bar: number; baz: number } }>>,\n  ExpectTrue<Equal<typeof nonPlainObject, { foo: string[] | number[] }>>,\n  ExpectTrue<\n    Equal<typeof optionalNested, { foo: { bar: boolean } | { bar: boolean } }>\n  >,\n]\n"
  },
  {
    "path": "packages/vite/src/node/assetSource.ts",
    "content": "import type { DefaultTreeAdapterMap, Token } from 'parse5'\n\ninterface HtmlAssetSource {\n  srcAttributes?: string[]\n  srcsetAttributes?: string[]\n  /**\n   * Called before handling an attribute to determine if it should be processed.\n   */\n  filter?: (data: HtmlAssetSourceFilterData) => boolean\n}\n\ninterface HtmlAssetSourceFilterData {\n  key: string\n  value: string\n  attributes: Record<string, string>\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name\n// https://wiki.whatwg.org/wiki/MetaExtensions\nconst ALLOWED_META_NAME = [\n  'msapplication-tileimage',\n  'msapplication-square70x70logo',\n  'msapplication-square150x150logo',\n  'msapplication-wide310x150logo',\n  'msapplication-square310x310logo',\n  'msapplication-config',\n  'twitter:image',\n]\n\n// https://ogp.me\nconst ALLOWED_META_PROPERTY = [\n  'og:image',\n  'og:image:url',\n  'og:image:secure_url',\n  'og:audio',\n  'og:audio:secure_url',\n  'og:video',\n  'og:video:secure_url',\n]\n\nconst DEFAULT_HTML_ASSET_SOURCES: Record<string, HtmlAssetSource> = {\n  audio: {\n    srcAttributes: ['src'],\n  },\n  embed: {\n    srcAttributes: ['src'],\n  },\n  img: {\n    srcAttributes: ['src'],\n    srcsetAttributes: ['srcset'],\n  },\n  image: {\n    srcAttributes: ['href', 'xlink:href'],\n  },\n  input: {\n    srcAttributes: ['src'],\n  },\n  link: {\n    srcAttributes: ['href'],\n    srcsetAttributes: ['imagesrcset'],\n  },\n  object: {\n    srcAttributes: ['data'],\n  },\n  source: {\n    srcAttributes: ['src'],\n    srcsetAttributes: ['srcset'],\n  },\n  track: {\n    srcAttributes: ['src'],\n  },\n  use: {\n    srcAttributes: ['href', 'xlink:href'],\n  },\n  video: {\n    srcAttributes: ['src', 'poster'],\n  },\n  meta: {\n    srcAttributes: ['content'],\n    filter({ attributes }) {\n      if (\n        attributes.name &&\n        ALLOWED_META_NAME.includes(attributes.name.trim().toLowerCase())\n      ) {\n        return true\n      }\n\n      if (\n        attributes.property &&\n        ALLOWED_META_PROPERTY.includes(attributes.property.trim().toLowerCase())\n      ) {\n        return true\n      }\n\n      return false\n    },\n  },\n}\n\ninterface HtmlAssetAttribute {\n  type: 'src' | 'srcset' | 'remove'\n  key: string\n  value: string\n  attributes: Record<string, string>\n  location: Token.Location\n}\n\n/**\n * Given a HTML node, find all attributes that references an asset to be processed\n */\nexport function getNodeAssetAttributes(\n  node: DefaultTreeAdapterMap['element'],\n): HtmlAssetAttribute[] {\n  const matched = DEFAULT_HTML_ASSET_SOURCES[node.nodeName]\n  if (!matched) return []\n\n  const attributes: Record<string, string> = {}\n  for (const attr of node.attrs) {\n    attributes[getAttrKey(attr)] = attr.value\n  }\n\n  // If the node has a `vite-ignore` attribute, remove the attribute and early out\n  // to skip processing any attributes\n  if ('vite-ignore' in attributes) {\n    return [\n      {\n        type: 'remove',\n        key: 'vite-ignore',\n        value: '',\n        attributes,\n        location: node.sourceCodeLocation!.attrs!['vite-ignore'],\n      },\n    ]\n  }\n\n  const actions: HtmlAssetAttribute[] = []\n  function handleAttributeKey(key: string, type: 'src' | 'srcset') {\n    const value = attributes[key]\n    if (!value) return\n    if (matched.filter && !matched.filter({ key, value, attributes })) return\n    const location = node.sourceCodeLocation!.attrs![key]\n    actions.push({ type, key, value, attributes, location })\n  }\n  matched.srcAttributes?.forEach((key) => handleAttributeKey(key, 'src'))\n  matched.srcsetAttributes?.forEach((key) => handleAttributeKey(key, 'srcset'))\n  return actions\n}\n\nfunction getAttrKey(attr: Token.Attribute): string {\n  return attr.prefix === undefined ? attr.name : `${attr.prefix}:${attr.name}`\n}\n"
  },
  {
    "path": "packages/vite/src/node/baseEnvironment.ts",
    "content": "import colors from 'picocolors'\nimport type { Logger } from './logger'\nimport type { ResolvedConfig, ResolvedEnvironmentOptions } from './config'\nimport type { Plugin } from './plugin'\n\nconst environmentColors = [\n  colors.blue,\n  colors.magenta,\n  colors.green,\n  colors.gray,\n]\n\nexport class PartialEnvironment {\n  name: string\n  getTopLevelConfig(): ResolvedConfig {\n    return this._topLevelConfig\n  }\n\n  config: ResolvedConfig & ResolvedEnvironmentOptions\n\n  logger: Logger\n\n  /**\n   * @internal\n   */\n  _options: ResolvedEnvironmentOptions\n  /**\n   * @internal\n   */\n  _topLevelConfig: ResolvedConfig\n\n  constructor(\n    name: string,\n    topLevelConfig: ResolvedConfig,\n    options: ResolvedEnvironmentOptions = topLevelConfig.environments[name],\n  ) {\n    // only allow some characters so that we can use name without escaping for directory names\n    // and make users easier to access with `environments.*`\n    if (!/^[\\w$]+$/.test(name)) {\n      throw new Error(\n        `Invalid environment name \"${name}\". Environment names must only contain alphanumeric characters and \"$\", \"_\".`,\n      )\n    }\n    this.name = name\n    this._topLevelConfig = topLevelConfig\n    this._options = options\n    this.config = new Proxy(\n      options as ResolvedConfig & ResolvedEnvironmentOptions,\n      {\n        get: (target, prop: keyof ResolvedConfig) => {\n          if (prop === 'logger') {\n            return this.logger\n          }\n          if (prop in target) {\n            return this._options[prop as keyof ResolvedEnvironmentOptions]\n          }\n          return this._topLevelConfig[prop]\n        },\n      },\n    )\n    const environment = colors.dim(`(${this.name})`)\n    const colorIndex =\n      [...this.name].reduce((acc, c) => acc + c.charCodeAt(0), 0) %\n      environmentColors.length\n    const infoColor = environmentColors[colorIndex || 0]\n    this.logger = {\n      get hasWarned() {\n        return topLevelConfig.logger.hasWarned\n      },\n      info(msg, opts) {\n        return topLevelConfig.logger.info(msg, {\n          ...opts,\n          environment: infoColor(environment),\n        })\n      },\n      warn(msg, opts) {\n        return topLevelConfig.logger.warn(msg, {\n          ...opts,\n          environment: colors.yellow(environment),\n        })\n      },\n      warnOnce(msg, opts) {\n        return topLevelConfig.logger.warnOnce(msg, {\n          ...opts,\n          environment: colors.yellow(environment),\n        })\n      },\n      error(msg, opts) {\n        return topLevelConfig.logger.error(msg, {\n          ...opts,\n          environment: colors.red(environment),\n        })\n      },\n      clearScreen(type) {\n        return topLevelConfig.logger.clearScreen(type)\n      },\n      hasErrorLogged(error) {\n        return topLevelConfig.logger.hasErrorLogged(error)\n      },\n    }\n  }\n}\n\nexport class BaseEnvironment extends PartialEnvironment {\n  get plugins(): readonly Plugin[] {\n    return this.config.plugins\n  }\n\n  /**\n   * @internal\n   */\n  _initiated: boolean = false\n\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    options: ResolvedEnvironmentOptions = config.environments[name],\n  ) {\n    super(name, config, options)\n  }\n}\n\n/**\n * This class discourages users from inversely checking the `mode`\n * to determine the type of environment, e.g.\n *\n * ```js\n * const isDev = environment.mode !== 'build' // bad\n * const isDev = environment.mode === 'dev'   // good\n * ```\n *\n * You should also not check against `\"unknown\"` specifically. It's\n * a placeholder for more possible environment types.\n */\nexport class UnknownEnvironment extends BaseEnvironment {\n  mode = 'unknown' as const\n}\n"
  },
  {
    "path": "packages/vite/src/node/build.ts",
    "content": "import path from 'node:path'\nimport colors from 'picocolors'\nimport type {\n  ExternalOption,\n  InputOption,\n  InternalModuleFormat,\n  LogLevel,\n  LogOrStringHandler,\n  MinimalPluginContext,\n  ModuleFormat,\n  OutputAsset,\n  OutputBundle,\n  OutputChunk,\n  OutputOptions,\n  PluginContext,\n  RenderedChunk,\n  RolldownBuild,\n  RolldownOptions,\n  RolldownOutput,\n  RolldownWatcher,\n  RollupError,\n  RollupLog,\n  WarningHandlerWithDefault,\n  WatcherOptions,\n} from 'rolldown'\nimport { viteLoadFallbackPlugin as nativeLoadFallbackPlugin } from 'rolldown/experimental'\nimport type { EsbuildTarget } from '#types/internal/esbuildOptions'\nimport type { RollupCommonJSOptions } from '#dep-types/commonjs'\nimport type { RollupDynamicImportVarsOptions } from '#dep-types/dynamicImportVars'\nimport type { AssetMetadata, ChunkMetadata } from '#types/metadata'\nimport {\n  DEFAULT_ASSETS_INLINE_LIMIT,\n  ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET,\n  ROLLUP_HOOKS,\n  VERSION,\n} from './constants'\nimport type {\n  EnvironmentOptions,\n  InlineConfig,\n  ResolvedConfig,\n  ResolvedEnvironmentOptions,\n} from './config'\nimport { resolveConfig } from './config'\nimport type { PartialEnvironment } from './baseEnvironment'\nimport { buildReporterPlugin } from './plugins/reporter'\nimport { buildEsbuildPlugin } from './plugins/esbuild'\nimport { type TerserOptions, terserPlugin } from './plugins/terser'\nimport {\n  arraify,\n  asyncFlatten,\n  createDebugger,\n  displayTime,\n  getPkgName,\n  joinUrlSegments,\n  mergeConfig,\n  mergeWithDefaults,\n  partialEncodeURIPath,\n  setupRollupOptionCompat,\n  unique,\n} from './utils'\nimport { perEnvironmentPlugin } from './plugin'\nimport { manifestPlugin } from './plugins/manifest'\nimport { type Logger } from './logger'\nimport { buildImportAnalysisPlugin } from './plugins/importAnalysisBuild'\nimport { ssrManifestPlugin } from './ssr/ssrManifestPlugin'\nimport { findNearestMainPackageData, findNearestPackageData } from './packages'\nimport type { PackageCache } from './packages'\nimport {\n  convertToWatcherOptions,\n  getResolvedOutDirs,\n  resolveChokidarOptions,\n  resolveEmptyOutDir,\n} from './watch'\nimport { webWorkerPostPlugin } from './plugins/worker'\nimport { getHookHandler } from './plugins'\nimport { BaseEnvironment } from './baseEnvironment'\nimport type { MinimalPluginContextWithoutEnvironment, Plugin } from './plugin'\nimport type { RollupPluginHooks } from './typeUtils'\nimport { type LicenseOptions, licensePlugin } from './plugins/license'\nimport {\n  BasicMinimalPluginContext,\n  basePluginContextMeta,\n} from './server/pluginContainer'\nimport {\n  isFutureDeprecationEnabled,\n  warnFutureDeprecation,\n} from './deprecations'\nimport { prepareOutDirPlugin } from './plugins/prepareOutDir'\nimport type { Environment } from './environment'\n\nexport interface BuildEnvironmentOptions {\n  /**\n   * Compatibility transform target. The transform is performed with esbuild\n   * and the lowest supported target is es2015. Note this only handles\n   * syntax transformation and does not cover polyfills\n   *\n   * Default: 'baseline-widely-available' - transpile targeting browsers that\n   * are included in the Baseline Widely Available on 2026-01-01.\n   * (Chrome 111+, Edge 111+, Firefox 114+, Safari 16.4+).\n   *\n   * Another special value is 'esnext' - which only performs minimal transpiling\n   * (for minification compat).\n   *\n   * For custom targets, see https://esbuild.github.io/api/#target and\n   * https://esbuild.github.io/content-types/#javascript for more details.\n   * @default 'baseline-widely-available'\n   */\n  target?: 'baseline-widely-available' | EsbuildTarget | false\n  /**\n   * whether to inject module preload polyfill.\n   * Note: does not apply to library mode.\n   * @default true\n   * @deprecated use `modulePreload.polyfill` instead\n   */\n  polyfillModulePreload?: boolean\n  /**\n   * Configure module preload\n   * Note: does not apply to library mode.\n   * @default true\n   */\n  modulePreload?: boolean | ModulePreloadOptions\n  /**\n   * Directory relative from `root` where build output will be placed. If the\n   * directory exists, it will be removed before the build.\n   * @default 'dist'\n   */\n  outDir?: string\n  /**\n   * Directory relative from `outDir` where the built js/css/image assets will\n   * be placed.\n   * @default 'assets'\n   */\n  assetsDir?: string\n  /**\n   * Static asset files smaller than this number (in bytes) will be inlined as\n   * base64 strings. If a callback is passed, a boolean can be returned to opt-in\n   * or opt-out of inlining. If nothing is returned the default logic applies.\n   *\n   * Default limit is `4096` (4 KiB). Set to `0` to disable.\n   * @default 4096\n   */\n  assetsInlineLimit?:\n    | number\n    | ((filePath: string, content: Buffer) => boolean | undefined)\n  /**\n   * Whether to code-split CSS. When enabled, CSS in async chunks will be\n   * inlined as strings in the chunk and inserted via dynamically created\n   * style tags when the chunk is loaded.\n   * @default true\n   */\n  cssCodeSplit?: boolean\n  /**\n   * An optional separate target for CSS minification.\n   * As esbuild only supports configuring targets to mainstream\n   * browsers, users may need this option when they are targeting\n   * a niche browser that comes with most modern JavaScript features\n   * but has poor CSS support, e.g. Android WeChat WebView, which\n   * doesn't support the #RGBA syntax.\n   * @default target\n   */\n  cssTarget?: EsbuildTarget | false\n  /**\n   * Override CSS minification specifically instead of defaulting to `build.minify`,\n   * so you can configure minification for JS and CSS separately.\n   * @default 'lightningcss'\n   */\n  cssMinify?: boolean | 'lightningcss' | 'esbuild'\n  /**\n   * If `true`, a separate sourcemap file will be created. If 'inline', the\n   * sourcemap will be appended to the resulting output file as data URI.\n   * 'hidden' works like `true` except that the corresponding sourcemap\n   * comments in the bundled files are suppressed.\n   * @default false\n   */\n  sourcemap?: boolean | 'inline' | 'hidden'\n  /**\n   * Set to `false` to disable minification, or specify the minifier to use.\n   * Available options are 'oxc' or 'terser' or 'esbuild'.\n   * @default 'oxc'\n   */\n  minify?: boolean | 'oxc' | 'terser' | 'esbuild'\n  /**\n   * Options for terser\n   * https://terser.org/docs/api-reference#minify-options\n   *\n   * In addition, you can also pass a `maxWorkers: number` option to specify the\n   * max number of workers to spawn. Defaults to the number of CPUs minus 1.\n   */\n  terserOptions?: TerserOptions\n  /**\n   * Alias to `rolldownOptions`\n   * @deprecated Use `rolldownOptions` instead.\n   */\n  rollupOptions?: RolldownOptions\n  /**\n   * Will be merged with internal rolldown options.\n   * https://rolldown.rs/reference/config-options\n   */\n  rolldownOptions?: RolldownOptions\n  /**\n   * Options to pass on to `@rollup/plugin-commonjs`\n   * @deprecated This option is no-op and will be removed in future versions.\n   */\n  commonjsOptions?: RollupCommonJSOptions\n  /**\n   * Options to pass on to `@rollup/plugin-dynamic-import-vars`\n   */\n  dynamicImportVarsOptions?: RollupDynamicImportVarsOptions\n  /**\n   * Whether to write bundle to disk\n   * @default true\n   */\n  write?: boolean\n  /**\n   * Empty outDir on write.\n   * @default true when outDir is a sub directory of project root\n   */\n  emptyOutDir?: boolean | null\n  /**\n   * Copy the public directory to outDir on write.\n   * @default true\n   */\n  copyPublicDir?: boolean\n  /**\n   * Whether to emit a `.vite/license.md` file that includes all bundled dependencies'\n   * licenses. Pass an object to customize the output file name.\n   * @default false\n   */\n  license?: boolean | LicenseOptions\n  /**\n   * Whether to emit a .vite/manifest.json in the output dir to map hash-less filenames\n   * to their hashed versions. Useful when you want to generate your own HTML\n   * instead of using the one generated by Vite.\n   *\n   * Example:\n   *\n   * ```json\n   * {\n   *   \"main.js\": {\n   *     \"file\": \"main.68fe3fad.js\",\n   *     \"css\": \"main.e6b63442.css\",\n   *     \"imports\": [...],\n   *     \"dynamicImports\": [...]\n   *   }\n   * }\n   * ```\n   * @default false\n   */\n  manifest?: boolean | string\n  /**\n   * Build in library mode. The value should be the global name of the lib in\n   * UMD mode. This will produce esm + cjs + umd bundle formats with default\n   * configurations that are suitable for distributing libraries.\n   * @default false\n   */\n  lib?: LibraryOptions | false\n  /**\n   * Produce SSR oriented build. Note this requires specifying SSR entry via\n   * `rollupOptions.input`.\n   * @default false\n   */\n  ssr?: boolean | string\n  /**\n   * Generate SSR manifest for determining style links and asset preload\n   * directives in production.\n   * @default false\n   */\n  ssrManifest?: boolean | string\n  /**\n   * Emit assets during SSR.\n   * @default false\n   */\n  ssrEmitAssets?: boolean\n  /**\n   * Emit assets during build. Frameworks can set environments.ssr.build.emitAssets\n   * By default, it is true for the client and false for other environments.\n   */\n  emitAssets?: boolean\n  /**\n   * Set to false to disable reporting compressed chunk sizes.\n   * Can slightly improve build speed.\n   * @default true\n   */\n  reportCompressedSize?: boolean\n  /**\n   * Adjust chunk size warning limit (in kB).\n   * @default 500\n   */\n  chunkSizeWarningLimit?: number\n  /**\n   * Rollup watch options\n   * https://rollupjs.org/configuration-options/#watch\n   * @default null\n   */\n  watch?: WatcherOptions | null\n  /**\n   * create the Build Environment instance\n   */\n  createEnvironment?: (\n    name: string,\n    config: ResolvedConfig,\n  ) => Promise<BuildEnvironment> | BuildEnvironment\n}\n\nexport type BuildOptions = BuildEnvironmentOptions\n\nexport interface LibraryOptions {\n  /**\n   * Path of library entry\n   */\n  entry: InputOption\n  /**\n   * The name of the exposed global variable. Required when the `formats` option includes\n   * `umd` or `iife`\n   */\n  name?: string\n  /**\n   * Output bundle formats\n   * @default ['es', 'umd']\n   */\n  formats?: LibraryFormats[]\n  /**\n   * The name of the package file output. The default file name is the name option\n   * of the project package.json. It can also be defined as a function taking the\n   * format as an argument.\n   */\n  fileName?: string | ((format: ModuleFormat, entryName: string) => string)\n  /**\n   * The name of the CSS file output if the library imports CSS. Defaults to the\n   * same value as `build.lib.fileName` if it's set a string, otherwise it falls\n   * back to the name option of the project package.json.\n   */\n  cssFileName?: string\n}\n\nexport type LibraryFormats = 'es' | 'cjs' | 'umd' | 'iife' // | 'system'\n\nexport interface ModulePreloadOptions {\n  /**\n   * Whether to inject a module preload polyfill.\n   * Note: does not apply to library mode.\n   * @default true\n   */\n  polyfill?: boolean\n  /**\n   * Resolve the list of dependencies to preload for a given dynamic import\n   * @experimental\n   */\n  resolveDependencies?: ResolveModulePreloadDependenciesFn\n}\nexport interface ResolvedModulePreloadOptions {\n  polyfill: boolean\n  resolveDependencies?: ResolveModulePreloadDependenciesFn\n}\n\nexport type ResolveModulePreloadDependenciesFn = (\n  filename: string,\n  deps: string[],\n  context: {\n    hostId: string\n    hostType: 'html' | 'js'\n  },\n) => string[]\n\nexport interface ResolvedBuildEnvironmentOptions extends Required<\n  Omit<BuildEnvironmentOptions, 'polyfillModulePreload'>\n> {\n  modulePreload: false | ResolvedModulePreloadOptions\n}\n\nexport interface ResolvedBuildOptions extends Required<\n  Omit<BuildOptions, 'polyfillModulePreload'>\n> {\n  modulePreload: false | ResolvedModulePreloadOptions\n}\n\nconst _buildEnvironmentOptionsDefaults = Object.freeze({\n  target: 'baseline-widely-available',\n  /** @deprecated */\n  polyfillModulePreload: true,\n  modulePreload: true,\n  outDir: 'dist',\n  assetsDir: 'assets',\n  assetsInlineLimit: DEFAULT_ASSETS_INLINE_LIMIT,\n  // cssCodeSplit\n  // cssTarget\n  // cssMinify\n  sourcemap: false,\n  // minify\n  terserOptions: {},\n  rolldownOptions: {},\n  commonjsOptions: {\n    include: [/node_modules/],\n    extensions: ['.js', '.cjs'],\n  },\n  dynamicImportVarsOptions: {\n    exclude: [/node_modules/],\n  },\n  write: true,\n  emptyOutDir: null,\n  copyPublicDir: true,\n  license: false,\n  manifest: false,\n  lib: false,\n  // ssr\n  ssrManifest: false,\n  ssrEmitAssets: false,\n  // emitAssets\n  reportCompressedSize: true,\n  chunkSizeWarningLimit: 500,\n  watch: null,\n  // createEnvironment\n} satisfies BuildEnvironmentOptions)\nexport const buildEnvironmentOptionsDefaults: Readonly<\n  Partial<BuildEnvironmentOptions>\n> = _buildEnvironmentOptionsDefaults\n\nexport function resolveBuildEnvironmentOptions(\n  raw: BuildEnvironmentOptions,\n  logger: Logger,\n  consumer: 'client' | 'server' | undefined,\n  isBundledDev: boolean,\n): ResolvedBuildEnvironmentOptions {\n  const deprecatedPolyfillModulePreload = raw.polyfillModulePreload\n  const { polyfillModulePreload, ...rest } = raw\n  raw = rest\n  if (deprecatedPolyfillModulePreload !== undefined) {\n    logger.warn(\n      'polyfillModulePreload is deprecated. Use modulePreload.polyfill instead.',\n    )\n  }\n  if (\n    deprecatedPolyfillModulePreload === false &&\n    raw.modulePreload === undefined\n  ) {\n    raw.modulePreload = { polyfill: false }\n  }\n\n  const merged = mergeWithDefaults(\n    {\n      ..._buildEnvironmentOptionsDefaults,\n      cssCodeSplit: !raw.lib,\n      minify: consumer === 'server' || isBundledDev ? false : 'oxc',\n      rollupOptions: {},\n      rolldownOptions: undefined,\n      ssr: consumer === 'server',\n      emitAssets: consumer === 'client',\n      createEnvironment: (name, config) => new BuildEnvironment(name, config),\n    } satisfies BuildEnvironmentOptions,\n    raw,\n  )\n  setupRollupOptionCompat(merged, 'build')\n  merged.rolldownOptions = {\n    platform: consumer === 'server' ? 'node' : 'browser',\n    ...merged.rolldownOptions,\n  }\n\n  // handle special build targets\n  if (merged.target === 'baseline-widely-available') {\n    merged.target = ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET\n  }\n  // dedupe target\n  if (Array.isArray(merged.target)) {\n    // esbuild allowed duplicate targets but oxc does not\n    merged.target = unique(merged.target)\n  }\n\n  // normalize false string into actual false\n  if ((merged.minify as string) === 'false') {\n    merged.minify = false\n  } else if (merged.minify === true) {\n    merged.minify = 'oxc'\n  }\n\n  const defaultModulePreload = {\n    polyfill: true,\n  }\n\n  const resolved: ResolvedBuildEnvironmentOptions = {\n    ...merged,\n    cssTarget: merged.cssTarget ?? merged.target,\n    cssMinify:\n      merged.cssMinify ??\n      (consumer === 'server' ? 'lightningcss' : !!merged.minify),\n    // Resolve to false | object\n    modulePreload:\n      merged.modulePreload === false\n        ? false\n        : merged.modulePreload === true\n          ? defaultModulePreload\n          : {\n              ...defaultModulePreload,\n              ...merged.modulePreload,\n            },\n  }\n\n  return resolved\n}\n\nexport async function resolveBuildPlugins(config: ResolvedConfig): Promise<{\n  pre: Plugin[]\n  post: Plugin[]\n}> {\n  const isBuild = config.command === 'build'\n  return {\n    pre: [\n      ...(isBuild && !config.isWorker ? [prepareOutDirPlugin()] : []),\n      perEnvironmentPlugin(\n        'vite:rollup-options-plugins',\n        async (environment) =>\n          (\n            await asyncFlatten(\n              arraify(environment.config.build.rollupOptions.plugins),\n            )\n          ).filter(Boolean) as Plugin[],\n      ),\n      ...(config.isWorker ? [webWorkerPostPlugin(config)] : []),\n    ],\n    post: [\n      ...(isBuild ? buildImportAnalysisPlugin(config) : []),\n      ...(config.build.minify === 'esbuild' ? [buildEsbuildPlugin()] : []),\n      ...(isBuild ? [terserPlugin(config)] : []),\n      ...(isBuild && !config.isWorker\n        ? [\n            licensePlugin(),\n            manifestPlugin(),\n            ssrManifestPlugin(),\n            buildReporterPlugin(config),\n          ]\n        : []),\n      nativeLoadFallbackPlugin(),\n    ],\n  }\n}\n\n/**\n * Bundles a single environment for production.\n * Returns a Promise containing the build result.\n */\nexport async function build(\n  inlineConfig: InlineConfig = {},\n): Promise<RolldownOutput | RolldownOutput[] | RolldownWatcher> {\n  const builder = await createBuilder(inlineConfig, true)\n  const environment = Object.values(builder.environments)[0]\n  if (!environment) throw new Error('No environment found')\n  return builder.build(environment)\n}\n\nfunction resolveConfigToBuild(\n  inlineConfig: InlineConfig = {},\n  patchConfig?: (config: ResolvedConfig) => void,\n  patchPlugins?: (resolvedPlugins: Plugin[]) => void,\n): Promise<ResolvedConfig> {\n  return resolveConfig(\n    inlineConfig,\n    'build',\n    'production',\n    'production',\n    false,\n    patchConfig,\n    patchPlugins,\n  )\n}\n\nexport function resolveRolldownOptions(\n  environment: Environment,\n  chunkMetadataMap: ChunkMetadataMap,\n): RolldownOptions {\n  const { root, packageCache, build: options } = environment.config\n  const libOptions = options.lib\n  const { logger } = environment\n  const ssr = environment.config.consumer === 'server'\n\n  const resolve = (p: string) => path.resolve(root, p)\n  const input = libOptions\n    ? options.rollupOptions.input ||\n      (typeof libOptions.entry === 'string'\n        ? resolve(libOptions.entry)\n        : Array.isArray(libOptions.entry)\n          ? libOptions.entry.map(resolve)\n          : Object.fromEntries(\n              Object.entries(libOptions.entry).map(([alias, file]) => [\n                alias,\n                resolve(file),\n              ]),\n            ))\n    : typeof options.ssr === 'string'\n      ? resolve(options.ssr)\n      : options.rollupOptions.input || resolve('index.html')\n\n  if (ssr && typeof input === 'string' && input.endsWith('.html')) {\n    throw new Error(\n      `rollupOptions.input should not be an html file when building for SSR. ` +\n        `Please specify a dedicated SSR entry.`,\n    )\n  }\n  if (options.cssCodeSplit === false) {\n    const inputs =\n      typeof input === 'string'\n        ? [input]\n        : Array.isArray(input)\n          ? input\n          : Object.values(input)\n    if (inputs.some((input) => input.endsWith('.css'))) {\n      throw new Error(\n        `When \"build.cssCodeSplit: false\" is set, \"rollupOptions.input\" should not include CSS files.`,\n      )\n    }\n  }\n\n  const outDir = resolve(options.outDir)\n\n  // inject environment and ssr arg to plugin load/transform hooks\n  const plugins = environment.plugins.map((p) =>\n    injectEnvironmentToHooks(environment, chunkMetadataMap, p),\n  )\n\n  const rollupOptions: RolldownOptions = {\n    preserveEntrySignatures: ssr\n      ? 'allow-extension'\n      : libOptions\n        ? 'strict'\n        : false,\n    // cache: options.watch ? undefined : false,\n    ...options.rollupOptions,\n    output: options.rollupOptions.output,\n    input,\n    plugins,\n    external: options.rollupOptions.external,\n    onLog(level, log) {\n      onRollupLog(level, log, environment)\n    },\n    transform: {\n      target: options.target === false ? undefined : options.target,\n      ...options.rollupOptions.transform,\n      define: {\n        ...options.rollupOptions.transform?.define,\n        // disable builtin process.env.NODE_ENV replacement as it is handled by the define plugin\n        'process.env.NODE_ENV': 'process.env.NODE_ENV',\n      },\n    },\n    // TODO: remove this and enable rolldown's CSS support later\n    moduleTypes: {\n      ...options.rollupOptions.moduleTypes,\n      '.css': 'js',\n    },\n    experimental: {\n      ...options.rollupOptions.experimental,\n      viteMode: true,\n    },\n  }\n\n  const isSsrTargetWebworkerEnvironment =\n    environment.name === 'ssr' &&\n    environment.getTopLevelConfig().ssr?.target === 'webworker'\n\n  const buildOutputOptions = (output: OutputOptions = {}): OutputOptions => {\n    // @ts-expect-error See https://github.com/vitejs/vite/issues/5812#issuecomment-984345618\n    if (output.output) {\n      logger.warn(\n        `You've set \"rollupOptions.output.output\" in your config. ` +\n          `This is deprecated and will override all Vite.js default output options. ` +\n          `Please use \"rollupOptions.output\" instead.`,\n      )\n    }\n    if (output.file) {\n      throw new Error(\n        `Vite does not support \"rollupOptions.output.file\". ` +\n          `Please use \"rollupOptions.output.dir\" and \"rollupOptions.output.entryFileNames\" instead.`,\n      )\n    }\n    if (output.sourcemap) {\n      logger.warnOnce(\n        colors.yellow(\n          `Vite does not support \"rollupOptions.output.sourcemap\". ` +\n            `Please use \"build.sourcemap\" instead.`,\n        ),\n      )\n    }\n\n    const format = output.format || 'es'\n    const jsExt =\n      (ssr && !isSsrTargetWebworkerEnvironment) || libOptions\n        ? resolveOutputJsExtension(\n            format,\n            findNearestPackageData(root, packageCache)?.data.type,\n          )\n        : 'js'\n    return {\n      dir: outDir,\n      // Default format is 'es' for regular and for SSR builds\n      format,\n      exports: 'auto',\n      sourcemap: options.sourcemap,\n      name: libOptions ? libOptions.name : undefined,\n      // hoistTransitiveImports: libOptions ? false : undefined,\n      // es2015 enables `generatedCode.symbols`\n      // - #764 add `Symbol.toStringTag` when build es module into cjs chunk\n      // - #1048 add `Symbol.toStringTag` for module default export\n      generatedCode: {\n        preset: 'es2015',\n      },\n      entryFileNames: ssr\n        ? `[name].${jsExt}`\n        : libOptions\n          ? ({ name }) =>\n              resolveLibFilename(\n                libOptions,\n                format,\n                name,\n                root,\n                jsExt,\n                packageCache,\n              )\n          : path.posix.join(options.assetsDir, `[name]-[hash].${jsExt}`),\n      chunkFileNames: libOptions\n        ? `[name]-[hash].${jsExt}`\n        : path.posix.join(options.assetsDir, `[name]-[hash].${jsExt}`),\n      assetFileNames: libOptions\n        ? `[name].[ext]`\n        : path.posix.join(options.assetsDir, `[name]-[hash].[ext]`),\n      codeSplitting:\n        output.codeSplitting ??\n        (output.format === 'umd' ||\n        output.format === 'iife' ||\n        (isSsrTargetWebworkerEnvironment &&\n          (typeof input === 'string' || Object.keys(input).length === 1))\n          ? false\n          : undefined),\n      comments:\n        typeof output.comments === 'boolean'\n          ? output.comments\n          : {\n              // Do not minify whitespace for ES lib output since that would remove\n              // pure annotations and break tree-shaking\n              annotation:\n                !options.minify ||\n                (libOptions && (format === 'es' || format === 'esm')),\n              jsdoc: !options.minify,\n              legal: !options.minify,\n              ...output.comments,\n            },\n      minify:\n        options.minify === 'oxc'\n          ? libOptions && (format === 'es' || format === 'esm')\n            ? {\n                compress: true,\n                mangle: true,\n                // Do not minify whitespace for ES lib output since that would remove\n                // pure annotations and break tree-shaking\n                codegen: false,\n              }\n            : true\n          : options.minify === false\n            ? 'dce-only'\n            : false,\n      topLevelVar: true,\n      ...output,\n    }\n  }\n\n  // resolve lib mode outputs\n  const outputs = resolveBuildOutputs(\n    options.rollupOptions.output,\n    libOptions,\n    logger,\n  )\n\n  if (Array.isArray(outputs)) {\n    rollupOptions.output = outputs.map(buildOutputOptions)\n  } else {\n    rollupOptions.output = buildOutputOptions(outputs)\n  }\n\n  return rollupOptions\n}\n\n/**\n * Build an App environment, or a App library (if libraryOptions is provided)\n **/\nasync function buildEnvironment(\n  environment: BuildEnvironment,\n): Promise<RolldownOutput | RolldownOutput[] | RolldownWatcher> {\n  const { logger, config } = environment\n  const { root, build: options } = config\n\n  logger.info(\n    colors.cyan(\n      `vite v${VERSION} ${colors.green(\n        `building ${environment.name} environment for ${environment.config.mode}...`,\n      )}`,\n    ),\n  )\n\n  let bundle: RolldownBuild | undefined\n  let startTime: number | undefined\n  try {\n    const chunkMetadataMap = new ChunkMetadataMap()\n    const rollupOptions = resolveRolldownOptions(environment, chunkMetadataMap)\n\n    // watch file changes with rollup\n    if (options.watch) {\n      logger.info(colors.cyan(`\\nwatching for file changes...`))\n\n      const resolvedOutDirs = getResolvedOutDirs(\n        root,\n        options.outDir,\n        options.rollupOptions.output,\n      )\n      const emptyOutDir = resolveEmptyOutDir(\n        options.emptyOutDir,\n        root,\n        resolvedOutDirs,\n        logger,\n      )\n      const resolvedChokidarOptions = resolveChokidarOptions(\n        {\n          // @ts-expect-error chokidar option does not exist in rolldown but used for backward compat\n          ...(rollupOptions.watch || {}).chokidar,\n          // @ts-expect-error chokidar option does not exist in rolldown but used for backward compat\n          ...options.watch.chokidar,\n        },\n        resolvedOutDirs,\n        emptyOutDir,\n        environment.config.cacheDir,\n      )\n\n      const { watch } = await import('rolldown')\n      const watcher = watch({\n        ...rollupOptions,\n        watch: {\n          ...rollupOptions.watch,\n          ...options.watch,\n          watcher: convertToWatcherOptions(resolvedChokidarOptions),\n        },\n      })\n\n      watcher.on('event', (event) => {\n        if (event.code === 'BUNDLE_START') {\n          logger.info(colors.cyan(`\\nbuild started...`))\n          chunkMetadataMap.clearResetChunks()\n        } else if (event.code === 'BUNDLE_END') {\n          event.result.close()\n          logger.info(colors.cyan(`built in ${event.duration}ms.`))\n        } else if (event.code === 'ERROR') {\n          const e = event.error\n          enhanceRollupError(e)\n          clearLine()\n          logger.error(e.message, { error: e })\n        }\n      })\n\n      return watcher\n    }\n\n    // write or generate files with rolldown\n    const { rolldown } = await import('rolldown')\n    startTime = Date.now()\n    bundle = await rolldown(rollupOptions)\n\n    const res: RolldownOutput[] = []\n    for (const output of arraify(rollupOptions.output!)) {\n      res.push(await bundle[options.write ? 'write' : 'generate'](output))\n    }\n    for (const output of res) {\n      for (const chunk of output.output) {\n        injectChunkMetadata(chunkMetadataMap, chunk)\n      }\n    }\n    logger.info(\n      `${colors.green(`✓ built in ${displayTime(Date.now() - startTime)}`)}`,\n    )\n    return Array.isArray(rollupOptions.output) ? res : res[0]\n  } catch (e) {\n    enhanceRollupError(e)\n    clearLine()\n    if (startTime) {\n      logger.error(\n        `${colors.red('✗')} Build failed in ${displayTime(Date.now() - startTime)}`,\n      )\n      startTime = undefined\n    }\n    throw e\n  } finally {\n    if (bundle) await bundle.close()\n  }\n}\n\nexport function enhanceRollupError(e: RollupError): void {\n  const stackOnly = extractStack(e)\n\n  let msg = colors.red((e.plugin ? `[${e.plugin}] ` : '') + e.message)\n  if (e.loc && e.loc.file && e.loc.file !== e.id) {\n    msg += `\\nfile: ${colors.cyan(\n      `${e.loc.file}:${e.loc.line}:${e.loc.column}` +\n        (e.id ? ` (${e.id})` : ''),\n    )}`\n  } else if (e.id) {\n    msg += `\\nfile: ${colors.cyan(\n      e.id + (e.loc ? `:${e.loc.line}:${e.loc.column}` : ''),\n    )}`\n  }\n  if (e.frame) {\n    msg += `\\n` + colors.yellow(normalizeCodeFrame(e.frame))\n  }\n\n  e.message = msg\n\n  // We are rebuilding the stack trace to include the more detailed message at the top.\n  // Previously this code was relying on mutating e.message changing the generated stack\n  // when it was accessed, but we don't have any guarantees that the error we are working\n  // with hasn't already had its stack accessed before we get here.\n  if (stackOnly !== undefined) {\n    e.stack = `${e.message}\\n${stackOnly}`\n  }\n}\n\n/**\n * The stack string usually contains a copy of the message at the start of the stack.\n * If the stack starts with the message, we remove it and just return the stack trace\n * portion. Otherwise the original stack trace is used.\n */\nfunction extractStack(e: RollupError) {\n  const { stack, name = 'Error', message } = e\n\n  // If we don't have a stack, not much we can do.\n  if (!stack) {\n    return stack\n  }\n\n  const expectedPrefix = `${name}: ${message}\\n`\n  if (stack.startsWith(expectedPrefix)) {\n    return stack.slice(expectedPrefix.length)\n  }\n\n  return stack\n}\n\n/**\n * Esbuild code frames have newlines at the start and end of the frame, rollup doesn't\n * This function normalizes the frame to match the esbuild format which has more pleasing padding\n */\nfunction normalizeCodeFrame(frame: string) {\n  const trimmedPadding = frame.replace(/^\\n|\\n$/g, '')\n  return `\\n${trimmedPadding}\\n`\n}\n\ntype JsExt = 'js' | 'cjs' | 'mjs'\n\nfunction resolveOutputJsExtension(\n  format: ModuleFormat,\n  type: string = 'commonjs',\n): JsExt {\n  if (type === 'module') {\n    return format === 'cjs' || format === 'umd' ? 'cjs' : 'js'\n  } else {\n    return format === 'es' ? 'mjs' : 'js'\n  }\n}\n\nexport function resolveLibFilename(\n  libOptions: LibraryOptions,\n  format: ModuleFormat,\n  entryName: string,\n  root: string,\n  extension?: JsExt,\n  packageCache?: PackageCache,\n): string {\n  if (typeof libOptions.fileName === 'function') {\n    return libOptions.fileName(format, entryName)\n  }\n\n  const packageJson = findNearestMainPackageData(root, packageCache)?.data\n  const name =\n    libOptions.fileName ||\n    (packageJson && typeof libOptions.entry === 'string'\n      ? getPkgName(packageJson.name)\n      : entryName)\n\n  if (!name)\n    throw new Error(\n      'Name in package.json is required if option \"build.lib.fileName\" is not provided.',\n    )\n\n  extension ??= resolveOutputJsExtension(format, packageJson?.type)\n\n  if (format === 'cjs' || format === 'es') {\n    return `${name}.${extension}`\n  }\n\n  return `${name}.${format}.${extension}`\n}\n\nexport function resolveBuildOutputs(\n  outputs: OutputOptions | OutputOptions[] | undefined,\n  libOptions: LibraryOptions | false,\n  logger: Logger,\n): OutputOptions | OutputOptions[] | undefined {\n  if (libOptions) {\n    const libHasMultipleEntries =\n      typeof libOptions.entry !== 'string' &&\n      Object.values(libOptions.entry).length > 1\n    const libFormats =\n      libOptions.formats ||\n      (libHasMultipleEntries ? ['es', 'cjs'] : ['es', 'umd'])\n\n    if (!Array.isArray(outputs)) {\n      if (libFormats.includes('umd') || libFormats.includes('iife')) {\n        if (libHasMultipleEntries) {\n          throw new Error(\n            'Multiple entry points are not supported when output formats include \"umd\" or \"iife\".',\n          )\n        }\n\n        if (!libOptions.name) {\n          throw new Error(\n            'Option \"build.lib.name\" is required when output formats include \"umd\" or \"iife\".',\n          )\n        }\n      }\n\n      return libFormats.map((format) => ({ ...outputs, format }))\n    }\n\n    // By this point, we know \"outputs\" is an Array.\n    if (libOptions.formats) {\n      logger.warn(\n        colors.yellow(\n          '\"build.lib.formats\" will be ignored because \"build.rollupOptions.output\" is already an array format.',\n        ),\n      )\n    }\n\n    outputs.forEach((output) => {\n      if (\n        (output.format === 'umd' || output.format === 'iife') &&\n        !output.name\n      ) {\n        throw new Error(\n          'Entries in \"build.rollupOptions.output\" must specify \"name\" when the format is \"umd\" or \"iife\".',\n        )\n      }\n    })\n  }\n\n  return outputs\n}\n\nconst warningIgnoreList = [`CIRCULAR_DEPENDENCY`, `THIS_IS_UNDEFINED`]\nconst dynamicImportWarningIgnoreList = [\n  `Unsupported expression`,\n  `statically analyzed`,\n]\n\nexport function clearLine(): void {\n  const tty = process.stdout.isTTY && !process.env.CI\n  if (tty) {\n    process.stdout.clearLine(0)\n    process.stdout.cursorTo(0)\n  }\n}\n\nexport function onRollupLog(\n  level: LogLevel,\n  log: RollupLog,\n  environment: Environment,\n): void {\n  const debugLogger = createDebugger('vite:build')\n  const viteLog: LogOrStringHandler = (logLeveling, rawLogging) => {\n    const logging =\n      typeof rawLogging === 'object' ? rawLogging : { message: rawLogging }\n\n    if (logging.code === 'UNRESOLVED_IMPORT') {\n      const id = logging.id\n      const exporter = logging.exporter\n      // throw unless it's commonjs external...\n      if (!id || !id.endsWith('?commonjs-external')) {\n        throw new Error(\n          `[vite]: Rolldown failed to resolve import \"${exporter}\" from \"${id}\".\\n` +\n            `This is most likely unintended because it can break your application at runtime.\\n` +\n            `If you do want to externalize this module explicitly add it to\\n` +\n            `\\`build.rollupOptions.external\\``,\n        )\n      }\n    }\n\n    if (logLeveling === 'warn') {\n      if (\n        logging.plugin === 'rollup-plugin-dynamic-import-variables' &&\n        dynamicImportWarningIgnoreList.some((msg) =>\n          logging.message.includes(msg),\n        )\n      ) {\n        return\n      }\n\n      if (warningIgnoreList.includes(logging.code!)) {\n        return\n      }\n    }\n\n    // append plugin name to align with Rollup's behavior\n    let message = logging.message\n    if (logging.plugin) {\n      message = `[plugin ${logging.plugin}] ${message}`\n    }\n\n    switch (logLeveling) {\n      case 'info':\n        environment.logger.info(message)\n        return\n      case 'warn':\n        environment.logger.warn(colors.yellow(message))\n        return\n      case 'error':\n        environment.logger.error(colors.red(message))\n        return\n      case 'debug':\n        debugLogger?.(message)\n        return\n      default:\n        logLeveling satisfies never\n        // fallback to info if a unknown log level is passed\n        environment.logger.info(message)\n        return\n    }\n  }\n\n  clearLine()\n  const userOnLog = environment.config.build.rollupOptions?.onLog\n  const userOnWarn = environment.config.build.rollupOptions?.onwarn\n  if (userOnLog) {\n    if (userOnWarn) {\n      const normalizedUserOnWarn = normalizeUserOnWarn(userOnWarn, viteLog)\n      userOnLog(level, log, normalizedUserOnWarn)\n    } else {\n      userOnLog(level, log, viteLog)\n    }\n  } else if (userOnWarn) {\n    const normalizedUserOnWarn = normalizeUserOnWarn(userOnWarn, viteLog)\n    normalizedUserOnWarn(level, log)\n  } else {\n    viteLog(level, log)\n  }\n}\n\nfunction normalizeUserOnWarn(\n  userOnWarn: WarningHandlerWithDefault,\n  defaultHandler: LogOrStringHandler,\n): LogOrStringHandler {\n  return (logLevel, logging) => {\n    if (logLevel === 'warn') {\n      userOnWarn(normalizeLog(logging), (log) =>\n        defaultHandler('warn', typeof log === 'function' ? log() : log),\n      )\n    } else {\n      defaultHandler(logLevel, logging)\n    }\n  }\n}\n\nconst normalizeLog = (log: RollupLog | string): RollupLog =>\n  typeof log === 'string' ? { message: log } : log\n\nexport function resolveUserExternal(\n  user: ExternalOption,\n  id: string,\n  parentId: string | undefined,\n  isResolved: boolean,\n): boolean | null | void {\n  if (typeof user === 'function') {\n    return user(id, parentId, isResolved)\n  } else if (Array.isArray(user)) {\n    return user.some((test) => isExternal(id, test))\n  } else {\n    return isExternal(id, user)\n  }\n}\n\nfunction isExternal(id: string, test: string | RegExp) {\n  if (typeof test === 'string') {\n    return id === test\n  } else {\n    return test.test(id)\n  }\n}\n\nexport class ChunkMetadataMap {\n  private _inner = new Map<string, ChunkMetadata | AssetMetadata>()\n  private _resetChunks = new Set<string>()\n\n  private _getKey(chunk: RenderedChunk | OutputChunk | OutputAsset): string {\n    return 'preliminaryFileName' in chunk\n      ? chunk.preliminaryFileName\n      : chunk.fileName\n  }\n\n  private _getDefaultValue(\n    chunk: RenderedChunk | OutputChunk | OutputAsset,\n  ): ChunkMetadata | AssetMetadata {\n    return chunk.type === 'chunk'\n      ? {\n          importedAssets: new Set(),\n          importedCss: new Set(),\n          // NOTE: adding this as a workaround for now ideally we'd want to remove this workaround\n          // use shared `chunk.modules` object to allow mutation on js side plugins\n          __modules: chunk.modules,\n        }\n      : {\n          importedAssets: new Set(),\n          importedCss: new Set(),\n        }\n  }\n\n  get(\n    chunk: RenderedChunk | OutputChunk | OutputAsset,\n  ): ChunkMetadata | AssetMetadata {\n    const key = this._getKey(chunk)\n    if (!this._inner.has(key)) {\n      this._inner.set(key, this._getDefaultValue(chunk))\n    }\n    return this._inner.get(key)!\n  }\n\n  // reset chunk metadata on the first RenderChunk call for watch mode\n  reset(chunk: RenderedChunk | OutputChunk | OutputAsset): void {\n    const key = this._getKey(chunk)\n    if (this._resetChunks.has(key)) return\n\n    this._resetChunks.add(key)\n    this._inner.set(key, this._getDefaultValue(chunk))\n  }\n\n  clearResetChunks(): void {\n    this._resetChunks.clear()\n  }\n}\n\nexport function injectEnvironmentToHooks(\n  environment: Environment,\n  chunkMetadataMap: ChunkMetadataMap,\n  plugin: Plugin,\n): Plugin {\n  const { resolveId, load, transform } = plugin\n\n  // the plugin can be a class instance (e.g. native plugins)\n  const clone: Plugin = Object.assign(\n    Object.create(Object.getPrototypeOf(plugin)),\n    plugin,\n  )\n\n  for (const hook of Object.keys(clone) as RollupPluginHooks[]) {\n    switch (hook) {\n      case 'resolveId':\n        clone[hook] = wrapEnvironmentResolveId(\n          environment,\n          resolveId,\n          plugin.name,\n        )\n        break\n      case 'load':\n        clone[hook] = wrapEnvironmentLoad(environment, load, plugin.name)\n        break\n      case 'transform':\n        clone[hook] = wrapEnvironmentTransform(\n          environment,\n          transform,\n          plugin.name,\n        )\n        break\n      default:\n        if (ROLLUP_HOOKS.includes(hook)) {\n          ;(clone as any)[hook] = wrapEnvironmentHook(\n            environment,\n            chunkMetadataMap,\n            plugin,\n            hook,\n          )\n        }\n        break\n    }\n  }\n\n  return clone\n}\n\ntype AbstractHook<Handler extends Function> = {\n  handler: Handler\n  filter?: unknown\n  order?: unknown\n}\nconst wrappedHookMap = new WeakMap<\n  AbstractHook<Function>,\n  Array<AbstractHook<Function>>\n>()\nfunction wrapHookObject<\n  Handler extends Function,\n  Hook extends AbstractHook<Handler>,\n>(hook: Hook, handler: Handler): Hook {\n  const newHook = {\n    ...hook,\n    handler,\n  }\n\n  if (!wrappedHookMap.has(hook)) {\n    wrappedHookMap.set(hook, [])\n    Object.defineProperty(hook, 'filter', {\n      get() {\n        return wrappedHookMap.get(hook)![0].filter\n      },\n      set(v) {\n        for (const h of wrappedHookMap.get(hook)!) {\n          h.filter = v\n        }\n      },\n    })\n    Object.defineProperty(hook, 'order', {\n      get() {\n        return wrappedHookMap.get(hook)![0].order\n      },\n      set(v) {\n        for (const h of wrappedHookMap.get(hook)!) {\n          h.order = v\n        }\n      },\n    })\n  }\n  wrappedHookMap.get(hook)!.push(newHook)\n\n  return newHook\n}\n\nfunction wrapEnvironmentResolveId(\n  environment: Environment,\n  hook: Plugin['resolveId'] | undefined,\n  pluginName: string,\n): Plugin['resolveId'] {\n  if (!hook) return\n\n  const fn = getHookHandler(hook)\n  const handler: Plugin['resolveId'] = function (id, importer, options) {\n    return fn.call(\n      injectEnvironmentInContext(this, environment),\n      id,\n      importer,\n      injectSsrFlag(options, environment, pluginName),\n    )\n  }\n\n  if ('handler' in hook) {\n    return wrapHookObject(hook, handler)\n  } else {\n    return handler\n  }\n}\n\nfunction wrapEnvironmentLoad(\n  environment: Environment,\n  hook: Plugin['load'] | undefined,\n  pluginName: string,\n): Plugin['load'] {\n  if (!hook) return\n\n  const fn = getHookHandler(hook)\n  const handler: Plugin['load'] = function (id, ...args) {\n    return fn.call(\n      injectEnvironmentInContext(this, environment),\n      id,\n      injectSsrFlag(args[0], environment, pluginName),\n    )\n  }\n\n  if ('handler' in hook) {\n    return wrapHookObject(hook, handler)\n  } else {\n    return handler\n  }\n}\n\nfunction wrapEnvironmentTransform(\n  environment: Environment,\n  hook: Plugin['transform'] | undefined,\n  pluginName: string,\n): Plugin['transform'] {\n  if (!hook) return\n\n  const fn = getHookHandler(hook)\n  const handler: Plugin['transform'] = function (code, importer, ...args) {\n    return fn.call(\n      injectEnvironmentInContext(this, environment),\n      code,\n      importer,\n      injectSsrFlag(args[0], environment, pluginName),\n    )\n  }\n\n  if ('handler' in hook) {\n    return wrapHookObject(hook, handler)\n  } else {\n    return handler\n  }\n}\n\nfunction wrapEnvironmentHook<HookName extends keyof Plugin>(\n  environment: Environment,\n  chunkMetadataMap: ChunkMetadataMap,\n  plugin: Plugin,\n  hookName: HookName,\n): Plugin[HookName] {\n  const hook = plugin[hookName]\n  if (!hook) return\n\n  const fn = getHookHandler(hook)\n  if (typeof fn !== 'function') return hook\n\n  const handler: Plugin[HookName] = function (\n    this: PluginContext,\n    ...args: any[]\n  ) {\n    if (hookName === 'renderChunk') {\n      injectChunkMetadata(chunkMetadataMap, args[1], true)\n    }\n    if (hookName === 'augmentChunkHash') {\n      injectChunkMetadata(chunkMetadataMap, args[0])\n    }\n    if (hookName === 'generateBundle' || hookName === 'writeBundle') {\n      const bundle = args[1] as OutputBundle\n      for (const chunk of Object.values(bundle)) {\n        injectChunkMetadata(chunkMetadataMap, chunk)\n      }\n    }\n    return fn.call(injectEnvironmentInContext(this, environment), ...args)\n  }\n\n  if ('handler' in hook) {\n    return wrapHookObject(hook, handler)\n  } else {\n    return handler\n  }\n}\n\nfunction injectChunkMetadata(\n  chunkMetadataMap: ChunkMetadataMap,\n  chunk: RenderedChunk | OutputChunk | OutputAsset,\n  resetChunkMetadata = false,\n) {\n  if (resetChunkMetadata) {\n    chunkMetadataMap.reset(chunk)\n  }\n  // define instead of assign to avoid detected as a change\n  // https://github.com/rolldown/rolldown/blob/f4c5ff27799f2b0152c689c398e61bc7d30429ff/packages/rolldown/src/utils/transform-to-rollup-output.ts#L87\n  Object.defineProperty(chunk, 'viteMetadata', {\n    value: chunkMetadataMap.get(chunk),\n    enumerable: true,\n  })\n  if (chunk.type === 'chunk') {\n    Object.defineProperty(chunk, 'modules', {\n      get() {\n        return chunk.viteMetadata!.__modules\n      },\n      enumerable: true,\n    })\n  }\n}\n\nfunction injectEnvironmentInContext<Context extends MinimalPluginContext>(\n  context: Context,\n  environment: Environment,\n) {\n  context.meta.viteVersion ??= VERSION\n  context.environment ??= environment\n  return context\n}\n\nfunction injectSsrFlag<T extends Record<string, any>>(\n  options: T | undefined,\n  environment: Environment,\n  pluginName: string,\n): T & { ssr?: boolean } {\n  let ssr = environment.config.consumer === 'server'\n  const newOptions = { ...(options ?? {}), ssr } as T & {\n    ssr?: boolean\n  }\n\n  if (\n    isFutureDeprecationEnabled(\n      environment?.getTopLevelConfig(),\n      'removePluginHookSsrArgument',\n    )\n  ) {\n    Object.defineProperty(newOptions, 'ssr', {\n      get() {\n        warnFutureDeprecation(\n          environment?.getTopLevelConfig(),\n          'removePluginHookSsrArgument',\n          `Used in plugin \"${pluginName}\".`,\n        )\n        return ssr\n      },\n      set(v) {\n        ssr = v\n      },\n    })\n  }\n\n  return newOptions\n}\n\n/*\n  The following functions are copied from rollup\n  https://github.com/rollup/rollup/blob/ce6cb93098850a46fa242e37b74a919e99a5de28/src/ast/nodes/MetaProperty.ts#L155-L203\n\n  https://github.com/rollup/rollup\n  The MIT License (MIT)\n  Copyright (c) 2017 [these people](https://github.com/rollup/rollup/graphs/contributors)\n  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\nconst needsEscapeRegEx = /[\\n\\r'\\\\\\u2028\\u2029]/\nconst quoteNewlineRegEx = /([\\n\\r'\\u2028\\u2029])/g\nconst backSlashRegEx = /\\\\/g\n\nfunction escapeId(id: string): string {\n  if (!needsEscapeRegEx.test(id)) return id\n  return id.replace(backSlashRegEx, '\\\\\\\\').replace(quoteNewlineRegEx, '\\\\$1')\n}\n\nconst getResolveUrl = (path: string, URL = 'URL') => `new ${URL}(${path}).href`\n\nconst getRelativeUrlFromDocument = (relativePath: string, umd = false) =>\n  getResolveUrl(\n    `'${escapeId(partialEncodeURIPath(relativePath))}', ${\n      umd ? `typeof document === 'undefined' ? location.href : ` : ''\n    }document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || document.baseURI`,\n  )\n\nconst getFileUrlFromFullPath = (path: string) =>\n  `require('u' + 'rl').pathToFileURL(${path}).href`\n\nconst getFileUrlFromRelativePath = (path: string) =>\n  getFileUrlFromFullPath(`__dirname + '/${escapeId(path)}'`)\n\nconst relativeUrlMechanisms: Record<\n  InternalModuleFormat,\n  (relativePath: string) => string\n> = {\n  // amd: (relativePath) => {\n  //   if (relativePath[0] !== '.') relativePath = './' + relativePath\n  //   return getResolveUrl(\n  //     `require.toUrl('${escapeId(relativePath)}'), document.baseURI`,\n  //   )\n  // },\n  cjs: (relativePath) =>\n    `(typeof document === 'undefined' ? ${getFileUrlFromRelativePath(\n      relativePath,\n    )} : ${getRelativeUrlFromDocument(relativePath)})`,\n  es: (relativePath) =>\n    getResolveUrl(\n      `'${escapeId(partialEncodeURIPath(relativePath))}', import.meta.url`,\n    ),\n  iife: (relativePath) => getRelativeUrlFromDocument(relativePath),\n  // NOTE: make sure rollup generate `module` params\n  // system: (relativePath) =>\n  //   getResolveUrl(\n  //     `'${escapeId(partialEncodeURIPath(relativePath))}', module.meta.url`,\n  //   ),\n  umd: (relativePath) =>\n    `(typeof document === 'undefined' && typeof location === 'undefined' ? ${getFileUrlFromRelativePath(\n      relativePath,\n    )} : ${getRelativeUrlFromDocument(relativePath, true)})`,\n}\n/* end of copy */\n\nconst customRelativeUrlMechanisms = {\n  ...relativeUrlMechanisms,\n  'worker-iife': (relativePath) =>\n    getResolveUrl(\n      `'${escapeId(partialEncodeURIPath(relativePath))}', self.location.href`,\n    ),\n} as const satisfies Record<string, (relativePath: string) => string>\n\nexport type RenderBuiltAssetUrl = (\n  filename: string,\n  type: {\n    type: 'asset' | 'public'\n    hostId: string\n    hostType: 'js' | 'css' | 'html'\n    ssr: boolean\n  },\n) => string | { relative?: boolean; runtime?: string } | undefined\n\nexport function toOutputFilePathInJS(\n  environment: PartialEnvironment,\n  filename: string,\n  type: 'asset' | 'public',\n  hostId: string,\n  hostType: 'js' | 'css' | 'html',\n  toRelative: (\n    filename: string,\n    hostType: string,\n  ) => string | { runtime: string },\n): string | { runtime: string } {\n  const { experimental, base, decodedBase } = environment.config\n  const ssr = environment.config.consumer === 'server' // was !!environment.config.build.ssr\n  const { renderBuiltUrl } = experimental\n  let relative = base === '' || base === './'\n  if (renderBuiltUrl) {\n    const result = renderBuiltUrl(filename, {\n      hostId,\n      hostType,\n      type,\n      ssr,\n    })\n    if (typeof result === 'object') {\n      if (result.runtime) {\n        return { runtime: result.runtime }\n      }\n      if (typeof result.relative === 'boolean') {\n        relative = result.relative\n      }\n    } else if (result) {\n      return result\n    }\n  }\n  if (relative && !ssr) {\n    return toRelative(filename, hostId)\n  }\n  return joinUrlSegments(decodedBase, filename)\n}\n\nexport function createToImportMetaURLBasedRelativeRuntime(\n  format: InternalModuleFormat,\n  isWorker: boolean,\n): (filename: string, importer: string) => { runtime: string } {\n  const formatLong = isWorker && format === 'iife' ? 'worker-iife' : format\n  const toRelativePath = customRelativeUrlMechanisms[formatLong]\n  return (filename, importer) => ({\n    runtime: toRelativePath(\n      path.posix.relative(path.dirname(importer), filename),\n    ),\n  })\n}\n\nexport function toOutputFilePathWithoutRuntime(\n  filename: string,\n  type: 'asset' | 'public',\n  hostId: string,\n  hostType: 'js' | 'css' | 'html',\n  config: ResolvedConfig,\n  toRelative: (filename: string, hostId: string) => string,\n): string {\n  const { renderBuiltUrl } = config.experimental\n  let relative = config.base === '' || config.base === './'\n  if (renderBuiltUrl) {\n    const result = renderBuiltUrl(filename, {\n      hostId,\n      hostType,\n      type,\n      ssr: !!config.build.ssr,\n    })\n    if (typeof result === 'object') {\n      if (result.runtime) {\n        throw new Error(\n          `{ runtime: \"${result.runtime}\" } is not supported for assets in ${hostType} files: ${filename}`,\n        )\n      }\n      if (typeof result.relative === 'boolean') {\n        relative = result.relative\n      }\n    } else if (result) {\n      return result\n    }\n  }\n  if (relative && !config.build.ssr) {\n    return toRelative(filename, hostId)\n  } else {\n    return joinUrlSegments(config.decodedBase, filename)\n  }\n}\n\nexport const toOutputFilePathInCss: typeof toOutputFilePathWithoutRuntime =\n  toOutputFilePathWithoutRuntime\nexport const toOutputFilePathInHtml: typeof toOutputFilePathWithoutRuntime =\n  toOutputFilePathWithoutRuntime\n\nexport class BuildEnvironment extends BaseEnvironment {\n  mode = 'build' as const\n\n  isBuilt = false\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    setup?: {\n      options?: EnvironmentOptions\n    },\n  ) {\n    let options = config.environments[name]\n    if (!options) {\n      throw new Error(`Environment \"${name}\" is not defined in the config.`)\n    }\n    if (setup?.options) {\n      options = mergeConfig(\n        options,\n        setup.options,\n      ) as ResolvedEnvironmentOptions\n    }\n    super(name, config, options)\n  }\n\n  async init(): Promise<void> {\n    if (this._initiated) {\n      return\n    }\n    this._initiated = true\n  }\n}\n\nexport interface ViteBuilder {\n  environments: Record<string, BuildEnvironment>\n  config: ResolvedConfig\n  buildApp(): Promise<void>\n  build(\n    environment: BuildEnvironment,\n  ): Promise<RolldownOutput | RolldownOutput[] | RolldownWatcher>\n  runDevTools(): Promise<void>\n}\n\nexport interface BuilderOptions {\n  /**\n   * Whether to share the config instance among environments to align with the behavior of dev server.\n   *\n   * @default false\n   * @experimental\n   */\n  sharedConfigBuild?: boolean\n  /**\n   * Whether to share the plugin instances among environments to align with the behavior of dev server.\n   *\n   * @default false\n   * @experimental\n   */\n  sharedPlugins?: boolean\n  buildApp?: (builder: ViteBuilder) => Promise<void>\n}\n\nconst _builderOptionsDefaults = Object.freeze({\n  sharedConfigBuild: false,\n  sharedPlugins: false,\n  // buildApp\n} satisfies BuilderOptions)\nexport const builderOptionsDefaults: Readonly<Partial<BuilderOptions>> =\n  _builderOptionsDefaults\n\nexport function resolveBuilderOptions(\n  options: BuilderOptions | undefined,\n): ResolvedBuilderOptions | undefined {\n  if (!options) return\n  return mergeWithDefaults(\n    { ..._builderOptionsDefaults, buildApp: async () => {} },\n    options,\n  )\n}\n\nexport type ResolvedBuilderOptions = Required<BuilderOptions>\n\n/**\n * Creates a ViteBuilder to orchestrate building multiple environments.\n * @experimental\n */\nexport async function createBuilder(\n  inlineConfig: InlineConfig = {},\n  useLegacyBuilder: null | boolean = false,\n): Promise<ViteBuilder> {\n  const patchConfig = (resolved: ResolvedConfig) => {\n    if (!(useLegacyBuilder ?? !resolved.builder)) return\n\n    // Until the ecosystem updates to use `environment.config.build` instead of `config.build`,\n    // we need to make override `config.build` for the current environment.\n    // We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later\n    // remove the default values that shouldn't be used at all once the config is resolved\n    const environmentName = resolved.build.ssr ? 'ssr' : 'client'\n    ;(resolved.build as ResolvedBuildOptions) = {\n      ...resolved.environments[environmentName].build,\n    }\n  }\n  const config = await resolveConfigToBuild(inlineConfig, patchConfig)\n  useLegacyBuilder ??= !config.builder\n  const configBuilder = config.builder ?? resolveBuilderOptions({})!\n\n  const environments: Record<string, BuildEnvironment> = {}\n\n  const builder: ViteBuilder = {\n    environments,\n    config,\n    async buildApp() {\n      const pluginContext = new BasicMinimalPluginContext(\n        { ...basePluginContextMeta, watchMode: false },\n        config.logger,\n      )\n\n      // order 'pre' and 'normal' hooks are run first, then config.builder.buildApp, then 'post' hooks\n      let configBuilderBuildAppCalled = false\n      for (const p of config.getSortedPlugins('buildApp')) {\n        const hook = p.buildApp\n        if (\n          !configBuilderBuildAppCalled &&\n          typeof hook === 'object' &&\n          hook.order === 'post'\n        ) {\n          configBuilderBuildAppCalled = true\n          await configBuilder.buildApp(builder)\n        }\n        const handler = getHookHandler(hook)\n        await handler.call(pluginContext, builder)\n      }\n      if (!configBuilderBuildAppCalled) {\n        await configBuilder.buildApp(builder)\n      }\n      // fallback to building all environments if no environments have been built\n      if (\n        Object.values(builder.environments).every(\n          (environment) => !environment.isBuilt,\n        )\n      ) {\n        for (const environment of Object.values(builder.environments)) {\n          await builder.build(environment)\n        }\n      }\n    },\n    async build(\n      environment: BuildEnvironment,\n    ): Promise<RolldownOutput | RolldownOutput[] | RolldownWatcher> {\n      const output = await buildEnvironment(environment)\n      environment.isBuilt = true\n      return output\n    },\n    async runDevTools() {\n      const devtoolsConfig = config.devtools\n      if (devtoolsConfig.enabled) {\n        try {\n          const { start } = await import(`@vitejs/devtools/cli-commands`)\n          await start(devtoolsConfig.config)\n        } catch (e) {\n          config.logger.error(\n            colors.red(`Failed to run Vite DevTools: ${e.message || e.stack}`),\n            { error: e },\n          )\n        }\n      }\n    },\n  }\n\n  async function setupEnvironment(name: string, config: ResolvedConfig) {\n    const environment = await config.build.createEnvironment(name, config)\n    await environment.init()\n    environments[name] = environment\n  }\n\n  if (useLegacyBuilder) {\n    await setupEnvironment(config.build.ssr ? 'ssr' : 'client', config)\n  } else {\n    const environmentConfigs: [string, ResolvedConfig][] = []\n    for (const environmentName of Object.keys(config.environments)) {\n      // We need to resolve the config again so we can properly merge options\n      // and get a new set of plugins for each build environment. The ecosystem\n      // expects plugins to be run for the same environment once they are created\n      // and to process a single bundle at a time (contrary to dev mode where\n      // plugins are built to handle multiple environments concurrently).\n      let environmentConfig = config\n      if (!configBuilder.sharedConfigBuild) {\n        const patchConfig = (resolved: ResolvedConfig) => {\n          // Until the ecosystem updates to use `environment.config.build` instead of `config.build`,\n          // we need to make override `config.build` for the current environment.\n          // We can deprecate `config.build` in ResolvedConfig and push everyone to upgrade, and later\n          // remove the default values that shouldn't be used at all once the config is resolved\n          ;(resolved.build as ResolvedBuildOptions) = {\n            ...resolved.environments[environmentName].build,\n          }\n        }\n        const patchPlugins = (resolvedPlugins: Plugin[]) => {\n          // Force opt-in shared plugins\n          let j = 0\n          for (let i = 0; i < resolvedPlugins.length; i++) {\n            const environmentPlugin = resolvedPlugins[i]\n            if (\n              configBuilder.sharedPlugins ||\n              environmentPlugin.sharedDuringBuild\n            ) {\n              for (let k = j; k < config.plugins.length; k++) {\n                if (environmentPlugin.name === config.plugins[k].name) {\n                  resolvedPlugins[i] = config.plugins[k]\n                  j = k + 1\n                  break\n                }\n              }\n            }\n          }\n        }\n        environmentConfig = await resolveConfigToBuild(\n          inlineConfig,\n          patchConfig,\n          patchPlugins,\n        )\n      }\n      environmentConfigs.push([environmentName, environmentConfig])\n    }\n    await Promise.all(\n      environmentConfigs.map(\n        async ([environmentName, environmentConfig]) =>\n          await setupEnvironment(environmentName, environmentConfig),\n      ),\n    )\n  }\n\n  return builder\n}\n\nexport type BuildAppHook = (\n  this: MinimalPluginContextWithoutEnvironment,\n  builder: ViteBuilder,\n) => Promise<void>\n"
  },
  {
    "path": "packages/vite/src/node/cli.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport { inspect } from 'node:util'\nimport { performance } from 'node:perf_hooks'\nimport { cac } from 'cac'\nimport colors from 'picocolors'\nimport { VERSION } from './constants'\nimport type { BuildEnvironmentOptions } from './build'\nimport type { ServerOptions } from './server'\nimport type { CLIShortcut } from './shortcuts'\nimport type { LogLevel } from './logger'\nimport { createLogger } from './logger'\nimport type { InlineConfig } from './config'\n\nfunction checkNodeVersion(nodeVersion: string): boolean {\n  const currentVersion = nodeVersion.split('.')\n  const major = parseInt(currentVersion[0], 10)\n  const minor = parseInt(currentVersion[1], 10)\n  const isSupported =\n    (major === 20 && minor >= 19) || (major === 22 && minor >= 12) || major > 22\n  return isSupported\n}\n\nif (!checkNodeVersion(process.versions.node)) {\n  // eslint-disable-next-line no-console\n  console.warn(\n    colors.yellow(\n      `You are using Node.js ${process.versions.node}. ` +\n        `Vite requires Node.js version 20.19+ or 22.12+. ` +\n        `Please upgrade your Node.js version.`,\n    ),\n  )\n}\n\nconst cli = cac('vite')\n\n// global options\ninterface GlobalCLIOptions {\n  '--'?: string[]\n  c?: boolean | string\n  config?: string\n  base?: string\n  l?: LogLevel\n  logLevel?: LogLevel\n  clearScreen?: boolean\n  configLoader?: 'bundle' | 'runner' | 'native'\n  d?: boolean | string\n  debug?: boolean | string\n  f?: string\n  filter?: string\n  m?: string\n  mode?: string\n  force?: boolean\n  w?: boolean\n}\n\ninterface ExperimentalDevOptions {\n  experimentalBundle?: boolean\n}\n\ninterface BuilderCLIOptions {\n  app?: boolean\n}\n\nlet profileSession = global.__vite_profile_session\nlet profileCount = 0\n\nexport const stopProfiler = (\n  log: (message: string) => void,\n): void | Promise<void> => {\n  if (!profileSession) return\n  return new Promise((res, rej) => {\n    profileSession!.post('Profiler.stop', (err: any, { profile }: any) => {\n      // Write profile to disk, upload, etc.\n      if (!err) {\n        const outPath = path.resolve(\n          `./vite-profile-${profileCount++}.cpuprofile`,\n        )\n        fs.writeFileSync(outPath, JSON.stringify(profile))\n        log(\n          colors.yellow(\n            `CPU profile written to ${colors.white(colors.dim(outPath))}`,\n          ),\n        )\n        profileSession = undefined\n        res()\n      } else {\n        rej(err)\n      }\n    })\n  })\n}\n\nconst filterDuplicateOptions = <T extends object>(options: T) => {\n  for (const [key, value] of Object.entries(options)) {\n    if (Array.isArray(value)) {\n      options[key as keyof T] = value[value.length - 1]\n    }\n  }\n}\n/**\n * removing global flags before passing as command specific sub-configs\n */\nfunction cleanGlobalCLIOptions<Options extends GlobalCLIOptions>(\n  options: Options,\n): Omit<Options, keyof GlobalCLIOptions> {\n  const ret = { ...options }\n  delete ret['--']\n  delete ret.c\n  delete ret.config\n  delete ret.base\n  delete ret.l\n  delete ret.logLevel\n  delete ret.clearScreen\n  delete ret.configLoader\n  delete ret.d\n  delete ret.debug\n  delete ret.f\n  delete ret.filter\n  delete ret.m\n  delete ret.mode\n  delete ret.force\n  delete ret.w\n\n  // convert the sourcemap option to a boolean if necessary\n  if ('sourcemap' in ret) {\n    const sourcemap = ret.sourcemap as `${boolean}` | 'inline' | 'hidden'\n    ret.sourcemap =\n      sourcemap === 'true'\n        ? true\n        : sourcemap === 'false'\n          ? false\n          : ret.sourcemap\n  }\n  if ('watch' in ret) {\n    const watch = ret.watch\n    ret.watch = watch ? {} : undefined\n  }\n\n  return ret\n}\n\n/**\n * removing builder flags before passing as command specific sub-configs\n */\nfunction cleanBuilderCLIOptions<Options extends BuilderCLIOptions>(\n  options: Options,\n): Omit<Options, keyof BuilderCLIOptions> {\n  const ret = { ...options }\n  delete ret.app\n  return ret\n}\n\n/**\n * host may be a number (like 0), should convert to string\n */\nconst convertHost = (v: any) => {\n  if (typeof v === 'number') {\n    return String(v)\n  }\n  return v\n}\n\n/**\n * base may be a number (like 0), should convert to empty string\n */\nconst convertBase = (v: any) => {\n  if (v === 0) {\n    return ''\n  }\n  return v\n}\n\ncli\n  .option('-c, --config <file>', `[string] use specified config file`)\n  .option('--base <path>', `[string] public base path (default: /)`, {\n    type: [convertBase],\n  })\n  .option('-l, --logLevel <level>', `[string] info | warn | error | silent`)\n  .option('--clearScreen', `[boolean] allow/disable clear screen when logging`)\n  .option(\n    '--configLoader <loader>',\n    `[string] use 'bundle' to bundle the config with Rolldown, or 'runner' (experimental) to process it on the fly, or 'native' (experimental) to load using the native runtime (default: bundle)`,\n  )\n  .option('-d, --debug [feat]', `[string | boolean] show debug logs`)\n  .option('-f, --filter <filter>', `[string] filter debug logs`)\n  .option('-m, --mode <mode>', `[string] set env mode`)\n\n// dev\ncli\n  .command('[root]', 'start dev server') // default command\n  .alias('serve') // the command is called 'serve' in Vite's API\n  .alias('dev') // alias to align with the script name\n  .option('--host [host]', `[string] specify hostname`, { type: [convertHost] })\n  .option('--port <port>', `[number] specify port`)\n  .option('--open [path]', `[boolean | string] open browser on startup`)\n  .option('--cors', `[boolean] enable CORS`)\n  .option('--strictPort', `[boolean] exit if specified port is already in use`)\n  .option(\n    '--force',\n    `[boolean] force the optimizer to ignore the cache and re-bundle`,\n  )\n  .option(\n    '--experimentalBundle',\n    `[boolean] use experimental full bundle mode (this is highly experimental)`,\n  )\n  .action(\n    async (\n      root: string,\n      options: ServerOptions & ExperimentalDevOptions & GlobalCLIOptions,\n    ) => {\n      filterDuplicateOptions(options)\n      // output structure is preserved even after bundling so require()\n      // is ok here\n      const { createServer } = await import('./server')\n      try {\n        const server = await createServer({\n          root,\n          base: options.base,\n          mode: options.mode,\n          configFile: options.config,\n          configLoader: options.configLoader,\n          logLevel: options.logLevel,\n          clearScreen: options.clearScreen,\n          server: cleanGlobalCLIOptions(options),\n          forceOptimizeDeps: options.force,\n          experimental: {\n            bundledDev: options.experimentalBundle,\n          },\n        })\n\n        if (!server.httpServer) {\n          throw new Error('HTTP server not available')\n        }\n\n        await server.listen()\n\n        const info = server.config.logger.info\n\n        const modeString =\n          options.mode && options.mode !== 'development'\n            ? `  ${colors.bgGreen(` ${colors.bold(options.mode)} `)}`\n            : ''\n        const viteStartTime = global.__vite_start_time ?? false\n        const startupDurationString = viteStartTime\n          ? colors.dim(\n              `ready in ${colors.reset(\n                colors.bold(Math.ceil(performance.now() - viteStartTime)),\n              )} ms`,\n            )\n          : ''\n        const hasExistingLogs =\n          process.stdout.bytesWritten > 0 || process.stderr.bytesWritten > 0\n\n        info(\n          `\\n  ${colors.green(\n            `${colors.bold('VITE')} v${VERSION}`,\n          )}${modeString}  ${startupDurationString}\\n`,\n          {\n            clear: !hasExistingLogs,\n          },\n        )\n\n        server.printUrls()\n        const customShortcuts: CLIShortcut<typeof server>[] = []\n        if (profileSession) {\n          customShortcuts.push({\n            key: 'p',\n            description: 'start/stop the profiler',\n            async action(server) {\n              if (profileSession) {\n                await stopProfiler(server.config.logger.info)\n              } else {\n                const inspector = await import('node:inspector').then(\n                  (r) => r.default,\n                )\n                await new Promise<void>((res) => {\n                  profileSession = new inspector.Session()\n                  profileSession.connect()\n                  profileSession.post('Profiler.enable', () => {\n                    profileSession!.post('Profiler.start', () => {\n                      server.config.logger.info('Profiler started')\n                      res()\n                    })\n                  })\n                })\n              }\n            },\n          })\n        }\n        server.bindCLIShortcuts({ print: true, customShortcuts })\n      } catch (e) {\n        const logger = createLogger(options.logLevel)\n        logger.error(\n          colors.red(`error when starting dev server:\\n${inspect(e)}`),\n          {\n            error: e,\n          },\n        )\n        await stopProfiler(logger.info)\n        process.exit(1)\n      }\n    },\n  )\n\n// build\ncli\n  .command('build [root]', 'build for production')\n  .option(\n    '--target <target>',\n    `[string] transpile target (default: 'baseline-widely-available')`,\n  )\n  .option('--outDir <dir>', `[string] output directory (default: dist)`)\n  .option(\n    '--assetsDir <dir>',\n    `[string] directory under outDir to place assets in (default: assets)`,\n  )\n  .option(\n    '--assetsInlineLimit <number>',\n    `[number] static asset base64 inline threshold in bytes (default: 4096)`,\n  )\n  .option(\n    '--ssr [entry]',\n    `[string] build specified entry for server-side rendering`,\n  )\n  .option(\n    '--sourcemap [output]',\n    `[boolean | \"inline\" | \"hidden\"] output source maps for build (default: false)`,\n  )\n  .option(\n    '--minify [minifier]',\n    `[boolean | \"terser\" | \"esbuild\"] enable/disable minification, ` +\n      `or specify minifier to use (default: esbuild)`,\n  )\n  .option('--manifest [name]', `[boolean | string] emit build manifest json`)\n  .option('--ssrManifest [name]', `[boolean | string] emit ssr manifest json`)\n  .option(\n    '--emptyOutDir',\n    `[boolean] force empty outDir when it's outside of root`,\n  )\n  .option('-w, --watch', `[boolean] rebuilds when modules have changed on disk`)\n  .option('--app', `[boolean] same as \\`builder: {}\\``)\n  .action(\n    async (\n      root: string,\n      options: BuildEnvironmentOptions & BuilderCLIOptions & GlobalCLIOptions,\n    ) => {\n      filterDuplicateOptions(options)\n      const { createBuilder } = await import('./build')\n\n      const buildOptions: BuildEnvironmentOptions = cleanGlobalCLIOptions(\n        cleanBuilderCLIOptions(options),\n      )\n\n      try {\n        const inlineConfig: InlineConfig = {\n          root,\n          base: options.base,\n          mode: options.mode,\n          configFile: options.config,\n          configLoader: options.configLoader,\n          logLevel: options.logLevel,\n          clearScreen: options.clearScreen,\n          build: buildOptions,\n          ...(options.app ? { builder: {} } : {}),\n        }\n        const builder = await createBuilder(inlineConfig, null)\n        await builder.buildApp()\n        await builder.runDevTools()\n      } catch (e) {\n        createLogger(options.logLevel).error(\n          colors.red(`error during build:\\n${inspect(e)}`),\n          { error: e },\n        )\n        process.exit(1)\n      } finally {\n        await stopProfiler((message) =>\n          createLogger(options.logLevel).info(message),\n        )\n      }\n    },\n  )\n\n// optimize\ncli\n  .command(\n    'optimize [root]',\n    'pre-bundle dependencies (deprecated, the pre-bundle process runs automatically and does not need to be called)',\n  )\n  .option(\n    '--force',\n    `[boolean] force the optimizer to ignore the cache and re-bundle`,\n  )\n  .action(\n    async (root: string, options: { force?: boolean } & GlobalCLIOptions) => {\n      filterDuplicateOptions(options)\n      const { resolveConfig } = await import('./config')\n      const { optimizeDeps } = await import('./optimizer')\n      try {\n        const config = await resolveConfig(\n          {\n            root,\n            base: options.base,\n            configFile: options.config,\n            configLoader: options.configLoader,\n            logLevel: options.logLevel,\n            mode: options.mode,\n          },\n          'serve',\n        )\n        await optimizeDeps(config, options.force, true)\n      } catch (e) {\n        createLogger(options.logLevel).error(\n          colors.red(`error when optimizing deps:\\n${inspect(e)}`),\n          { error: e },\n        )\n        process.exit(1)\n      }\n    },\n  )\n\n// preview\ncli\n  .command('preview [root]', 'locally preview production build')\n  .option('--host [host]', `[string] specify hostname`, { type: [convertHost] })\n  .option('--port <port>', `[number] specify port`)\n  .option('--strictPort', `[boolean] exit if specified port is already in use`)\n  .option('--open [path]', `[boolean | string] open browser on startup`)\n  .option('--outDir <dir>', `[string] output directory (default: dist)`)\n  .action(\n    async (\n      root: string,\n      options: {\n        host?: string | boolean\n        port?: number\n        open?: boolean | string\n        strictPort?: boolean\n        outDir?: string\n      } & GlobalCLIOptions,\n    ) => {\n      filterDuplicateOptions(options)\n      const { preview } = await import('./preview')\n      try {\n        const server = await preview({\n          root,\n          base: options.base,\n          configFile: options.config,\n          configLoader: options.configLoader,\n          logLevel: options.logLevel,\n          mode: options.mode,\n          build: {\n            outDir: options.outDir,\n          },\n          preview: {\n            port: options.port,\n            strictPort: options.strictPort,\n            host: options.host,\n            open: options.open,\n          },\n        })\n        server.printUrls()\n        server.bindCLIShortcuts({ print: true })\n      } catch (e) {\n        createLogger(options.logLevel).error(\n          colors.red(`error when starting preview server:\\n${inspect(e)}`),\n          { error: e },\n        )\n        process.exit(1)\n      } finally {\n        await stopProfiler((message) =>\n          createLogger(options.logLevel).info(message),\n        )\n      }\n    },\n  )\n\ncli.help()\ncli.version(VERSION)\n\ncli.parse()\n"
  },
  {
    "path": "packages/vite/src/node/config.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport fsp from 'node:fs/promises'\nimport { pathToFileURL } from 'node:url'\nimport { inspect, promisify } from 'node:util'\nimport { performance } from 'node:perf_hooks'\nimport { createRequire } from 'node:module'\nimport crypto from 'node:crypto'\nimport colors from 'picocolors'\nimport picomatch from 'picomatch'\nimport {\n  type NormalizedOutputOptions,\n  type OutputChunk,\n  type PluginContextMeta,\n  type RolldownOptions,\n  rolldown,\n} from 'rolldown'\nimport type {\n  DevToolsConfig,\n  ResolvedDevToolsConfig,\n} from '@vitejs/devtools/config'\nimport type { Alias, AliasOptions } from '#dep-types/alias'\nimport type { AnymatchFn } from '../types/anymatch'\nimport { withTrailingSlash } from '../shared/utils'\nimport {\n  createImportMetaResolver,\n  importMetaResolveWithCustomHookString,\n} from '../module-runner/importMetaResolver'\nimport {\n  CLIENT_ENTRY,\n  DEFAULT_ASSETS_RE,\n  DEFAULT_CLIENT_CONDITIONS,\n  DEFAULT_CLIENT_MAIN_FIELDS,\n  DEFAULT_CONFIG_FILES,\n  DEFAULT_EXTENSIONS,\n  DEFAULT_EXTERNAL_CONDITIONS,\n  DEFAULT_PREVIEW_PORT,\n  DEFAULT_SERVER_CONDITIONS,\n  DEFAULT_SERVER_MAIN_FIELDS,\n  ENV_ENTRY,\n  FS_PREFIX,\n} from './constants'\nimport { resolveEnvironmentPlugins } from './plugin'\nimport type {\n  FalsyPlugin,\n  HookHandler,\n  Plugin,\n  PluginOption,\n  PluginWithRequiredHook,\n} from './plugin'\nimport type {\n  BuildEnvironmentOptions,\n  BuilderOptions,\n  RenderBuiltAssetUrl,\n  ResolvedBuildEnvironmentOptions,\n  ResolvedBuildOptions,\n  ResolvedBuilderOptions,\n} from './build'\nimport {\n  buildEnvironmentOptionsDefaults,\n  builderOptionsDefaults,\n  resolveBuildEnvironmentOptions,\n  resolveBuilderOptions,\n} from './build'\nimport type { ResolvedServerOptions, ServerOptions } from './server'\nimport { resolveServerOptions, serverConfigDefaults } from './server'\nimport { DevEnvironment } from './server/environment'\nimport { createRunnableDevEnvironment } from './server/environments/runnableEnvironment'\nimport type { WebSocketServer } from './server/ws'\nimport type { PreviewOptions, ResolvedPreviewOptions } from './preview'\nimport { resolvePreviewOptions } from './preview'\nimport {\n  type CSSOptions,\n  type ResolvedCSSOptions,\n  cssConfigDefaults,\n  resolveCSSOptions,\n} from './plugins/css'\nimport {\n  arraify,\n  asyncFlatten,\n  createDebugger,\n  createFilter,\n  hasBothRollupOptionsAndRolldownOptions,\n  isExternalUrl,\n  isFilePathESM,\n  isInNodeModules,\n  isNodeBuiltin,\n  isNodeLikeBuiltin,\n  isObject,\n  isParentDirectory,\n  mergeAlias,\n  mergeConfig,\n  mergeWithDefaults,\n  nodeLikeBuiltins,\n  normalizeAlias,\n  normalizePath,\n  resolveHostname,\n  setupRollupOptionCompat,\n} from './utils'\nimport {\n  createPluginHookUtils,\n  getHookHandler,\n  getSortedPluginsByHook,\n  resolvePlugins,\n} from './plugins'\nimport type { ESBuildOptions } from './plugins/esbuild'\nimport {\n  type EnvironmentResolveOptions,\n  type InternalResolveOptions,\n  type ResolveOptions,\n} from './plugins/resolve'\nimport type { LogLevel, Logger } from './logger'\nimport { createLogger } from './logger'\nimport type { DepOptimizationOptions } from './optimizer'\nimport type { JsonOptions } from './plugins/json'\nimport type { PackageCache } from './packages'\nimport { findNearestNodeModules, findNearestPackageData } from './packages'\nimport { loadEnv, resolveEnvPrefix } from './env'\nimport type { ResolvedSSROptions, SSROptions } from './ssr'\nimport { resolveSSROptions, ssrConfigDefaults } from './ssr'\nimport { PartialEnvironment } from './baseEnvironment'\nimport { createIdResolver } from './idResolver'\nimport { runnerImport } from './ssr/runnerImport'\nimport { getAdditionalAllowedHosts } from './server/middlewares/hostCheck'\nimport { convertEsbuildPluginToRolldownPlugin } from './optimizer/pluginConverter'\nimport { type OxcOptions, convertEsbuildConfigToOxcConfig } from './plugins/oxc'\nimport type { RequiredExceptFor } from './typeUtils'\nimport {\n  BasicMinimalPluginContext,\n  basePluginContextMeta,\n} from './server/pluginContainer'\nimport { nodeResolveWithVite } from './nodeResolve'\nimport { FullBundleDevEnvironment } from './server/environments/fullBundleEnvironment'\n\nconst debug = createDebugger('vite:config', { depth: 10 })\nconst promisifiedRealpath = promisify(fs.realpath)\nconst SYMBOL_RESOLVED_CONFIG: unique symbol = Symbol('vite:resolved-config')\n\nexport interface ConfigEnv {\n  /**\n   * 'serve': during dev (`vite` command)\n   * 'build': when building for production (`vite build` command)\n   */\n  command: 'build' | 'serve'\n  mode: string\n  isSsrBuild?: boolean\n  isPreview?: boolean\n}\n\n/**\n * spa: include SPA fallback middleware and configure sirv with `single: true` in preview\n *\n * mpa: only include non-SPA HTML middlewares\n *\n * custom: don't include HTML middlewares\n */\nexport type AppType = 'spa' | 'mpa' | 'custom'\n\nexport type UserConfigFnObject = (env: ConfigEnv) => UserConfig\nexport type UserConfigFnPromise = (env: ConfigEnv) => Promise<UserConfig>\nexport type UserConfigFn = (env: ConfigEnv) => UserConfig | Promise<UserConfig>\n\nexport type UserConfigExport =\n  | UserConfig\n  | Promise<UserConfig>\n  | UserConfigFnObject\n  | UserConfigFnPromise\n  | UserConfigFn\n\n/**\n * Type helper to make it easier to use vite.config.ts\n * accepts a direct {@link UserConfig} object, or a function that returns it.\n * The function receives a {@link ConfigEnv} object.\n */\nexport function defineConfig(config: UserConfig): UserConfig\nexport function defineConfig(config: Promise<UserConfig>): Promise<UserConfig>\nexport function defineConfig(config: UserConfigFnObject): UserConfigFnObject\nexport function defineConfig(config: UserConfigFnPromise): UserConfigFnPromise\nexport function defineConfig(config: UserConfigFn): UserConfigFn\nexport function defineConfig(config: UserConfigExport): UserConfigExport\nexport function defineConfig(config: UserConfigExport): UserConfigExport {\n  return config\n}\n\nexport interface CreateDevEnvironmentContext {\n  ws: WebSocketServer\n}\n\nexport interface DevEnvironmentOptions {\n  /**\n   * Files to be pre-transformed. Supports glob patterns.\n   */\n  warmup?: string[]\n  /**\n   * Pre-transform known direct imports\n   * defaults to true for the client environment, false for the rest\n   */\n  preTransformRequests?: boolean\n  /**\n   * Enables sourcemaps during dev\n   * @default { js: true }\n   * @experimental\n   */\n  sourcemap?: boolean | { js?: boolean; css?: boolean }\n  /**\n   * Whether or not to ignore-list source files in the dev server sourcemap, used to populate\n   * the [`x_google_ignoreList` source map extension](https://developer.chrome.com/blog/devtools-better-angular-debugging/#the-x_google_ignorelist-source-map-extension).\n   *\n   * By default, it excludes all paths containing `node_modules`. You can pass `false` to\n   * disable this behavior, or, for full control, a function that takes the source path and\n   * sourcemap path and returns whether to ignore the source path.\n   */\n  sourcemapIgnoreList?:\n    | false\n    | ((sourcePath: string, sourcemapPath: string) => boolean)\n\n  /**\n   * create the Dev Environment instance\n   */\n  createEnvironment?: (\n    name: string,\n    config: ResolvedConfig,\n    context: CreateDevEnvironmentContext,\n  ) => Promise<DevEnvironment> | DevEnvironment\n\n  /**\n   * For environments that support a full-reload, like the client, we can short-circuit when\n   * restarting the server throwing early to stop processing current files. We avoided this for\n   * SSR requests. Maybe this is no longer needed.\n   * @experimental\n   */\n  recoverable?: boolean\n\n  /**\n   * For environments associated with a module runner.\n   * By default, it is false for the client environment and true for non-client environments.\n   * This option can also be used instead of the removed config.experimental.skipSsrTransform.\n   */\n  moduleRunnerTransform?: boolean\n}\n\nfunction defaultCreateClientDevEnvironment(\n  name: string,\n  config: ResolvedConfig,\n  context: CreateDevEnvironmentContext,\n) {\n  if (config.experimental.bundledDev) {\n    return new FullBundleDevEnvironment(name, config, {\n      hot: true,\n      transport: context.ws,\n    })\n  }\n\n  return new DevEnvironment(name, config, {\n    hot: true,\n    transport: context.ws,\n  })\n}\n\nfunction defaultCreateDevEnvironment(name: string, config: ResolvedConfig) {\n  return createRunnableDevEnvironment(name, config)\n}\n\nexport type ResolvedDevEnvironmentOptions = Omit<\n  Required<DevEnvironmentOptions>,\n  'sourcemapIgnoreList'\n> & {\n  sourcemapIgnoreList: Exclude<\n    DevEnvironmentOptions['sourcemapIgnoreList'],\n    false | undefined\n  >\n}\n\ntype AllResolveOptions = ResolveOptions & {\n  alias?: AliasOptions\n}\n\ntype ResolvedAllResolveOptions = Required<ResolveOptions> & { alias: Alias[] }\n\nexport interface SharedEnvironmentOptions {\n  /**\n   * Define global variable replacements.\n   * Entries will be defined on `window` during dev and replaced during build.\n   */\n  define?: Record<string, any>\n  /**\n   * Configure resolver\n   */\n  resolve?: EnvironmentResolveOptions\n  /**\n   * Define if this environment is used for Server-Side Rendering\n   * @default 'server' if it isn't the client environment\n   */\n  consumer?: 'client' | 'server'\n  /**\n   * If true, `process.env` referenced in code will be preserved as-is and evaluated in runtime.\n   * Otherwise, it is statically replaced as an empty object.\n   */\n  keepProcessEnv?: boolean\n  /**\n   * Optimize deps config\n   */\n  optimizeDeps?: DepOptimizationOptions\n}\n\nexport interface EnvironmentOptions extends SharedEnvironmentOptions {\n  /**\n   * Dev specific options\n   */\n  dev?: DevEnvironmentOptions\n  /**\n   * Build specific options\n   */\n  build?: BuildEnvironmentOptions\n}\n\nexport type ResolvedResolveOptions = Required<ResolveOptions>\n\nexport type ResolvedEnvironmentOptions = {\n  define?: Record<string, any>\n  resolve: ResolvedResolveOptions\n  consumer: 'client' | 'server'\n  keepProcessEnv?: boolean\n  optimizeDeps: DepOptimizationOptions\n  dev: ResolvedDevEnvironmentOptions\n  build: ResolvedBuildEnvironmentOptions\n  plugins: readonly Plugin[]\n  /** @internal */\n  optimizeDepsPluginNames: string[]\n}\n\nexport type DefaultEnvironmentOptions = Omit<\n  EnvironmentOptions,\n  'consumer' | 'resolve' | 'keepProcessEnv'\n> & {\n  resolve?: AllResolveOptions\n}\n\nexport interface UserConfig extends DefaultEnvironmentOptions {\n  /**\n   * Project root directory. Can be an absolute path, or a path relative from\n   * the location of the config file itself.\n   * @default process.cwd()\n   */\n  root?: string\n  /**\n   * Base public path when served in development or production.\n   * @default '/'\n   */\n  base?: string\n  /**\n   * Directory to serve as plain static assets. Files in this directory are\n   * served and copied to build dist dir as-is without transform. The value\n   * can be either an absolute file system path or a path relative to project root.\n   *\n   * Set to `false` or an empty string to disable copied static assets to build dist dir.\n   * @default 'public'\n   */\n  publicDir?: string | false\n  /**\n   * Directory to save cache files. Files in this directory are pre-bundled\n   * deps or some other cache files that generated by vite, which can improve\n   * the performance. You can use `--force` flag or manually delete the directory\n   * to regenerate the cache files. The value can be either an absolute file\n   * system path or a path relative to project root.\n   * Default to `.vite` when no `package.json` is detected.\n   * @default 'node_modules/.vite'\n   */\n  cacheDir?: string\n  /**\n   * Explicitly set a mode to run in. This will override the default mode for\n   * each command, and can be overridden by the command line --mode option.\n   */\n  mode?: string\n  /**\n   * Array of vite plugins to use.\n   */\n  plugins?: PluginOption[]\n  /**\n   * HTML related options\n   */\n  html?: HTMLOptions\n  /**\n   * CSS related options (preprocessors and CSS modules)\n   */\n  css?: CSSOptions\n  /**\n   * JSON loading options\n   */\n  json?: JsonOptions\n  /**\n   * Transform options to pass to esbuild.\n   * Or set to `false` to disable esbuild.\n   *\n   * @deprecated Use `oxc` option instead.\n   */\n  esbuild?: ESBuildOptions | false\n  /**\n   * Transform options to pass to Oxc.\n   * Or set to `false` to disable Oxc.\n   */\n  oxc?: OxcOptions | false\n  /**\n   * Specify additional picomatch patterns to be treated as static assets.\n   */\n  assetsInclude?: string | RegExp | (string | RegExp)[]\n  /**\n   * Builder specific options\n   * @experimental\n   */\n  builder?: BuilderOptions\n  /**\n   * Server specific options, e.g. host, port, https...\n   */\n  server?: ServerOptions\n  /**\n   * Preview specific options, e.g. host, port, https...\n   */\n  preview?: PreviewOptions\n  /**\n   * Experimental features\n   *\n   * Features under this field could change in the future and might NOT follow semver.\n   * Please be careful and always pin Vite's version when using them.\n   * @experimental\n   */\n  experimental?: ExperimentalOptions\n  /**\n   * Options to opt-in to future behavior\n   */\n  future?: FutureOptions | 'warn'\n  /**\n   * Legacy options\n   *\n   * Features under this field only follow semver for patches, they could be removed in a\n   * future minor version. Please always pin Vite's version to a minor when using them.\n   */\n  legacy?: LegacyOptions\n  /**\n   * Log level.\n   * @default 'info'\n   */\n  logLevel?: LogLevel\n  /**\n   * Custom logger.\n   */\n  customLogger?: Logger\n  /**\n   * @default true\n   */\n  clearScreen?: boolean\n  /**\n   * Environment files directory. Can be an absolute path, or a path relative from\n   * root.\n   * @default root\n   */\n  envDir?: string | false\n  /**\n   * Env variables starts with `envPrefix` will be exposed to your client source code via import.meta.env.\n   * @default 'VITE_'\n   */\n  envPrefix?: string | string[]\n  /**\n   * Worker bundle options\n   */\n  worker?: {\n    /**\n     * Output format for worker bundle\n     * @default 'iife'\n     */\n    format?: 'es' | 'iife'\n    /**\n     * Vite plugins that apply to worker bundle. The plugins returned by this function\n     * should be new instances every time it is called, because they are used for each\n     * rolldown worker bundling process.\n     */\n    plugins?: () => PluginOption[]\n    /**\n     * Alias to `rolldownOptions`.\n     * @deprecated Use `rolldownOptions` instead.\n     */\n    rollupOptions?: Omit<\n      RolldownOptions,\n      'plugins' | 'input' | 'onwarn' | 'preserveEntrySignatures'\n    >\n    /**\n     * Rolldown options to build worker bundle\n     */\n    rolldownOptions?: Omit<\n      RolldownOptions,\n      'plugins' | 'input' | 'onwarn' | 'preserveEntrySignatures'\n    >\n  }\n  /**\n   * Dep optimization options\n   */\n  optimizeDeps?: DepOptimizationOptions\n  /**\n   * SSR specific options\n   * We could make SSROptions be a EnvironmentOptions if we can abstract\n   * external/noExternal for environments in general.\n   */\n  ssr?: SSROptions\n  /**\n   * Environment overrides\n   */\n  environments?: Record<string, EnvironmentOptions>\n  /**\n   * Whether your application is a Single Page Application (SPA),\n   * a Multi-Page Application (MPA), or Custom Application (SSR\n   * and frameworks with custom HTML handling)\n   * @default 'spa'\n   */\n  appType?: AppType\n  /**\n   * Enable devtools integration. Ensure that `@vitejs/devtools` is installed as a dependency.\n   * This feature is currently supported only in build mode.\n   * @experimental\n   * @default false\n   */\n  devtools?: boolean | DevToolsConfig\n}\n\nexport interface HTMLOptions {\n  /**\n   * A nonce value placeholder that will be used when generating script/style tags.\n   *\n   * Make sure that this placeholder will be replaced with a unique value for each request by the server.\n   */\n  cspNonce?: string\n}\n\nexport interface FutureOptions {\n  removePluginHookHandleHotUpdate?: 'warn'\n  removePluginHookSsrArgument?: 'warn'\n\n  removeServerModuleGraph?: 'warn'\n  removeServerReloadModule?: 'warn'\n  removeServerPluginContainer?: 'warn'\n  removeServerHot?: 'warn'\n  removeServerTransformRequest?: 'warn'\n  removeServerWarmupRequest?: 'warn'\n\n  removeSsrLoadModule?: 'warn'\n}\n\nexport interface ExperimentalOptions {\n  /**\n   * Append fake `&lang.(ext)` when queries are specified, to preserve the file extension for following plugins to process.\n   *\n   * @experimental\n   * @default false\n   */\n  importGlobRestoreExtension?: boolean\n  /**\n   * Allow finegrain control over assets and public files paths\n   *\n   * @experimental\n   */\n  renderBuiltUrl?: RenderBuiltAssetUrl\n  /**\n   * Enables support of HMR partial accept via `import.meta.hot.acceptExports`.\n   *\n   * @experimental\n   * @default false\n   */\n  hmrPartialAccept?: boolean\n  /**\n   * Enable full bundle mode.\n   *\n   * This is highly experimental.\n   *\n   * @experimental\n   * @default false\n   */\n  bundledDev?: boolean\n}\n\nexport interface LegacyOptions {\n  /**\n   * In Vite 6.0.8 and below, WebSocket server was able to connect from any web pages. However,\n   * that could be exploited by a malicious web page.\n   *\n   * In Vite 6.0.9+, the WebSocket server now requires a token to connect from a web page.\n   * But this may break some plugins and frameworks that connects to the WebSocket server\n   * on their own. Enabling this option will make Vite skip the token check.\n   *\n   * **We do not recommend enabling this option unless you are sure that you are fine with\n   * that security weakness.**\n   */\n  skipWebSocketTokenCheck?: boolean\n  /**\n   * Opt-in to the pre-Vite 8 CJS interop behavior, which was inconsistent.\n   *\n   * In pre-Vite 8 versions, Vite had inconsistent CJS interop behavior. This was due to\n   * the different behavior of esbuild and the Rollup commonjs plugin.\n   * Vite 8+ uses Rolldown for both the dependency optimization in dev and the production build,\n   * which aligns the behavior to esbuild.\n   *\n   * See the Vite 8 migration guide for more details.\n   */\n  inconsistentCjsInterop?: boolean\n}\n\nexport interface ResolvedWorkerOptions {\n  format: 'es' | 'iife'\n  plugins: (bundleChain: string[]) => Promise<ResolvedConfig>\n  /**\n   * @deprecated Use `rolldownOptions` instead.\n   */\n  rollupOptions: RolldownOptions\n  rolldownOptions: RolldownOptions\n}\n\nexport interface InlineConfig extends UserConfig {\n  configFile?: string | false\n  /** @experimental */\n  configLoader?: 'bundle' | 'runner' | 'native'\n  /** @deprecated */\n  envFile?: false\n  forceOptimizeDeps?: boolean\n}\n\nexport interface ResolvedConfig extends Readonly<\n  Omit<\n    UserConfig,\n    | 'plugins'\n    | 'css'\n    | 'json'\n    | 'assetsInclude'\n    | 'optimizeDeps'\n    | 'worker'\n    | 'build'\n    | 'dev'\n    | 'environments'\n    | 'experimental'\n    | 'future'\n    | 'server'\n    | 'preview'\n    | 'devtools'\n  > & {\n    configFile: string | undefined\n    configFileDependencies: string[]\n    inlineConfig: InlineConfig\n    root: string\n    base: string\n    /** @internal */\n    decodedBase: string\n    /** @internal */\n    rawBase: string\n    publicDir: string\n    cacheDir: string\n    command: 'build' | 'serve'\n    mode: string\n    /** `true` when build or full-bundle mode dev */\n    isBundled: boolean\n    isWorker: boolean\n    // in nested worker bundle to find the main config\n    /** @internal */\n    mainConfig: ResolvedConfig | null\n    /** @internal list of bundle entry id. used to detect recursive worker bundle. */\n    bundleChain: string[]\n    isProduction: boolean\n    envDir: string | false\n    env: Record<string, any>\n    resolve: Required<ResolveOptions> & {\n      alias: Alias[]\n    }\n    plugins: readonly Plugin[]\n    css: ResolvedCSSOptions\n    json: Required<JsonOptions>\n    /** @deprecated Use `oxc` option instead. */\n    esbuild: ESBuildOptions | false\n    oxc: OxcOptions | false\n    server: ResolvedServerOptions\n    dev: ResolvedDevEnvironmentOptions\n    /** @experimental */\n    builder: ResolvedBuilderOptions | undefined\n    build: ResolvedBuildOptions\n    devtools: ResolvedDevToolsConfig\n    preview: ResolvedPreviewOptions\n    ssr: ResolvedSSROptions\n    assetsInclude: (file: string) => boolean\n    rawAssetsInclude: (string | RegExp)[]\n    logger: Logger\n    /**\n     * Create an internal resolver to be used in special scenarios, e.g.\n     * optimizer & handling css `@imports`.\n     *\n     * This API is deprecated. It only works for the client and ssr\n     * environments. The `aliasOnly` option is also not being used anymore.\n     * Plugins should move to `createIdResolver(environment.config)` instead.\n     *\n     * @deprecated Use `createIdResolver` from `vite` instead.\n     */\n    createResolver: (options?: Partial<InternalResolveOptions>) => ResolveFn\n    optimizeDeps: DepOptimizationOptions\n    /** @internal */\n    packageCache: PackageCache\n    worker: ResolvedWorkerOptions\n    appType: AppType\n    experimental: RequiredExceptFor<ExperimentalOptions, 'renderBuiltUrl'>\n    future: FutureOptions | undefined\n    environments: Record<string, ResolvedEnvironmentOptions>\n    /** @internal injected by legacy plugin */\n    isOutputOptionsForLegacyChunks?(\n      outputOptions: NormalizedOutputOptions,\n    ): boolean\n    /**\n     * The token to connect to the WebSocket server from browsers.\n     *\n     * We recommend using `import.meta.hot` rather than connecting\n     * to the WebSocket server directly.\n     * If you have a usecase that requires connecting to the WebSocket\n     * server, please create an issue so that we can discuss.\n     *\n     * @deprecated\n     */\n    webSocketToken: string\n    /** @internal */\n    fsDenyGlob: AnymatchFn\n    /** @internal */\n    safeModulePaths: Set<string>\n    /** @internal */\n    [SYMBOL_RESOLVED_CONFIG]: true\n  } & PluginHookUtils\n> {}\n\nexport async function resolveDevToolsConfig(\n  config: DevToolsConfig | boolean | undefined,\n  host: string | boolean | undefined,\n  logger: Logger,\n): Promise<ResolvedDevToolsConfig> {\n  const isEnabled = config === true || !!(config && config.enabled)\n  const resolvedHostname = await resolveHostname(host)\n  const fallbackHostname = resolvedHostname.host ?? 'localhost'\n  const fallbackConfig = {\n    config: {\n      host: fallbackHostname,\n    },\n    enabled: false,\n  }\n  if (!isEnabled) {\n    return fallbackConfig\n  }\n\n  try {\n    const { normalizeDevToolsConfig } = await import('@vitejs/devtools/config')\n    return normalizeDevToolsConfig(config, fallbackHostname)\n  } catch (e) {\n    logger.error(\n      colors.red(\n        `Failed to load Vite DevTools config: ${e.message || e.stack}`,\n      ),\n      { error: e },\n    )\n    return fallbackConfig\n  }\n}\n\n// inferred ones are omitted\nconst configDefaults = Object.freeze({\n  define: {},\n  dev: {\n    warmup: [],\n    // preTransformRequests\n    /** @experimental */\n    sourcemap: { js: true },\n    sourcemapIgnoreList: undefined,\n    // createEnvironment\n    // recoverable\n    // moduleRunnerTransform\n  },\n  build: buildEnvironmentOptionsDefaults,\n  resolve: {\n    // mainFields\n    // conditions\n    externalConditions: [...DEFAULT_EXTERNAL_CONDITIONS],\n    extensions: DEFAULT_EXTENSIONS,\n    dedupe: [],\n    /** @experimental */\n    noExternal: [],\n    external: [],\n    preserveSymlinks: false,\n    tsconfigPaths: false,\n    alias: [],\n  },\n\n  // root\n  base: '/',\n  publicDir: 'public',\n  // cacheDir\n  // mode\n  plugins: [],\n  html: {\n    cspNonce: undefined,\n  },\n  css: cssConfigDefaults,\n  json: {\n    namedExports: true,\n    stringify: 'auto',\n  },\n  // esbuild\n  assetsInclude: undefined,\n  /** @experimental */\n  builder: builderOptionsDefaults,\n  server: serverConfigDefaults,\n  preview: {\n    port: DEFAULT_PREVIEW_PORT,\n    // strictPort\n    // host\n    // https\n    // open\n    // proxy\n    // cors\n    // headers\n  },\n  /** @experimental */\n  experimental: {\n    importGlobRestoreExtension: false,\n    renderBuiltUrl: undefined,\n    hmrPartialAccept: false,\n    bundledDev: false,\n  },\n  future: {\n    removePluginHookHandleHotUpdate: undefined,\n    removePluginHookSsrArgument: undefined,\n    removeServerModuleGraph: undefined,\n    removeServerHot: undefined,\n    removeServerTransformRequest: undefined,\n    removeServerWarmupRequest: undefined,\n    removeSsrLoadModule: undefined,\n  },\n  legacy: {\n    skipWebSocketTokenCheck: false,\n  },\n  logLevel: 'info',\n  customLogger: undefined,\n  clearScreen: true,\n  envDir: undefined,\n  envPrefix: 'VITE_',\n  worker: {\n    format: 'iife',\n    plugins: (): never[] => [],\n    // rollupOptions\n  },\n  optimizeDeps: {\n    include: [],\n    exclude: [],\n    needsInterop: [],\n    // esbuildOptions\n    rolldownOptions: {},\n    /** @experimental */\n    extensions: [],\n    /** @deprecated @experimental */\n    disabled: 'build',\n    // noDiscovery\n    /** @experimental */\n    holdUntilCrawlEnd: true,\n    // entries\n    /** @experimental */\n    force: false,\n    /** @experimental */\n    ignoreOutdatedRequests: false,\n  },\n  ssr: ssrConfigDefaults,\n  environments: {},\n  appType: 'spa',\n} satisfies UserConfig)\n\nexport function resolveDevEnvironmentOptions(\n  dev: DevEnvironmentOptions | undefined,\n  environmentName: string | undefined,\n  consumer: 'client' | 'server' | undefined,\n  // Backward compatibility\n  preTransformRequest?: boolean,\n): ResolvedDevEnvironmentOptions {\n  const resolved = mergeWithDefaults(\n    {\n      ...configDefaults.dev,\n      sourcemapIgnoreList: isInNodeModules,\n      preTransformRequests: preTransformRequest ?? consumer === 'client',\n      createEnvironment:\n        environmentName === 'client'\n          ? defaultCreateClientDevEnvironment\n          : defaultCreateDevEnvironment,\n      recoverable: consumer === 'client',\n      moduleRunnerTransform: consumer === 'server',\n    },\n    dev ?? {},\n  )\n  return {\n    ...resolved,\n    sourcemapIgnoreList:\n      resolved.sourcemapIgnoreList === false\n        ? () => false\n        : resolved.sourcemapIgnoreList,\n  }\n}\n\nfunction resolveEnvironmentOptions(\n  options: EnvironmentOptions,\n  alias: Alias[],\n  preserveSymlinks: boolean,\n  forceOptimizeDeps: boolean | undefined,\n  logger: Logger,\n  environmentName: string,\n  isBundledDev: boolean,\n  // Backward compatibility\n  isSsrTargetWebworkerSet?: boolean,\n  preTransformRequests?: boolean,\n): ResolvedEnvironmentOptions {\n  const isClientEnvironment = environmentName === 'client'\n  const consumer =\n    options.consumer ?? (isClientEnvironment ? 'client' : 'server')\n  const isSsrTargetWebworkerEnvironment =\n    isSsrTargetWebworkerSet && environmentName === 'ssr'\n\n  if (options.define?.['process.env']) {\n    const processEnvDefine = options.define['process.env']\n    if (typeof processEnvDefine === 'object') {\n      const pathKey = Object.entries(processEnvDefine).find(\n        // check with toLowerCase() to match with `Path` / `PATH` (Windows uses `Path`)\n        ([key, value]) => key.toLowerCase() === 'path' && !!value,\n      )?.[0]\n      if (pathKey) {\n        logger.warnOnce(\n          colors.yellow(\n            `The \\`define\\` option contains an object with ${JSON.stringify(pathKey)} for \"process.env\" key. ` +\n              'It looks like you may have passed the entire `process.env` object to `define`, ' +\n              'which can unintentionally expose all environment variables. ' +\n              'This poses a security risk and is discouraged.',\n          ),\n        )\n      }\n    }\n  }\n\n  const resolve = resolveEnvironmentResolveOptions(\n    options.resolve,\n    alias,\n    preserveSymlinks,\n    logger,\n    consumer,\n    isSsrTargetWebworkerEnvironment,\n  )\n  return {\n    define: options.define,\n    resolve,\n    keepProcessEnv:\n      options.keepProcessEnv ??\n      (isSsrTargetWebworkerEnvironment ? false : consumer === 'server'),\n    consumer,\n    optimizeDeps: resolveDepOptimizationOptions(\n      options.optimizeDeps,\n      resolve.preserveSymlinks,\n      forceOptimizeDeps,\n      consumer,\n      logger,\n    ),\n    dev: resolveDevEnvironmentOptions(\n      options.dev,\n      environmentName,\n      consumer,\n      preTransformRequests,\n    ),\n    build: resolveBuildEnvironmentOptions(\n      options.build ?? {},\n      logger,\n      consumer,\n      isBundledDev,\n    ),\n    plugins: undefined!, // to be resolved later\n    // will be set by `setOptimizeDepsPluginNames` later\n    optimizeDepsPluginNames: undefined!,\n  }\n}\n\nexport function getDefaultEnvironmentOptions(\n  config: UserConfig,\n): EnvironmentOptions {\n  return {\n    define: config.define,\n    resolve: {\n      ...config.resolve,\n      // mainFields and conditions are not inherited\n      mainFields: undefined,\n      conditions: undefined,\n    },\n    dev: config.dev,\n    build: config.build,\n  }\n}\n\nexport interface PluginHookUtils {\n  getSortedPlugins: <K extends keyof Plugin>(\n    hookName: K,\n  ) => PluginWithRequiredHook<K>[]\n  getSortedPluginHooks: <K extends keyof Plugin>(\n    hookName: K,\n  ) => NonNullable<HookHandler<Plugin[K]>>[]\n}\n\nexport type ResolveFn = (\n  id: string,\n  importer?: string,\n  aliasOnly?: boolean,\n  ssr?: boolean,\n) => Promise<string | undefined>\n\n/**\n * Check and warn if `path` includes characters that don't work well in Vite,\n * such as `#` and `?` and `*`.\n */\nfunction checkBadCharactersInPath(\n  name: string,\n  path: string,\n  logger: Logger,\n): void {\n  const badChars = []\n\n  if (path.includes('#')) {\n    badChars.push('#')\n  }\n  if (path.includes('?')) {\n    badChars.push('?')\n  }\n  if (path.includes('*')) {\n    badChars.push('*')\n  }\n\n  if (badChars.length > 0) {\n    const charString = badChars.map((c) => `\"${c}\"`).join(' and ')\n    const inflectedChars = badChars.length > 1 ? 'characters' : 'character'\n\n    logger.warn(\n      colors.yellow(\n        `${name} contains the ${charString} ${inflectedChars} (${colors.cyan(\n          path,\n        )}), which may not work when running Vite. Consider renaming the directory / file to remove the characters.`,\n      ),\n    )\n  }\n}\n\nconst clientAlias = [\n  {\n    find: /^\\/?@vite\\/env/,\n    replacement: path.posix.join(FS_PREFIX, normalizePath(ENV_ENTRY)),\n  },\n  {\n    find: /^\\/?@vite\\/client/,\n    replacement: path.posix.join(FS_PREFIX, normalizePath(CLIENT_ENTRY)),\n  },\n]\n\n/**\n * alias and preserveSymlinks are not per-environment options, but they are\n * included in the resolved environment options for convenience.\n */\nfunction resolveEnvironmentResolveOptions(\n  resolve: EnvironmentResolveOptions | undefined,\n  alias: Alias[],\n  preserveSymlinks: boolean,\n  logger: Logger,\n  /** undefined when resolving the top-level resolve options */\n  consumer: 'client' | 'server' | undefined,\n  // Backward compatibility\n  isSsrTargetWebworkerEnvironment?: boolean,\n): ResolvedAllResolveOptions {\n  const resolvedResolve: ResolvedAllResolveOptions = mergeWithDefaults(\n    {\n      ...configDefaults.resolve,\n      mainFields:\n        consumer === undefined ||\n        consumer === 'client' ||\n        isSsrTargetWebworkerEnvironment\n          ? DEFAULT_CLIENT_MAIN_FIELDS\n          : DEFAULT_SERVER_MAIN_FIELDS,\n      conditions:\n        consumer === undefined ||\n        consumer === 'client' ||\n        isSsrTargetWebworkerEnvironment\n          ? DEFAULT_CLIENT_CONDITIONS\n          : DEFAULT_SERVER_CONDITIONS.filter((c) => c !== 'browser'),\n      builtins:\n        resolve?.builtins ??\n        (consumer === 'server'\n          ? isSsrTargetWebworkerEnvironment && resolve?.noExternal === true\n            ? []\n            : nodeLikeBuiltins\n          : []),\n    },\n    resolve ?? {},\n  )\n  resolvedResolve.preserveSymlinks = preserveSymlinks\n  resolvedResolve.alias = alias\n\n  if (\n    // @ts-expect-error removed field\n    resolve?.browserField === false &&\n    resolvedResolve.mainFields.includes('browser')\n  ) {\n    logger.warn(\n      colors.yellow(\n        `\\`resolve.browserField\\` is set to false, but the option is removed in favour of ` +\n          `the 'browser' string in \\`resolve.mainFields\\`. You may want to update \\`resolve.mainFields\\` ` +\n          `to remove the 'browser' string and preserve the previous browser behaviour.`,\n      ),\n    )\n  }\n  return resolvedResolve\n}\n\nfunction resolveResolveOptions(\n  resolve: AllResolveOptions | undefined,\n  logger: Logger,\n): ResolvedAllResolveOptions {\n  // resolve alias with internal client alias\n  const alias = normalizeAlias(\n    mergeAlias(clientAlias, resolve?.alias || configDefaults.resolve.alias),\n  )\n  const preserveSymlinks =\n    resolve?.preserveSymlinks ?? configDefaults.resolve.preserveSymlinks\n\n  if (alias.some((a) => a.find === '/')) {\n    logger.warn(\n      colors.yellow(\n        `\\`resolve.alias\\` contains an alias that maps \\`/\\`. ` +\n          `This is not recommended as it can cause unexpected behavior when resolving paths.`,\n      ),\n    )\n  }\n  if (alias.some((a) => a.customResolver)) {\n    logger.warn(\n      colors.yellow(\n        `\\`resolve.alias\\` contains an alias with \\`customResolver\\` option. ` +\n          `This is deprecated and will be removed in Vite 9. ` +\n          `Please use a custom plugin with a resolveId hook and \\`enforce: 'pre'\\` instead.`,\n      ),\n    )\n  }\n\n  return resolveEnvironmentResolveOptions(\n    resolve,\n    alias,\n    preserveSymlinks,\n    logger,\n    undefined,\n  )\n}\n\n// TODO: Introduce ResolvedDepOptimizationOptions\nfunction resolveDepOptimizationOptions(\n  optimizeDeps: DepOptimizationOptions | undefined,\n  preserveSymlinks: boolean,\n  forceOptimizeDeps: boolean | undefined,\n  consumer: 'client' | 'server' | undefined,\n  logger: Logger,\n): DepOptimizationOptions {\n  if (\n    optimizeDeps?.rolldownOptions &&\n    optimizeDeps?.rolldownOptions === optimizeDeps?.rollupOptions\n  ) {\n    delete optimizeDeps?.rollupOptions\n  }\n  const merged = mergeWithDefaults(\n    {\n      ...configDefaults.optimizeDeps,\n      disabled: undefined, // do not set here to avoid deprecation warning\n      noDiscovery: consumer !== 'client',\n      force: forceOptimizeDeps ?? configDefaults.optimizeDeps.force,\n    },\n    optimizeDeps ?? {},\n  )\n  setupRollupOptionCompat(merged, 'optimizeDeps')\n\n  const rolldownOptions = merged.rolldownOptions as Exclude<\n    DepOptimizationOptions['rolldownOptions'],\n    undefined\n  >\n\n  if (merged.esbuildOptions && Object.keys(merged.esbuildOptions).length > 0) {\n    logger.warn(\n      colors.yellow(\n        `You or a plugin you are using have set \\`optimizeDeps.esbuildOptions\\` ` +\n          `but this option is now deprecated. ` +\n          `Vite now uses Rolldown to optimize the dependencies. ` +\n          `Please use \\`optimizeDeps.rolldownOptions\\` instead.`,\n      ),\n    )\n\n    rolldownOptions.resolve ??= {}\n    rolldownOptions.output ??= {}\n    rolldownOptions.transform ??= {}\n\n    const setResolveOptions = <\n      T extends keyof Exclude<RolldownOptions['resolve'], undefined>,\n    >(\n      key: T,\n      value: Exclude<RolldownOptions['resolve'], undefined>[T],\n    ) => {\n      if (value !== undefined && rolldownOptions.resolve![key] === undefined) {\n        rolldownOptions.resolve![key] = value\n      }\n    }\n\n    if (\n      merged.esbuildOptions.minify !== undefined &&\n      rolldownOptions.output.minify === undefined\n    ) {\n      rolldownOptions.output.minify = merged.esbuildOptions.minify\n    }\n    if (\n      merged.esbuildOptions.treeShaking !== undefined &&\n      rolldownOptions.treeshake === undefined\n    ) {\n      rolldownOptions.treeshake = merged.esbuildOptions.treeShaking\n    }\n    if (\n      merged.esbuildOptions.define !== undefined &&\n      rolldownOptions.transform.define === undefined\n    ) {\n      rolldownOptions.transform.define = merged.esbuildOptions.define\n    }\n    if (merged.esbuildOptions.loader !== undefined) {\n      const loader = merged.esbuildOptions.loader\n      rolldownOptions.moduleTypes ??= {}\n      for (const [key, value] of Object.entries(loader)) {\n        if (\n          rolldownOptions.moduleTypes[key] === undefined &&\n          value !== 'copy' &&\n          value !== 'css' &&\n          value !== 'default' &&\n          value !== 'file' &&\n          value !== 'local-css'\n        ) {\n          rolldownOptions.moduleTypes[key] = value\n        }\n      }\n    }\n    if (\n      merged.esbuildOptions.preserveSymlinks !== undefined &&\n      rolldownOptions.resolve.symlinks === undefined\n    ) {\n      rolldownOptions.resolve.symlinks = !merged.esbuildOptions.preserveSymlinks\n    }\n    setResolveOptions('extensions', merged.esbuildOptions.resolveExtensions)\n    setResolveOptions('mainFields', merged.esbuildOptions.mainFields)\n    setResolveOptions('conditionNames', merged.esbuildOptions.conditions)\n    if (\n      merged.esbuildOptions.keepNames !== undefined &&\n      rolldownOptions.output.keepNames === undefined\n    ) {\n      rolldownOptions.output.keepNames = merged.esbuildOptions.keepNames\n    }\n\n    if (\n      merged.esbuildOptions.platform !== undefined &&\n      rolldownOptions.platform === undefined\n    ) {\n      rolldownOptions.platform = merged.esbuildOptions.platform\n    }\n\n    // NOTE: the following options cannot be converted\n    // - legalComments\n    // - target, supported (Vite used to transpile down to `ESBUILD_MODULES_TARGET`)\n    // - ignoreAnnotations\n    // - jsx, jsxFactory, jsxFragment, jsxImportSource, jsxDev, jsxSideEffects\n    // - tsconfigRaw, tsconfig\n\n    // NOTE: the following options can be converted but probably not worth it\n    // - sourceRoot\n    // - sourcesContent (`output.sourcemapExcludeSources` is not supported by rolldown)\n    // - drop\n    // - dropLabels\n    // - mangleProps, reserveProps, mangleQuoted, mangleCache\n    // - minifyWhitespace, minifyIdentifiers, minifySyntax\n    // - lineLimit\n    // - charset\n    // - pure (`treeshake.manualPureFunctions` is not supported by rolldown)\n    // - alias (it probably does not work the same with `resolve.alias`)\n    // - inject\n    // - banner, footer\n    // - nodePaths\n\n    // NOTE: the following options does not make sense to set / convert it\n    // - globalName (we only use ESM format)\n    // - color\n    // - logLimit\n    // - logOverride\n    // - splitting\n    // - outbase\n    // - packages (this should not be set)\n    // - allowOverwrite\n    // - publicPath (`file` loader is not supported by rolldown)\n    // - entryNames, chunkNames, assetNames (Vite does not support changing these options)\n    // - stdin\n    // - absWorkingDir\n  }\n\n  merged.esbuildOptions ??= {}\n  merged.esbuildOptions.preserveSymlinks ??= preserveSymlinks\n\n  rolldownOptions.resolve ??= {}\n  rolldownOptions.resolve.symlinks ??= !preserveSymlinks\n  rolldownOptions.output ??= {}\n  rolldownOptions.output.topLevelVar ??= true\n\n  return merged\n}\n\nasync function setOptimizeDepsPluginNames(resolvedConfig: ResolvedConfig) {\n  await Promise.all(\n    Object.values(resolvedConfig.environments).map(async (environment) => {\n      const plugins = environment.optimizeDeps.rolldownOptions?.plugins ?? []\n      const outputPlugins =\n        environment.optimizeDeps.rolldownOptions?.output?.plugins ?? []\n      const flattenedPlugins = await asyncFlatten([plugins, outputPlugins])\n\n      const pluginNames = []\n      for (const plugin of flattenedPlugins) {\n        if (plugin && 'name' in plugin) {\n          pluginNames.push(plugin.name)\n        }\n      }\n      environment.optimizeDepsPluginNames = pluginNames\n    }),\n  )\n}\n\nfunction applyDepOptimizationOptionCompat(resolvedConfig: ResolvedConfig) {\n  if (\n    resolvedConfig.optimizeDeps.esbuildOptions?.plugins &&\n    resolvedConfig.optimizeDeps.esbuildOptions.plugins.length > 0\n  ) {\n    resolvedConfig.optimizeDeps.rolldownOptions ??= {}\n    resolvedConfig.optimizeDeps.rolldownOptions.plugins ||= []\n    ;(resolvedConfig.optimizeDeps.rolldownOptions.plugins as any[]).push(\n      ...resolvedConfig.optimizeDeps.esbuildOptions.plugins.map((plugin) =>\n        convertEsbuildPluginToRolldownPlugin(plugin),\n      ),\n    )\n  }\n}\n\nexport function isResolvedConfig(\n  inlineConfig: InlineConfig | ResolvedConfig,\n): inlineConfig is ResolvedConfig {\n  return (\n    SYMBOL_RESOLVED_CONFIG in inlineConfig &&\n    inlineConfig[SYMBOL_RESOLVED_CONFIG]\n  )\n}\n\nexport async function resolveConfig(\n  inlineConfig: InlineConfig,\n  command: 'build' | 'serve',\n  defaultMode = 'development',\n  defaultNodeEnv = 'development',\n  isPreview = false,\n  /** @internal */\n  patchConfig: ((config: ResolvedConfig) => void) | undefined = undefined,\n  /** @internal */\n  patchPlugins: ((resolvedPlugins: Plugin[]) => void) | undefined = undefined,\n): Promise<ResolvedConfig> {\n  let config = inlineConfig\n  config.build ??= {}\n  setupRollupOptionCompat(config.build, 'build')\n  config.worker ??= {}\n  setupRollupOptionCompat(config.worker, 'worker')\n  config.optimizeDeps ??= {}\n  setupRollupOptionCompat(config.optimizeDeps, 'optimizeDeps')\n  if (config.ssr) {\n    config.ssr.optimizeDeps ??= {}\n    setupRollupOptionCompat(config.ssr.optimizeDeps, 'ssr.optimizeDeps')\n  }\n\n  let configFileDependencies: string[] = []\n  let mode = inlineConfig.mode || defaultMode\n  const isNodeEnvSet = !!process.env.NODE_ENV\n  const packageCache: PackageCache = new Map()\n\n  // some dependencies e.g. @vue/compiler-* relies on NODE_ENV for getting\n  // production-specific behavior, so set it early on\n  if (!isNodeEnvSet) {\n    process.env.NODE_ENV = defaultNodeEnv\n  }\n\n  const configEnv: ConfigEnv = {\n    mode,\n    command,\n    isSsrBuild: command === 'build' && !!config.build?.ssr,\n    isPreview,\n  }\n\n  let { configFile } = config\n  if (configFile !== false) {\n    const loadResult = await loadConfigFromFile(\n      configEnv,\n      configFile,\n      config.root,\n      config.logLevel,\n      config.customLogger,\n      config.configLoader,\n    )\n    if (loadResult) {\n      config = mergeConfig(loadResult.config, config)\n      configFile = loadResult.path\n      configFileDependencies = loadResult.dependencies\n    }\n  }\n\n  // user config may provide an alternative mode. But --mode has a higher priority\n  mode = inlineConfig.mode || config.mode || mode\n  configEnv.mode = mode\n\n  const filterPlugin = (p: Plugin | FalsyPlugin): p is Plugin => {\n    if (!p) {\n      return false\n    } else if (!p.apply) {\n      return true\n    } else if (typeof p.apply === 'function') {\n      return p.apply({ ...config, mode }, configEnv)\n    } else {\n      return p.apply === command\n    }\n  }\n\n  // resolve plugins\n  const rawPlugins = (await asyncFlatten(config.plugins || [])).filter(\n    filterPlugin,\n  )\n\n  const [prePlugins, normalPlugins, postPlugins] = sortUserPlugins(rawPlugins)\n\n  const isBuild = command === 'build'\n\n  // run config hooks\n  const userPlugins = [...prePlugins, ...normalPlugins, ...postPlugins]\n  config = await runConfigHook(config, userPlugins, configEnv)\n\n  // Ensure default client and ssr environments\n  // If there are present, ensure order { client, ssr, ...custom }\n  config.environments ??= {}\n  if (\n    !config.environments.ssr &&\n    (!isBuild || config.ssr || config.build?.ssr)\n  ) {\n    // During dev, the ssr environment is always available even if it isn't configure\n    // There is no perf hit, because the optimizer is initialized only if ssrLoadModule\n    // is called.\n    // During build, we only build the ssr environment if it is configured\n    // through the deprecated ssr top level options or if it is explicitly defined\n    // in the environments config\n    config.environments = { ssr: {}, ...config.environments }\n  }\n  if (!config.environments.client) {\n    config.environments = { client: {}, ...config.environments }\n  }\n\n  // Define logger\n  const logger = createLogger(config.logLevel, {\n    allowClearScreen: config.clearScreen,\n    customLogger: config.customLogger,\n  })\n\n  const tsconfigPathsPlugin = userPlugins.find(\n    (p) =>\n      p.name === 'vite-tsconfig-paths' ||\n      p.name === 'vite-plugin-tsconfig-paths',\n  )\n  if (tsconfigPathsPlugin) {\n    logger.warnOnce(\n      colors.yellow(\n        `The plugin ${JSON.stringify(tsconfigPathsPlugin.name)} is detected. ` +\n          `Vite now supports tsconfig paths resolution natively via the ${colors.bold('resolve.tsconfigPaths')} option. ` +\n          `You can remove the plugin and set ${colors.bold('resolve.tsconfigPaths: true')} in your Vite config instead.`,\n      ),\n    )\n  }\n\n  // resolve root\n  const resolvedRoot = normalizePath(\n    config.root ? path.resolve(config.root) : process.cwd(),\n  )\n\n  checkBadCharactersInPath('The project root', resolvedRoot, logger)\n\n  const configEnvironmentsClient = config.environments!.client!\n  configEnvironmentsClient.dev ??= {}\n\n  const deprecatedSsrOptimizeDepsConfig = config.ssr?.optimizeDeps ?? {}\n  let configEnvironmentsSsr = config.environments!.ssr\n\n  // Backward compatibility: server.warmup.clientFiles/ssrFiles -> environment.dev.warmup\n  const warmupOptions = config.server?.warmup\n  if (warmupOptions?.clientFiles) {\n    configEnvironmentsClient.dev.warmup = warmupOptions.clientFiles\n  }\n  if (warmupOptions?.ssrFiles) {\n    configEnvironmentsSsr ??= {}\n    configEnvironmentsSsr.dev ??= {}\n    configEnvironmentsSsr.dev.warmup = warmupOptions.ssrFiles\n  }\n\n  // Backward compatibility: merge ssr into environments.ssr.config as defaults\n  if (configEnvironmentsSsr) {\n    configEnvironmentsSsr.optimizeDeps = mergeConfig(\n      deprecatedSsrOptimizeDepsConfig,\n      configEnvironmentsSsr.optimizeDeps ?? {},\n    )\n\n    // merge with `resolve` as the root to merge `noExternal` correctly\n    configEnvironmentsSsr.resolve = mergeConfig(\n      {\n        resolve: {\n          conditions: config.ssr?.resolve?.conditions,\n          externalConditions: config.ssr?.resolve?.externalConditions,\n          mainFields: config.ssr?.resolve?.mainFields,\n          external: config.ssr?.external,\n          noExternal: config.ssr?.noExternal,\n        },\n      } satisfies EnvironmentOptions,\n      {\n        resolve: configEnvironmentsSsr.resolve ?? {},\n      },\n    ).resolve\n  }\n\n  if (config.build?.ssrEmitAssets !== undefined) {\n    configEnvironmentsSsr ??= {}\n    configEnvironmentsSsr.build ??= {}\n    configEnvironmentsSsr.build.emitAssets = config.build.ssrEmitAssets\n  }\n\n  // The client and ssr environment configs can't be removed by the user in the config hook\n  if (!config.environments.client || (!config.environments.ssr && !isBuild)) {\n    throw new Error(\n      'Required environments configuration were stripped out in the config hook',\n    )\n  }\n\n  // Merge default environment config values\n  const defaultEnvironmentOptions = getDefaultEnvironmentOptions(config)\n  // Some top level options only apply to the client environment\n  const defaultClientEnvironmentOptions: UserConfig = {\n    ...defaultEnvironmentOptions,\n    resolve: config.resolve, // inherit everything including mainFields and conditions\n    optimizeDeps: config.optimizeDeps,\n  }\n  const defaultNonClientEnvironmentOptions: UserConfig = {\n    ...defaultEnvironmentOptions,\n    dev: {\n      ...defaultEnvironmentOptions.dev,\n      createEnvironment: undefined,\n      warmup: undefined,\n    },\n    build: {\n      ...defaultEnvironmentOptions.build,\n      createEnvironment: undefined,\n    },\n  }\n\n  for (const name of Object.keys(config.environments)) {\n    config.environments[name] = mergeConfig(\n      name === 'client'\n        ? defaultClientEnvironmentOptions\n        : defaultNonClientEnvironmentOptions,\n      config.environments[name],\n    )\n  }\n\n  await runConfigEnvironmentHook(\n    config.environments,\n    userPlugins,\n    logger,\n    configEnv,\n    config.ssr?.target === 'webworker',\n  )\n\n  const isBundledDev = command === 'serve' && !!config.experimental?.bundledDev\n\n  // Backward compatibility: merge config.environments.client.resolve back into config.resolve\n  config.resolve ??= {}\n  config.resolve.conditions = config.environments.client.resolve?.conditions\n  config.resolve.mainFields = config.environments.client.resolve?.mainFields\n\n  const resolvedDefaultResolve = resolveResolveOptions(config.resolve, logger)\n\n  const resolvedEnvironments: Record<string, ResolvedEnvironmentOptions> = {}\n  for (const environmentName of Object.keys(config.environments)) {\n    resolvedEnvironments[environmentName] = resolveEnvironmentOptions(\n      config.environments[environmentName],\n      resolvedDefaultResolve.alias,\n      resolvedDefaultResolve.preserveSymlinks,\n      inlineConfig.forceOptimizeDeps,\n      logger,\n      environmentName,\n      isBundledDev,\n      config.ssr?.target === 'webworker',\n      config.server?.preTransformRequests,\n    )\n  }\n\n  // Backward compatibility: merge environments.client.optimizeDeps back into optimizeDeps\n  // The same object is assigned back for backward compatibility. The ecosystem is modifying\n  // optimizeDeps in the ResolvedConfig hook, so these changes will be reflected on the\n  // client environment.\n  const backwardCompatibleOptimizeDeps =\n    resolvedEnvironments.client.optimizeDeps\n\n  const resolvedDevEnvironmentOptions = resolveDevEnvironmentOptions(\n    config.dev,\n    // default environment options\n    undefined,\n    undefined,\n  )\n\n  const resolvedBuildOptions = resolveBuildEnvironmentOptions(\n    config.build ?? {},\n    logger,\n    undefined,\n    isBundledDev,\n  )\n\n  // Backward compatibility: merge config.environments.ssr back into config.ssr\n  // so ecosystem SSR plugins continue to work if only environments.ssr is configured\n  const patchedConfigSsr = {\n    ...config.ssr,\n    external: resolvedEnvironments.ssr?.resolve.external,\n    noExternal: resolvedEnvironments.ssr?.resolve.noExternal,\n    optimizeDeps: resolvedEnvironments.ssr?.optimizeDeps,\n    resolve: {\n      ...config.ssr?.resolve,\n      conditions: resolvedEnvironments.ssr?.resolve.conditions,\n      externalConditions: resolvedEnvironments.ssr?.resolve.externalConditions,\n    },\n  }\n  const ssr = resolveSSROptions(\n    patchedConfigSsr,\n    resolvedDefaultResolve.preserveSymlinks,\n  )\n\n  // load .env files\n  // Backward compatibility: set envDir to false when envFile is false\n  let envDir = config.envFile === false ? false : config.envDir\n  if (envDir !== false) {\n    envDir = config.envDir\n      ? normalizePath(path.resolve(resolvedRoot, config.envDir))\n      : resolvedRoot\n  }\n\n  const userEnv = loadEnv(mode, envDir, resolveEnvPrefix(config))\n\n  // Note it is possible for user to have a custom mode, e.g. `staging` where\n  // development-like behavior is expected. This is indicated by NODE_ENV=development\n  // loaded from `.staging.env` and set by us as VITE_USER_NODE_ENV\n  const userNodeEnv = process.env.VITE_USER_NODE_ENV\n  if (!isNodeEnvSet && userNodeEnv) {\n    if (userNodeEnv === 'development') {\n      process.env.NODE_ENV = 'development'\n    } else {\n      // NODE_ENV=production is not supported as it could break HMR in dev for frameworks like Vue\n      logger.warn(\n        `NODE_ENV=${userNodeEnv} is not supported in the .env file. ` +\n          `Only NODE_ENV=development is supported to create a development build of your project. ` +\n          `If you need to set process.env.NODE_ENV, you can set it in the Vite config instead.`,\n      )\n    }\n  }\n\n  const isProduction = process.env.NODE_ENV === 'production'\n\n  // resolve public base url\n  const relativeBaseShortcut = config.base === '' || config.base === './'\n\n  // During dev, we ignore relative base and fallback to '/'\n  // For the SSR build, relative base isn't possible by means\n  // of import.meta.url.\n  const resolvedBase = relativeBaseShortcut\n    ? !isBuild || config.build?.ssr\n      ? '/'\n      : './'\n    : resolveBaseUrl(config.base, isBuild, logger)\n\n  // resolve cache directory\n  const pkgDir = findNearestPackageData(resolvedRoot, packageCache)?.dir\n  const cacheDir = normalizePath(\n    config.cacheDir\n      ? path.resolve(resolvedRoot, config.cacheDir)\n      : pkgDir\n        ? path.join(pkgDir, `node_modules/.vite`)\n        : path.join(resolvedRoot, `.vite`),\n  )\n\n  const assetsFilter =\n    config.assetsInclude &&\n    (!Array.isArray(config.assetsInclude) || config.assetsInclude.length)\n      ? createFilter(config.assetsInclude)\n      : () => false\n\n  const { publicDir } = config\n  const resolvedPublicDir =\n    publicDir !== false && publicDir !== ''\n      ? normalizePath(\n          path.resolve(\n            resolvedRoot,\n            typeof publicDir === 'string'\n              ? publicDir\n              : configDefaults.publicDir,\n          ),\n        )\n      : ''\n\n  const server = await resolveServerOptions(resolvedRoot, config.server, logger)\n\n  const builder = resolveBuilderOptions(config.builder)\n\n  const BASE_URL = resolvedBase\n\n  const resolvedConfigContext = new BasicMinimalPluginContext(\n    {\n      ...basePluginContextMeta,\n      watchMode:\n        (command === 'serve' && !isPreview) ||\n        (command === 'build' && !!resolvedBuildOptions.watch),\n    } satisfies PluginContextMeta,\n    logger,\n  )\n\n  let resolved: ResolvedConfig\n\n  let createUserWorkerPlugins = config.worker?.plugins\n  if (Array.isArray(createUserWorkerPlugins)) {\n    // @ts-expect-error backward compatibility\n    createUserWorkerPlugins = () => config.worker?.plugins\n\n    logger.warn(\n      colors.yellow(\n        `worker.plugins is now a function that returns an array of plugins. ` +\n          `Please update your Vite config accordingly.\\n`,\n      ),\n    )\n  }\n\n  const createWorkerPlugins = async function (bundleChain: string[]) {\n    // Some plugins that aren't intended to work in the bundling of workers (doing post-processing at build time for example).\n    // And Plugins may also have cached that could be corrupted by being used in these extra rollup calls.\n    // So we need to separate the worker plugin from the plugin that vite needs to run.\n    const rawWorkerUserPlugins = (\n      await asyncFlatten(createUserWorkerPlugins?.() || [])\n    ).filter(filterPlugin)\n\n    // resolve worker\n    let workerConfig = mergeConfig({}, config)\n    const [workerPrePlugins, workerNormalPlugins, workerPostPlugins] =\n      sortUserPlugins(rawWorkerUserPlugins)\n\n    // run config hooks\n    const workerUserPlugins = [\n      ...workerPrePlugins,\n      ...workerNormalPlugins,\n      ...workerPostPlugins,\n    ]\n    workerConfig = await runConfigHook(\n      workerConfig,\n      workerUserPlugins,\n      configEnv,\n    )\n\n    const workerResolved: ResolvedConfig = {\n      ...workerConfig,\n      ...resolved,\n      isWorker: true,\n      mainConfig: resolved,\n      bundleChain,\n    }\n\n    // Plugins resolution needs the resolved config (minus plugins) so we need to mutate here\n    ;(workerResolved.plugins as Plugin[]) = await resolvePlugins(\n      workerResolved,\n      workerPrePlugins,\n      workerNormalPlugins,\n      workerPostPlugins,\n    )\n\n    // run configResolved hooks\n    await Promise.all(\n      createPluginHookUtils(workerResolved.plugins)\n        .getSortedPluginHooks('configResolved')\n        .map((hook) => hook.call(resolvedConfigContext, workerResolved)),\n    )\n\n    // Resolve environment plugins after configResolved because there are\n    // downstream projects modifying the plugins in it. This may change\n    // once the ecosystem is ready.\n    // During Build the client environment is used to bundle the worker\n    // Avoid overriding the mainConfig (resolved.environments.client)\n    ;(workerResolved.environments as Record<\n      string,\n      ResolvedEnvironmentOptions\n    >) = {\n      ...workerResolved.environments,\n      client: {\n        ...workerResolved.environments.client,\n        plugins: await resolveEnvironmentPlugins(\n          new PartialEnvironment('client', workerResolved),\n        ),\n      },\n    }\n\n    return workerResolved\n  }\n\n  const resolvedWorkerOptions: Omit<\n    ResolvedWorkerOptions,\n    'rolldownOptions'\n  > & {\n    rolldownOptions: ResolvedWorkerOptions['rolldownOptions'] | undefined\n  } = {\n    format: config.worker?.format || 'iife',\n    plugins: createWorkerPlugins,\n    rollupOptions: config.worker?.rollupOptions || {},\n    rolldownOptions: config.worker?.rolldownOptions, // will be set by setupRollupOptionCompat if undefined\n  }\n  setupRollupOptionCompat(resolvedWorkerOptions, 'worker')\n\n  const base = withTrailingSlash(resolvedBase)\n\n  const preview = resolvePreviewOptions(config.preview, server)\n\n  const additionalAllowedHosts = getAdditionalAllowedHosts(server, preview)\n  if (Array.isArray(server.allowedHosts)) {\n    server.allowedHosts.push(...additionalAllowedHosts)\n  }\n  if (Array.isArray(preview.allowedHosts)) {\n    preview.allowedHosts.push(...additionalAllowedHosts)\n  }\n\n  let oxc: OxcOptions | false | undefined = config.oxc\n  if (config.esbuild) {\n    if (config.oxc) {\n      logger.warn(\n        colors.yellow(\n          `Both esbuild and oxc options were set. oxc options will be used and esbuild options will be ignored.`,\n        ) +\n          ` The following esbuild options were set: \\`${inspect(config.esbuild)}\\``,\n      )\n    } else {\n      oxc = convertEsbuildConfigToOxcConfig(config.esbuild, logger)\n    }\n  } else if (config.esbuild === false && config.oxc !== false) {\n    logger.warn(\n      colors.yellow(\n        `\\`esbuild\\` option is set to false, but \\`oxc\\` option was not set to false. ` +\n          `\\`esbuild: false\\` does not have effect any more. ` +\n          `If you want to disable the default transformation, which is now handled by Oxc, please set \\`oxc: false\\` instead.`,\n      ),\n    )\n  }\n\n  const experimental = mergeWithDefaults(\n    configDefaults.experimental,\n    config.experimental ?? {},\n  )\n  if (command === 'serve' && experimental.bundledDev) {\n    // full bundle mode does not support experimental.renderBuiltUrl\n    experimental.renderBuiltUrl = undefined\n  }\n\n  const resolvedDevToolsConfig = await resolveDevToolsConfig(\n    config.devtools,\n    server.host,\n    logger,\n  )\n\n  resolved = {\n    configFile: configFile ? normalizePath(configFile) : undefined,\n    configFileDependencies: configFileDependencies.map((name) =>\n      normalizePath(path.resolve(name)),\n    ),\n    inlineConfig,\n    root: resolvedRoot,\n    base,\n    decodedBase: decodeBase(base),\n    rawBase: resolvedBase,\n    publicDir: resolvedPublicDir,\n    cacheDir,\n    command,\n    mode,\n    isBundled: config.experimental?.bundledDev || isBuild,\n    isWorker: false,\n    mainConfig: null,\n    bundleChain: [],\n    isProduction,\n    plugins: userPlugins, // placeholder to be replaced\n    css: resolveCSSOptions(config.css),\n    json: mergeWithDefaults(configDefaults.json, config.json ?? {}),\n    // preserve esbuild for buildEsbuildPlugin\n    esbuild:\n      config.esbuild === false\n        ? false\n        : {\n            jsxDev: !isProduction,\n            // change defaults that fit better for vite\n            charset: 'utf8',\n            legalComments: 'none',\n            ...config.esbuild,\n          },\n    oxc:\n      oxc === false\n        ? false\n        : {\n            ...oxc,\n            jsx:\n              typeof oxc?.jsx === 'string'\n                ? oxc.jsx\n                : {\n                    development: oxc?.jsx?.development ?? !isProduction,\n                    ...oxc?.jsx,\n                  },\n          },\n    server,\n    builder,\n    preview,\n    envDir,\n    env: {\n      ...userEnv,\n      BASE_URL,\n      MODE: mode,\n      DEV: !isProduction,\n      PROD: isProduction,\n    },\n    assetsInclude(file: string) {\n      return DEFAULT_ASSETS_RE.test(file) || assetsFilter(file)\n    },\n    rawAssetsInclude: config.assetsInclude ? arraify(config.assetsInclude) : [],\n    logger,\n    packageCache,\n    worker: resolvedWorkerOptions,\n    appType: config.appType ?? 'spa',\n    experimental,\n    future:\n      config.future === 'warn'\n        ? ({\n            removePluginHookHandleHotUpdate: 'warn',\n            removePluginHookSsrArgument: 'warn',\n            removeServerModuleGraph: 'warn',\n            removeServerReloadModule: 'warn',\n            removeServerPluginContainer: 'warn',\n            removeServerHot: 'warn',\n            removeServerTransformRequest: 'warn',\n            removeServerWarmupRequest: 'warn',\n            removeSsrLoadModule: 'warn',\n          } satisfies Required<FutureOptions>)\n        : config.future,\n\n    ssr,\n\n    optimizeDeps: backwardCompatibleOptimizeDeps,\n    resolve: resolvedDefaultResolve,\n    dev: resolvedDevEnvironmentOptions,\n    build: resolvedBuildOptions,\n    devtools: resolvedDevToolsConfig,\n\n    environments: resolvedEnvironments,\n\n    // random 72 bits (12 base64 chars)\n    // at least 64bits is recommended\n    // https://owasp.org/www-community/vulnerabilities/Insufficient_Session-ID_Length\n    webSocketToken: Buffer.from(\n      crypto.getRandomValues(new Uint8Array(9)),\n    ).toString('base64url'),\n\n    getSortedPlugins: undefined!,\n    getSortedPluginHooks: undefined!,\n\n    createResolver(options) {\n      const resolve = createIdResolver(this, options)\n      const clientEnvironment = new PartialEnvironment('client', this)\n      let ssrEnvironment: PartialEnvironment | undefined\n      return async (id, importer, aliasOnly, ssr) => {\n        if (ssr) {\n          ssrEnvironment ??= new PartialEnvironment('ssr', this)\n        }\n        return await resolve(\n          ssr ? ssrEnvironment! : clientEnvironment,\n          id,\n          importer,\n          aliasOnly,\n        )\n      }\n    },\n    fsDenyGlob: picomatch(\n      // matchBase: true does not work as it's documented\n      // https://github.com/micromatch/picomatch/issues/89\n      // convert patterns without `/` on our side for now\n      server.fs.deny.map((pattern) =>\n        pattern.includes('/') ? pattern : `**/${pattern}`,\n      ),\n      {\n        matchBase: false,\n        nocase: true,\n        dot: true,\n      },\n    ),\n    safeModulePaths: new Set<string>(),\n    [SYMBOL_RESOLVED_CONFIG]: true,\n  }\n  resolved = {\n    ...config,\n    ...resolved,\n  }\n\n  // Backward compatibility hook, modify the resolved config before it is used\n  // to create internal plugins. For example, `config.build.ssr`. Once we rework\n  // internal plugins to use environment.config, we can remove the dual\n  // patchConfig/patchPlugins and have a single patchConfig before configResolved\n  // gets called\n  patchConfig?.(resolved)\n\n  const resolvedPlugins = await resolvePlugins(\n    resolved,\n    prePlugins,\n    normalPlugins,\n    postPlugins,\n  )\n\n  // Backward compatibility hook used in builder, opt-in to shared plugins during build\n  patchPlugins?.(resolvedPlugins)\n  ;(resolved.plugins as Plugin[]) = resolvedPlugins\n\n  // TODO: Deprecate config.getSortedPlugins and config.getSortedPluginHooks\n  Object.assign(resolved, createPluginHookUtils(resolved.plugins))\n\n  // call configResolved hooks\n  await Promise.all(\n    resolved\n      .getSortedPluginHooks('configResolved')\n      .map((hook) => hook.call(resolvedConfigContext, resolved)),\n  )\n\n  // Resolve environment plugins after configResolved because there are\n  // downstream projects modifying the plugins in it. This may change\n  // once the ecosystem is ready.\n  for (const name of Object.keys(resolved.environments)) {\n    resolved.environments[name].plugins = await resolveEnvironmentPlugins(\n      new PartialEnvironment(name, resolved),\n    )\n  }\n\n  optimizeDepsDisabledBackwardCompatibility(resolved, resolved.optimizeDeps)\n  optimizeDepsDisabledBackwardCompatibility(\n    resolved,\n    resolved.ssr.optimizeDeps,\n    'ssr.',\n  )\n\n  // For backward compat, set ssr environment build.emitAssets with the same value as build.ssrEmitAssets that might be changed in configResolved hook\n  // https://github.com/vikejs/vike/blob/953614cea7b418fcc0309b5c918491889fdec90a/vike/node/plugin/plugins/buildConfig.ts#L67\n  if (!resolved.builder?.sharedConfigBuild && resolved.environments.ssr) {\n    resolved.environments.ssr.build.emitAssets =\n      resolved.build.ssrEmitAssets || resolved.build.emitAssets\n  }\n\n  // Enable `rolldownOptions.devtools` if devtools is enabled\n  if (resolved.devtools.enabled) {\n    resolved.build.rolldownOptions.devtools ??= {}\n  }\n\n  applyDepOptimizationOptionCompat(resolved)\n  await setOptimizeDepsPluginNames(resolved)\n\n  debug?.(`using resolved config: %O`, {\n    ...resolved,\n    plugins: resolved.plugins.map((p) => p.name),\n    worker: {\n      ...resolved.worker,\n      plugins: `() => plugins`,\n    },\n  })\n\n  // validate config\n\n  // Check if all assetFileNames have the same reference.\n  // If not, display a warn for user.\n  const outputOption = config.build?.rollupOptions?.output ?? []\n  // Use isArray to narrow its type to array\n  if (Array.isArray(outputOption)) {\n    const assetFileNamesList = outputOption.map(\n      (output) => output.assetFileNames,\n    )\n    if (assetFileNamesList.length > 1) {\n      const firstAssetFileNames = assetFileNamesList[0]\n      const hasDifferentReference = assetFileNamesList.some(\n        (assetFileNames) => assetFileNames !== firstAssetFileNames,\n      )\n      if (hasDifferentReference) {\n        resolved.logger.warn(\n          colors.yellow(`\nassetFileNames isn't equal for every build.rollupOptions.output. A single pattern across all outputs is supported by Vite.\n`),\n        )\n      }\n    }\n  }\n\n  // Warn about removal of experimental features\n  if (\n    // @ts-expect-error Option removed\n    config.legacy?.buildSsrCjsExternalHeuristics ||\n    // @ts-expect-error Option removed\n    config.ssr?.format === 'cjs'\n  ) {\n    resolved.logger.warn(\n      colors.yellow(`\n(!) Experimental legacy.buildSsrCjsExternalHeuristics and ssr.format were be removed in Vite 5.\n    The only SSR Output format is ESM. Find more information at https://github.com/vitejs/vite/discussions/13816.\n`),\n    )\n  }\n\n  const resolvedBuildOutDir = normalizePath(\n    path.resolve(resolved.root, resolved.build.outDir),\n  )\n  if (\n    isParentDirectory(resolvedBuildOutDir, resolved.root) ||\n    resolvedBuildOutDir === resolved.root\n  ) {\n    resolved.logger.warn(\n      colors.yellow(`\n(!) build.outDir must not be the same directory of root or a parent directory of root as this could cause Vite to overwriting source files with build outputs.\n`),\n    )\n  }\n\n  return resolved\n}\n\n/**\n * Resolve base url. Note that some users use Vite to build for non-web targets like\n * electron or expects to deploy\n */\nexport function resolveBaseUrl(\n  base: UserConfig['base'] = configDefaults.base,\n  isBuild: boolean,\n  logger: Logger,\n): string {\n  if (base[0] === '.') {\n    logger.warn(\n      colors.yellow(\n        colors.bold(\n          `(!) invalid \"base\" option: \"${base}\". The value can only be an absolute ` +\n            `URL, \"./\", or an empty string.`,\n        ),\n      ),\n    )\n    return '/'\n  }\n\n  // external URL flag\n  const isExternal = isExternalUrl(base)\n  // no leading slash warn\n  if (!isExternal && base[0] !== '/') {\n    logger.warn(\n      colors.yellow(\n        colors.bold(`(!) \"base\" option should start with a slash.`),\n      ),\n    )\n  }\n\n  // parse base when command is serve or base is not External URL\n  if (!isBuild || !isExternal) {\n    base = new URL(base, 'http://vite.dev').pathname\n    // ensure leading slash\n    if (base[0] !== '/') {\n      base = '/' + base\n    }\n  }\n\n  return base\n}\n\nfunction decodeBase(base: string): string {\n  try {\n    return decodeURI(base)\n  } catch {\n    throw new Error(\n      'The value passed to \"base\" option was malformed. It should be a valid URL.',\n    )\n  }\n}\n\nexport function sortUserPlugins(\n  plugins: (Plugin | Plugin[])[] | undefined,\n): [Plugin[], Plugin[], Plugin[]] {\n  const prePlugins: Plugin[] = []\n  const postPlugins: Plugin[] = []\n  const normalPlugins: Plugin[] = []\n\n  if (plugins) {\n    plugins.flat().forEach((p) => {\n      if (p.enforce === 'pre') prePlugins.push(p)\n      else if (p.enforce === 'post') postPlugins.push(p)\n      else normalPlugins.push(p)\n    })\n  }\n\n  return [prePlugins, normalPlugins, postPlugins]\n}\n\nexport async function loadConfigFromFile(\n  configEnv: ConfigEnv,\n  configFile?: string,\n  configRoot: string = process.cwd(),\n  logLevel?: LogLevel,\n  customLogger?: Logger,\n  configLoader: 'bundle' | 'runner' | 'native' = 'bundle',\n): Promise<{\n  path: string\n  config: UserConfig\n  dependencies: string[]\n} | null> {\n  if (\n    configLoader !== 'bundle' &&\n    configLoader !== 'runner' &&\n    configLoader !== 'native'\n  ) {\n    throw new Error(\n      `Unsupported configLoader: ${configLoader}. Accepted values are 'bundle', 'runner', and 'native'.`,\n    )\n  }\n\n  const start = performance.now()\n  const getTime = () => `${(performance.now() - start).toFixed(2)}ms`\n\n  let resolvedPath: string | undefined\n\n  if (configFile) {\n    // explicit config path is always resolved from cwd\n    resolvedPath = path.resolve(configFile)\n  } else {\n    // implicit config file loaded from inline root (if present)\n    // otherwise from cwd\n    for (const filename of DEFAULT_CONFIG_FILES) {\n      const filePath = path.resolve(configRoot, filename)\n      if (!fs.existsSync(filePath)) continue\n\n      resolvedPath = filePath\n      break\n    }\n  }\n\n  if (!resolvedPath) {\n    debug?.('no config file found.')\n    return null\n  }\n\n  try {\n    const resolver =\n      configLoader === 'bundle'\n        ? bundleAndLoadConfigFile\n        : configLoader === 'runner'\n          ? runnerImportConfigFile\n          : nativeImportConfigFile\n    const { configExport, dependencies } = await resolver(resolvedPath)\n    debug?.(`config file loaded in ${getTime()}`)\n\n    const config = await (typeof configExport === 'function'\n      ? configExport(configEnv)\n      : configExport)\n    if (!isObject(config)) {\n      throw new Error(`config must export or return an object.`)\n    }\n\n    return {\n      path: normalizePath(resolvedPath),\n      config,\n      dependencies,\n    }\n  } catch (e) {\n    const logger = createLogger(logLevel, { customLogger })\n    checkBadCharactersInPath('The config path', resolvedPath, logger)\n    logger.error(colors.red(`failed to load config from ${resolvedPath}`), {\n      error: e,\n    })\n    throw e\n  }\n}\n\nasync function nativeImportConfigFile(resolvedPath: string) {\n  const module = await import(\n    pathToFileURL(resolvedPath).href + '?t=' + Date.now()\n  )\n  return {\n    configExport: module.default,\n    dependencies: [],\n  }\n}\n\nasync function runnerImportConfigFile(resolvedPath: string) {\n  const { module, dependencies } = await runnerImport<{\n    default: UserConfigExport\n  }>(resolvedPath)\n  return {\n    configExport: module.default,\n    dependencies,\n  }\n}\n\nasync function bundleAndLoadConfigFile(resolvedPath: string) {\n  const isESM =\n    typeof process.versions.deno === 'string' || isFilePathESM(resolvedPath)\n\n  const bundled = await bundleConfigFile(resolvedPath, isESM)\n  const userConfig = await loadConfigFromBundledFile(\n    resolvedPath,\n    bundled.code,\n    isESM,\n  )\n\n  return {\n    configExport: userConfig,\n    dependencies: bundled.dependencies,\n  }\n}\n\nasync function bundleConfigFile(\n  fileName: string,\n  isESM: boolean,\n): Promise<{ code: string; dependencies: string[] }> {\n  let importMetaResolverRegistered = false\n\n  const root = path.dirname(fileName)\n  const dirnameVarName = '__vite_injected_original_dirname'\n  const filenameVarName = '__vite_injected_original_filename'\n  const importMetaUrlVarName = '__vite_injected_original_import_meta_url'\n  const importMetaResolveVarName =\n    '__vite_injected_original_import_meta_resolve'\n  const importMetaResolveRegex = /import\\.meta\\s*\\.\\s*resolve/\n\n  const bundle = await rolldown({\n    input: fileName,\n    // target: [`node${process.versions.node}`],\n    platform: 'node',\n    resolve: {\n      mainFields: ['main'],\n    },\n    transform: {\n      define: {\n        __dirname: dirnameVarName,\n        __filename: filenameVarName,\n        'import.meta.url': importMetaUrlVarName,\n        'import.meta.dirname': dirnameVarName,\n        'import.meta.filename': filenameVarName,\n        'import.meta.resolve': importMetaResolveVarName,\n        'import.meta.main': 'false',\n      },\n    },\n    // disable treeshake to include files that is not sideeffectful to `moduleIds`\n    treeshake: false,\n    // disable tsconfig as it's confusing to respect tsconfig options in the config file\n    // this also aligns with other config loader behaviors\n    tsconfig: false,\n    plugins: [\n      {\n        name: 'externalize-deps',\n        resolveId: {\n          filter: { id: /^[^.#].*/ },\n          async handler(id, importer, { kind }) {\n            if (!importer || path.isAbsolute(id) || isNodeBuiltin(id)) {\n              return\n            }\n\n            // With the `isNodeBuiltin` check above, this check captures if the builtin is a\n            // non-node built-in, which esbuild doesn't know how to handle. In that case, we\n            // externalize it so the non-node runtime handles it instead.\n            if (isNodeLikeBuiltin(id) || id.startsWith('npm:')) {\n              return { id, external: true }\n            }\n\n            const isImport = isESM || kind === 'dynamic-import'\n            let idFsPath: string | undefined\n            try {\n              idFsPath = nodeResolveWithVite(id, importer, {\n                root,\n                isRequire: !isImport,\n              })\n            } catch (e) {\n              if (!isImport) {\n                let canResolveWithImport = false\n                try {\n                  canResolveWithImport = !!nodeResolveWithVite(id, importer, {\n                    root,\n                  })\n                } catch {}\n                if (canResolveWithImport) {\n                  throw new Error(\n                    `Failed to resolve ${JSON.stringify(\n                      id,\n                    )}. This package is ESM only but it was tried to load by \\`require\\`. See https://vite.dev/guide/troubleshooting.html#this-package-is-esm-only for more details.`,\n                  )\n                }\n              }\n              throw e\n            }\n            if (!idFsPath) return\n            // always no-externalize json files as rolldown does not support import attributes\n            if (idFsPath.endsWith('.json')) {\n              return idFsPath\n            }\n\n            if (idFsPath && isImport) {\n              idFsPath = pathToFileURL(idFsPath).href\n            }\n            return { id: idFsPath, external: true }\n          },\n        },\n      },\n      {\n        name: 'inject-file-scope-variables',\n        transform: {\n          filter: { id: /\\.[cm]?[jt]s$/ },\n          handler(code, id) {\n            let injectValues =\n              `const ${dirnameVarName} = ${JSON.stringify(path.dirname(id))};` +\n              `const ${filenameVarName} = ${JSON.stringify(id)};` +\n              `const ${importMetaUrlVarName} = ${JSON.stringify(\n                pathToFileURL(id).href,\n              )};`\n            if (importMetaResolveRegex.test(code)) {\n              if (isESM) {\n                if (!importMetaResolverRegistered) {\n                  importMetaResolverRegistered = true\n                  createImportMetaResolver()\n                }\n                injectValues += `const ${importMetaResolveVarName} = (specifier, importer = ${importMetaUrlVarName}) => (${importMetaResolveWithCustomHookString})(specifier, importer);`\n              } else {\n                injectValues += `const ${importMetaResolveVarName} = (specifier, importer = ${importMetaUrlVarName}) => { throw new Error('import.meta.resolve is not supported in CJS config files') };`\n              }\n            }\n\n            let injectedContents: string\n            if (code.startsWith('#!')) {\n              // hashbang\n              let firstLineEndIndex = code.indexOf('\\n')\n              if (firstLineEndIndex < 0) firstLineEndIndex = code.length\n              injectedContents =\n                code.slice(0, firstLineEndIndex + 1) +\n                injectValues +\n                code.slice(firstLineEndIndex + 1)\n            } else {\n              injectedContents = injectValues + code\n            }\n\n            return {\n              code: injectedContents,\n              map: null,\n            }\n          },\n        },\n      },\n    ],\n  })\n  const result = await bundle.generate({\n    format: isESM ? 'esm' : 'cjs',\n    sourcemap: 'inline',\n    sourcemapPathTransform(relative) {\n      return path.resolve(fileName, relative)\n    },\n    // we want to generate a single chunk like esbuild does with `splitting: false`\n    codeSplitting: false,\n  })\n  await bundle.close()\n\n  const entryChunk = result.output.find(\n    (chunk): chunk is OutputChunk => chunk.type === 'chunk' && chunk.isEntry,\n  )!\n  const bundleChunks = Object.fromEntries(\n    result.output.flatMap((c) => (c.type === 'chunk' ? [[c.fileName, c]] : [])),\n  )\n\n  const allModules = new Set<string>()\n  collectAllModules(bundleChunks, entryChunk.fileName, allModules)\n\n  return {\n    code: entryChunk.code,\n    // exclude `\\x00rolldown/runtime.js`\n    dependencies: [...allModules].filter((m) => !m.startsWith('\\0')),\n  }\n}\n\nfunction collectAllModules(\n  bundle: Record<string, OutputChunk>,\n  fileName: string,\n  allModules: Set<string>,\n  analyzedModules = new Set<string>(),\n) {\n  if (analyzedModules.has(fileName)) return\n  analyzedModules.add(fileName)\n\n  const chunk = bundle[fileName]!\n  for (const mod of chunk.moduleIds) {\n    allModules.add(mod)\n  }\n  for (const i of chunk.imports) {\n    analyzedModules.add(i)\n    collectAllModules(bundle, i, allModules, analyzedModules)\n  }\n  for (const i of chunk.dynamicImports) {\n    analyzedModules.add(i)\n    collectAllModules(bundle, i, allModules, analyzedModules)\n  }\n}\n\ninterface NodeModuleWithCompile extends NodeModule {\n  _compile(code: string, filename: string): any\n}\n\nconst _require = createRequire(/** #__KEEP__ */ import.meta.url)\nasync function loadConfigFromBundledFile(\n  fileName: string,\n  bundledCode: string,\n  isESM: boolean,\n): Promise<UserConfigExport> {\n  // for esm, before we can register loaders without requiring users to run node\n  // with --experimental-loader themselves, we have to do a hack here:\n  // write it to disk, load it with native Node ESM, then delete the file.\n  if (isESM) {\n    // Storing the bundled file in node_modules/ is avoided for Deno\n    // because Deno only supports Node.js style modules under node_modules/\n    // and configs with `npm:` import statements will fail when executed.\n    let nodeModulesDir =\n      typeof process.versions.deno === 'string'\n        ? undefined\n        : findNearestNodeModules(path.dirname(fileName))\n    if (nodeModulesDir) {\n      try {\n        await fsp.mkdir(path.resolve(nodeModulesDir, '.vite-temp/'), {\n          recursive: true,\n        })\n      } catch (e) {\n        if (e.code === 'EACCES') {\n          // If there is no access permission, a temporary configuration file is created by default.\n          nodeModulesDir = undefined\n        } else {\n          throw e\n        }\n      }\n    }\n    const hash = `timestamp-${Date.now()}-${Math.random().toString(16).slice(2)}`\n    const tempFileName = nodeModulesDir\n      ? path.resolve(\n          nodeModulesDir,\n          `.vite-temp/${path.basename(fileName)}.${hash}.mjs`,\n        )\n      : `${fileName}.${hash}.mjs`\n    await fsp.writeFile(tempFileName, bundledCode)\n    try {\n      return (await import(pathToFileURL(tempFileName).href)).default\n    } finally {\n      fs.unlink(tempFileName, () => {}) // Ignore errors\n    }\n  }\n  // for cjs, we can register a custom loader via `_require.extensions`\n  else {\n    const extension = path.extname(fileName)\n    // We don't use fsp.realpath() here because it has the same behaviour as\n    // fs.realpath.native. On some Windows systems, it returns uppercase volume\n    // letters (e.g. \"C:\\\") while the Node.js loader uses lowercase volume letters.\n    // See https://github.com/vitejs/vite/issues/12923\n    const realFileName = await promisifiedRealpath(fileName)\n    const loaderExt = extension in _require.extensions ? extension : '.js'\n    const defaultLoader = _require.extensions[loaderExt]!\n    _require.extensions[loaderExt] = (module: NodeModule, filename: string) => {\n      if (filename === realFileName) {\n        ;(module as NodeModuleWithCompile)._compile(bundledCode, filename)\n      } else {\n        defaultLoader(module, filename)\n      }\n    }\n    // clear cache in case of server restart\n    delete _require.cache[_require.resolve(fileName)]\n    const raw = _require(fileName)\n    _require.extensions[loaderExt] = defaultLoader\n    return raw.__esModule ? raw.default : raw\n  }\n}\n\nasync function runConfigHook(\n  config: InlineConfig,\n  plugins: Plugin[],\n  configEnv: ConfigEnv,\n): Promise<InlineConfig> {\n  let conf = config\n\n  const tempLogger = createLogger(config.logLevel, {\n    allowClearScreen: config.clearScreen,\n    customLogger: config.customLogger,\n  })\n  const context = new BasicMinimalPluginContext<\n    Omit<PluginContextMeta, 'watchMode'>\n  >(basePluginContextMeta, tempLogger)\n\n  for (const p of getSortedPluginsByHook('config', plugins)) {\n    const hook = p.config\n    const handler = getHookHandler(hook)\n    const res = await handler.call(context, conf, configEnv)\n    if (res && res !== conf) {\n      if (hasBothRollupOptionsAndRolldownOptions(res)) {\n        context.warn(\n          `Both \\`rollupOptions\\` and \\`rolldownOptions\\` were specified by ${JSON.stringify(p.name)} plugin. ` +\n            `\\`rollupOptions\\` specified by that plugin will be ignored.`,\n        )\n      }\n      if (res.esbuild) {\n        context.warn(\n          `\\`esbuild\\` option was specified by ${JSON.stringify(p.name)} plugin. ` +\n            `This option is deprecated, please use \\`oxc\\` instead.`,\n        )\n      }\n      if (res.optimizeDeps?.esbuildOptions) {\n        context.warn(\n          `\\`optimizeDeps.esbuildOptions\\` option was specified by ${JSON.stringify(p.name)} plugin. ` +\n            `This option is deprecated, please use \\`optimizeDeps.rolldownOptions\\` instead.`,\n        )\n      }\n      conf = mergeConfig(conf, res)\n    }\n  }\n\n  return conf\n}\n\nasync function runConfigEnvironmentHook(\n  environments: Record<string, EnvironmentOptions>,\n  plugins: Plugin[],\n  logger: Logger,\n  configEnv: ConfigEnv,\n  isSsrTargetWebworkerSet: boolean,\n): Promise<void> {\n  const context = new BasicMinimalPluginContext<\n    Omit<PluginContextMeta, 'watchMode'>\n  >(basePluginContextMeta, logger)\n\n  const environmentNames = Object.keys(environments)\n  for (const p of getSortedPluginsByHook('configEnvironment', plugins)) {\n    const hook = p.configEnvironment\n    const handler = getHookHandler(hook)\n    for (const name of environmentNames) {\n      const res = await handler.call(context, name, environments[name], {\n        ...configEnv,\n        isSsrTargetWebworker: isSsrTargetWebworkerSet && name === 'ssr',\n      })\n      if (res) {\n        environments[name] = mergeConfig(environments[name], res)\n      }\n    }\n  }\n}\n\nfunction optimizeDepsDisabledBackwardCompatibility(\n  resolved: ResolvedConfig,\n  optimizeDeps: DepOptimizationOptions,\n  optimizeDepsPath: string = '',\n) {\n  const optimizeDepsDisabled = optimizeDeps.disabled\n  if (optimizeDepsDisabled !== undefined) {\n    if (optimizeDepsDisabled === true || optimizeDepsDisabled === 'dev') {\n      const commonjsOptionsInclude = resolved.build.commonjsOptions.include\n      const commonjsPluginDisabled =\n        Array.isArray(commonjsOptionsInclude) &&\n        commonjsOptionsInclude.length === 0\n      optimizeDeps.noDiscovery = true\n      optimizeDeps.include = undefined\n      if (commonjsPluginDisabled) {\n        resolved.build.commonjsOptions.include = undefined\n      }\n      resolved.logger.warn(\n        colors.yellow(`(!) Experimental ${optimizeDepsPath}optimizeDeps.disabled and deps pre-bundling during build were removed in Vite 5.1.\n    To disable the deps optimizer, set ${optimizeDepsPath}optimizeDeps.noDiscovery to true and ${optimizeDepsPath}optimizeDeps.include as undefined or empty.\n    Please remove ${optimizeDepsPath}optimizeDeps.disabled from your config.\n    ${\n      commonjsPluginDisabled\n        ? 'Empty config.build.commonjsOptions.include will be ignored to support CJS during build. This config should also be removed.'\n        : ''\n    }\n  `),\n      )\n    } else if (\n      optimizeDepsDisabled === false ||\n      optimizeDepsDisabled === 'build'\n    ) {\n      resolved.logger.warn(\n        colors.yellow(`(!) Experimental ${optimizeDepsPath}optimizeDeps.disabled and deps pre-bundling during build were removed in Vite 5.1.\n    Setting it to ${optimizeDepsDisabled} now has no effect.\n    Please remove ${optimizeDepsPath}optimizeDeps.disabled from your config.\n  `),\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/constants.ts",
    "content": "import path, { resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { readFileSync } from 'node:fs'\nimport type { RollupPluginHooks } from './typeUtils'\n\nconst { version } = JSON.parse(\n  readFileSync(new URL('../../package.json', import.meta.url)).toString(),\n)\n\nexport const ROLLUP_HOOKS: RollupPluginHooks[] = [\n  'options',\n  'buildStart',\n  'buildEnd',\n  'renderStart',\n  'renderError',\n  'renderChunk',\n  'writeBundle',\n  'generateBundle',\n  'banner',\n  'footer',\n  'augmentChunkHash',\n  'outputOptions',\n  // 'renderDynamicImport',\n  // 'resolveFileUrl',\n  // 'resolveImportMeta',\n  'intro',\n  'outro',\n  'closeBundle',\n  'closeWatcher',\n  'load',\n  'moduleParsed',\n  'watchChange',\n  'resolveDynamicImport',\n  'resolveId',\n  // 'shouldTransformCachedModule',\n  'transform',\n  'onLog',\n]\n\nexport const VERSION = version as string\n\nconst DEFAULT_MAIN_FIELDS = [\n  'browser',\n  'module',\n  'jsnext:main', // moment still uses this...\n  'jsnext',\n]\nexport const DEFAULT_CLIENT_MAIN_FIELDS: readonly string[] =\n  Object.freeze(DEFAULT_MAIN_FIELDS)\nexport const DEFAULT_SERVER_MAIN_FIELDS: readonly string[] = Object.freeze(\n  DEFAULT_MAIN_FIELDS.filter((f) => f !== 'browser'),\n)\n\n/**\n * A special condition that would be replaced with production or development\n * depending on NODE_ENV env variable\n */\nexport const DEV_PROD_CONDITION = `development|production` as const\n\nconst DEFAULT_CONDITIONS = ['module', 'browser', 'node', DEV_PROD_CONDITION]\nexport const DEFAULT_CLIENT_CONDITIONS: readonly string[] = Object.freeze(\n  DEFAULT_CONDITIONS.filter((c) => c !== 'node'),\n)\nexport const DEFAULT_SERVER_CONDITIONS: readonly string[] = Object.freeze(\n  DEFAULT_CONDITIONS.filter((c) => c !== 'browser'),\n)\n\nexport const DEFAULT_EXTERNAL_CONDITIONS: readonly string[] = Object.freeze([\n  'node',\n  'module-sync',\n])\n\nexport const DEFAULT_EXTENSIONS: string[] = [\n  '.mjs',\n  '.js',\n  '.mts',\n  '.ts',\n  '.jsx',\n  '.tsx',\n  '.json',\n]\n\n/**\n * The browser versions that are included in the Baseline Widely Available on 2025-05-01.\n *\n * This value would be bumped on each major release of Vite.\n *\n * The value is generated by `pnpm generate-target` script.\n */\nexport const ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET: string[] = [\n  'chrome111',\n  'edge111',\n  'firefox114',\n  'safari16.4',\n  'ios16.4',\n]\n\nexport const DEFAULT_CONFIG_FILES: string[] = [\n  'vite.config.js',\n  'vite.config.mjs',\n  'vite.config.ts',\n  'vite.config.cjs',\n  'vite.config.mts',\n  'vite.config.cts',\n]\n\nexport const JS_TYPES_RE: RegExp = /\\.(?:j|t)sx?$|\\.mjs$/\n\nexport const CSS_LANGS_RE: RegExp =\n  /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/\n\nexport const OPTIMIZABLE_ENTRY_RE: RegExp = /\\.[cm]?[jt]s$/\n\nexport const SPECIAL_QUERY_RE: RegExp = /[?&](?:worker|sharedworker|raw|url)\\b/\n\n/**\n * Prefix for resolved fs paths, since windows paths may not be valid as URLs.\n */\nexport const FS_PREFIX = `/@fs/`\n\nexport const CLIENT_PUBLIC_PATH = `/@vite/client`\nexport const ENV_PUBLIC_PATH = `/@vite/env`\nexport const VITE_PACKAGE_DIR: string = resolve(\n  fileURLToPath(import.meta.url),\n  '../../..',\n)\n\nexport const CLIENT_ENTRY: string = resolve(\n  VITE_PACKAGE_DIR,\n  'dist/client/client.mjs',\n)\nexport const ENV_ENTRY: string = resolve(\n  VITE_PACKAGE_DIR,\n  'dist/client/env.mjs',\n)\nexport const CLIENT_DIR: string = path.dirname(CLIENT_ENTRY)\n\n// ** READ THIS ** before editing `KNOWN_ASSET_TYPES`.\n//   If you add an asset to `KNOWN_ASSET_TYPES`, make sure to also add it\n//   to the TypeScript declaration file `packages/vite/client.d.ts` and\n//   add a mime type to the `registerCustomMime` in\n//   `packages/vite/src/node/plugin/assets.ts` if mime type cannot be\n//   looked up by mrmime.\n//   You can check if the mime type can be looked up by mrmime by running\n//   `node --print \"require('mrmime').lookup('foo.png')\"`\nexport const KNOWN_ASSET_TYPES: string[] = [\n  // images\n  'apng',\n  'bmp',\n  'png',\n  'jpe?g',\n  'jfif',\n  'pjpeg',\n  'pjp',\n  'gif',\n  'svg',\n  'ico',\n  'webp',\n  'avif',\n  'cur',\n  'jxl',\n\n  // media\n  'mp4',\n  'webm',\n  'ogg',\n  'mp3',\n  'wav',\n  'flac',\n  'aac',\n  'opus',\n  'mov',\n  'm4a',\n  'vtt',\n\n  // fonts\n  'woff2?',\n  'eot',\n  'ttf',\n  'otf',\n\n  // other\n  'webmanifest',\n  'pdf',\n  'txt',\n]\n\nexport const DEFAULT_ASSETS_RE: RegExp = new RegExp(\n  `\\\\.(` + KNOWN_ASSET_TYPES.join('|') + `)(\\\\?.*)?$`,\n  'i',\n)\n\nexport const DEP_VERSION_RE: RegExp = /[?&](v=[\\w.-]+)\\b/\n\nexport const loopbackHosts: Set<string> = new Set([\n  'localhost',\n  '127.0.0.1',\n  '::1',\n  '0000:0000:0000:0000:0000:0000:0000:0001',\n])\nexport const wildcardHosts: Set<string> = new Set([\n  '0.0.0.0',\n  '::',\n  '0000:0000:0000:0000:0000:0000:0000:0000',\n])\n\nexport const DEFAULT_DEV_PORT = 5173\n\nexport const DEFAULT_PREVIEW_PORT = 4173\n\nexport const DEFAULT_ASSETS_INLINE_LIMIT = 4096\n\n// the regex to allow loopback address origins:\n// - localhost domains (which will always resolve to the loopback address by RFC 6761 section 6.3)\n// - 127.0.0.1\n// - ::1\nexport const defaultAllowedOrigins: RegExp =\n  /^https?:\\/\\/(?:(?:[^:]+\\.)?localhost|127\\.0\\.0\\.1|\\[::1\\])(?::\\d+)?$/\n\nexport const METADATA_FILENAME = '_metadata.json'\n\nexport const ERR_OPTIMIZE_DEPS_PROCESSING_ERROR =\n  'ERR_OPTIMIZE_DEPS_PROCESSING_ERROR'\nexport const ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR =\n  'ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR'\n"
  },
  {
    "path": "packages/vite/src/node/deprecations.ts",
    "content": "import colors from 'picocolors'\nimport type { FutureOptions, ResolvedConfig } from './config'\n\nconst docsURL = 'https://vite.dev'\n\nconst deprecationCode = {\n  removePluginHookSsrArgument: 'this-environment-in-hooks',\n  removePluginHookHandleHotUpdate: 'hotupdate-hook',\n\n  removeServerModuleGraph: 'per-environment-apis',\n  removeServerReloadModule: 'per-environment-apis',\n  removeServerPluginContainer: 'per-environment-apis',\n  removeServerHot: 'per-environment-apis',\n  removeServerTransformRequest: 'per-environment-apis',\n  removeServerWarmupRequest: 'per-environment-apis',\n\n  removeSsrLoadModule: 'ssr-using-modulerunner',\n} satisfies Record<keyof FutureOptions, string>\n\nconst deprecationMessages = {\n  removePluginHookSsrArgument:\n    \"Plugin hook `options.ssr` is replaced with `this.environment.config.consumer === 'server'`.\",\n  removePluginHookHandleHotUpdate:\n    'Plugin hook `handleHotUpdate()` is replaced with `hotUpdate()`.',\n\n  removeServerModuleGraph:\n    'The `server.moduleGraph` is replaced with `this.environment.moduleGraph`.',\n  removeServerReloadModule:\n    'The `server.reloadModule` is replaced with `environment.reloadModule`.',\n  removeServerPluginContainer:\n    'The `server.pluginContainer` is replaced with `this.environment.pluginContainer`.',\n  removeServerHot: 'The `server.hot` is replaced with `this.environment.hot`.',\n  removeServerTransformRequest:\n    'The `server.transformRequest` is replaced with `this.environment.transformRequest`.',\n  removeServerWarmupRequest:\n    'The `server.warmupRequest` is replaced with `this.environment.warmupRequest`.',\n\n  removeSsrLoadModule:\n    'The `server.ssrLoadModule` is replaced with Environment Runner.',\n} satisfies Record<keyof FutureOptions, string>\n\nlet _ignoreDeprecationWarnings = false\n\nexport function isFutureDeprecationEnabled(\n  config: ResolvedConfig,\n  type: keyof FutureOptions,\n): boolean {\n  return !!config.future?.[type]\n}\n\n// Later we could have a `warnDeprecation` utils when the deprecation is landed\n/**\n * Warn about future deprecations.\n */\nexport function warnFutureDeprecation(\n  config: ResolvedConfig,\n  type: keyof FutureOptions,\n  extraMessage?: string,\n  stacktrace = true,\n): void {\n  if (\n    _ignoreDeprecationWarnings ||\n    !config.future ||\n    config.future[type] !== 'warn'\n  )\n    return\n\n  let msg = `[vite future] ${deprecationMessages[type]}`\n  if (extraMessage) {\n    msg += ` ${extraMessage}`\n  }\n  msg = colors.yellow(msg)\n\n  const docs = `${docsURL}/changes/${deprecationCode[type].toLowerCase()}`\n  msg +=\n    colors.gray(`\\n  ${stacktrace ? '├' : '└'}─── `) +\n    colors.underline(docs) +\n    '\\n'\n\n  if (stacktrace) {\n    const stack = new Error().stack\n    if (stack) {\n      let stacks = stack\n        .split('\\n')\n        .slice(3)\n        .filter((i) => !i.includes('/node_modules/vite/dist/'))\n      if (stacks.length === 0) {\n        stacks.push('No stack trace found.')\n      }\n      stacks = stacks.map(\n        (i, idx) => `  ${idx === stacks.length - 1 ? '└' : '│'} ${i.trim()}`,\n      )\n      msg += colors.dim(stacks.join('\\n')) + '\\n'\n    }\n  }\n  config.logger.warnOnce(msg)\n}\n\nexport function ignoreDeprecationWarnings<T>(fn: () => T): T {\n  const before = _ignoreDeprecationWarnings\n  _ignoreDeprecationWarnings = true\n  const ret = fn()\n  _ignoreDeprecationWarnings = before\n  return ret\n}\n"
  },
  {
    "path": "packages/vite/src/node/env.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { parseEnv } from 'node:util'\nimport { type DotenvPopulateInput, expand } from 'dotenv-expand'\nimport colors from 'picocolors'\nimport { arraify, createDebugger, normalizePath, tryStatSync } from './utils'\nimport type { UserConfig } from './config'\n\nconst debug = createDebugger('vite:env')\n\nexport function getEnvFilesForMode(\n  mode: string,\n  envDir: string | false,\n): string[] {\n  if (envDir !== false) {\n    return [\n      /** default file */ `.env`,\n      /** local file */ `.env.local`,\n      /** mode file */ `.env.${mode}`,\n      /** mode local file */ `.env.${mode}.local`,\n    ].map((file) => normalizePath(path.join(envDir, file)))\n  }\n\n  return []\n}\n\nexport function loadEnv(\n  mode: string,\n  envDir: string | false,\n  prefixes: string | string[] = 'VITE_',\n): Record<string, string> {\n  const start = performance.now()\n  const getTime = () => `${(performance.now() - start).toFixed(2)}ms`\n\n  if (mode === 'local') {\n    throw new Error(\n      `\"local\" cannot be used as a mode name because it conflicts with ` +\n        `the .local postfix for .env files.`,\n    )\n  }\n  prefixes = arraify(prefixes)\n  const env: Record<string, string> = {}\n  const envFiles = getEnvFilesForMode(mode, envDir)\n\n  debug?.(`loading env files: %O`, envFiles)\n\n  const parsed = Object.fromEntries(\n    envFiles.flatMap((filePath) => {\n      const stat = tryStatSync(filePath)\n      // Support FIFOs (named pipes) for apps like 1Password\n      if (!stat || (!stat.isFile() && !stat.isFIFO())) return []\n\n      const parsedEnv = parseEnv(fs.readFileSync(filePath, 'utf-8'))\n      return Object.entries(parsedEnv as Record<string, string>)\n    }),\n  )\n\n  debug?.(`env files loaded in ${getTime()}`)\n\n  // test NODE_ENV override before expand as otherwise process.env.NODE_ENV would override this\n  if (parsed.NODE_ENV && process.env.VITE_USER_NODE_ENV === undefined) {\n    process.env.VITE_USER_NODE_ENV = parsed.NODE_ENV\n  }\n  // support BROWSER and BROWSER_ARGS env variables\n  if (parsed.BROWSER && process.env.BROWSER === undefined) {\n    process.env.BROWSER = parsed.BROWSER\n  }\n  if (parsed.BROWSER_ARGS && process.env.BROWSER_ARGS === undefined) {\n    process.env.BROWSER_ARGS = parsed.BROWSER_ARGS\n  }\n\n  // let environment variables use each other. make a copy of `process.env` so that `dotenv-expand`\n  // doesn't re-assign the expanded values to the global `process.env`.\n  const processEnv = { ...process.env } as DotenvPopulateInput\n  expand({ parsed, processEnv })\n\n  // only keys that start with prefix are exposed to client\n  for (const [key, value] of Object.entries(parsed)) {\n    if (prefixes.some((prefix) => key.startsWith(prefix))) {\n      env[key] = value\n    }\n  }\n\n  // check if there are actual env variables starting with VITE_*\n  // these are typically provided inline and should be prioritized\n  for (const key in process.env) {\n    if (prefixes.some((prefix) => key.startsWith(prefix))) {\n      env[key] = process.env[key] as string\n    }\n  }\n\n  debug?.(`using resolved env: %O`, env)\n\n  return env\n}\n\nexport function resolveEnvPrefix({\n  envPrefix = 'VITE_',\n}: UserConfig): string[] {\n  envPrefix = arraify(envPrefix)\n  if (envPrefix.includes('')) {\n    throw new Error(\n      `envPrefix option contains value '', which could lead unexpected exposure of sensitive information.`,\n    )\n  }\n  if (envPrefix.some((prefix) => /\\s/.test(prefix))) {\n    // eslint-disable-next-line no-console\n    console.warn(\n      colors.yellow(\n        `[vite] Warning: envPrefix option contains values with whitespace, which does not work in practice.`,\n      ),\n    )\n  }\n  return envPrefix\n}\n"
  },
  {
    "path": "packages/vite/src/node/environment.ts",
    "content": "import type { PluginContext } from 'rolldown'\nimport type { DevEnvironment } from './server/environment'\nimport type { BuildEnvironment } from './build'\nimport type { ScanEnvironment } from './optimizer/scan'\nimport type { UnknownEnvironment } from './baseEnvironment'\n\nexport type Environment =\n  | DevEnvironment\n  | BuildEnvironment\n  | /** @internal */ ScanEnvironment\n  | UnknownEnvironment\n\n/**\n * Creates a function that hides the complexities of a WeakMap with an initial value\n * to implement object metadata. Used by plugins to implement cross hooks per\n * environment metadata\n *\n * @experimental\n */\nexport function perEnvironmentState<State>(\n  initial: (environment: Environment) => State,\n): (context: PluginContext) => State {\n  const stateMap = new WeakMap<Environment, State>()\n  return function (context: PluginContext) {\n    const { environment } = context\n    let state = stateMap.get(environment)\n    if (!state) {\n      state = initial(environment)\n      stateMap.set(environment, state)\n    }\n    return state\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/external.ts",
    "content": "import path from 'node:path'\nimport type { InternalResolveOptions } from './plugins/resolve'\nimport { tryNodeResolve } from './plugins/resolve'\nimport {\n  bareImportRE,\n  createDebugger,\n  createFilter,\n  getNpmPackageName,\n  isBuiltin,\n  isInNodeModules,\n} from './utils'\nimport type { Environment } from './environment'\nimport type { PartialEnvironment } from './baseEnvironment'\n\nconst debug = createDebugger('vite:external')\n\nconst isExternalCache = new WeakMap<\n  Environment,\n  (id: string, importer?: string) => boolean\n>()\n\nexport function shouldExternalize(\n  environment: Environment,\n  id: string,\n  importer: string | undefined,\n): boolean {\n  let isExternal = isExternalCache.get(environment)\n  if (!isExternal) {\n    isExternal = createIsExternal(environment)\n    isExternalCache.set(environment, isExternal)\n  }\n  return isExternal(id, importer)\n}\n\nexport function createIsConfiguredAsExternal(\n  environment: PartialEnvironment,\n): (id: string, importer?: string) => boolean {\n  const { config } = environment\n  const { root, resolve } = config\n  const { external, noExternal } = resolve\n  const noExternalFilter =\n    typeof noExternal !== 'boolean' &&\n    !(Array.isArray(noExternal) && noExternal.length === 0) &&\n    createFilter(undefined, noExternal, { resolve: false })\n\n  const targetConditions = resolve.externalConditions\n\n  const resolveOptions: InternalResolveOptions = {\n    ...resolve,\n    root,\n    isProduction: false,\n    isBuild: true,\n    conditions: targetConditions,\n  }\n\n  const isExternalizable = (\n    id: string,\n    importer: string | undefined,\n    configuredAsExternal: boolean,\n  ): boolean => {\n    if (!bareImportRE.test(id) || id.includes('\\0')) {\n      return false\n    }\n    try {\n      const resolved = tryNodeResolve(\n        id,\n        // Skip passing importer in build to avoid externalizing non-hoisted dependencies\n        // unresolvable from root (which would be unresolvable from output bundles also)\n        config.command === 'build' ? undefined : importer,\n        resolveOptions,\n        undefined,\n        false,\n      )\n      if (!resolved) {\n        return false\n      }\n      // Only allow linked packages to be externalized\n      // if they are explicitly configured as external\n      if (!configuredAsExternal && !isInNodeModules(resolved.id)) {\n        return false\n      }\n      return canExternalizeFile(resolved.id)\n    } catch {\n      debug?.(\n        `Failed to node resolve \"${id}\". Skipping externalizing it by default.`,\n      )\n      // may be an invalid import that's resolved by a plugin\n      return false\n    }\n  }\n\n  // Returns true if it is configured as external, false if it is filtered\n  // by noExternal and undefined if it isn't affected by the explicit config\n  return (id: string, importer?: string) => {\n    if (\n      // If this id is defined as external, force it as external\n      // Note that individual package entries are allowed in `external`\n      external !== true &&\n      external.includes(id)\n    ) {\n      return true\n    }\n    const pkgName = getNpmPackageName(id)\n    if (!pkgName) {\n      return isExternalizable(id, importer, false)\n    }\n    if (\n      // A package name in ssr.external externalizes every\n      // externalizable package entry\n      external !== true &&\n      external.includes(pkgName)\n    ) {\n      return isExternalizable(id, importer, true)\n    }\n    if (typeof noExternal === 'boolean') {\n      return !noExternal\n    }\n    if (noExternalFilter && !noExternalFilter(pkgName)) {\n      return false\n    }\n    // If external is true, all will be externalized by default, regardless if\n    // it's a linked package\n    return isExternalizable(id, importer, external === true)\n  }\n}\n\nfunction createIsExternal(\n  environment: Environment,\n): (id: string, importer?: string) => boolean {\n  const processedIds = new Map<string, boolean>()\n\n  const isConfiguredAsExternal = createIsConfiguredAsExternal(environment)\n\n  return (id: string, importer?: string) => {\n    if (processedIds.has(id)) {\n      return processedIds.get(id)!\n    }\n    let isExternal = false\n    if (id[0] !== '.' && !path.isAbsolute(id)) {\n      isExternal =\n        isBuiltin(environment.config.resolve.builtins, id) ||\n        isConfiguredAsExternal(id, importer)\n    }\n    processedIds.set(id, isExternal)\n    return isExternal\n  }\n}\n\nexport function canExternalizeFile(filePath: string): boolean {\n  const ext = path.extname(filePath)\n  // only external js imports\n  return !ext || ext === '.js' || ext === '.mjs' || ext === '.cjs'\n}\n"
  },
  {
    "path": "packages/vite/src/node/http.ts",
    "content": "import fsp from 'node:fs/promises'\nimport net from 'node:net'\nimport path from 'node:path'\nimport type { OutgoingHttpHeaders as HttpServerHeaders } from 'node:http'\nimport type { ServerOptions as HttpsServerOptions } from 'node:https'\nimport colors from 'picocolors'\nimport type { Connect } from '#dep-types/connect'\nimport type { ProxyOptions } from './server/middlewares/proxy'\nimport type { Logger } from './logger'\nimport type { HttpServer } from './server'\nimport { wildcardHosts } from './constants'\n\nexport interface CommonServerOptions {\n  /**\n   * Specify server port. Note if the port is already being used, Vite will\n   * automatically try the next available port so this may not be the actual\n   * port the server ends up listening on.\n   */\n  port?: number\n  /**\n   * If enabled, vite will exit if specified port is already in use\n   */\n  strictPort?: boolean\n  /**\n   * Specify which IP addresses the server should listen on.\n   * Set to 0.0.0.0 to listen on all addresses, including LAN and public addresses.\n   */\n  host?: string | boolean\n  /**\n   * The hostnames that Vite is allowed to respond to.\n   * `localhost` and subdomains under `.localhost` and all IP addresses are allowed by default.\n   * When using HTTPS, this check is skipped.\n   *\n   * If a string starts with `.`, it will allow that hostname without the `.` and all subdomains under the hostname.\n   * For example, `.example.com` will allow `example.com`, `foo.example.com`, and `foo.bar.example.com`.\n   *\n   * If set to `true`, the server is allowed to respond to requests for any hosts.\n   * This is not recommended as it will be vulnerable to DNS rebinding attacks.\n   */\n  allowedHosts?: string[] | true\n  /**\n   * Enable TLS + HTTP/2.\n   * Note: this downgrades to TLS only when the proxy option is also used.\n   */\n  https?: HttpsServerOptions\n  /**\n   * Open browser window on startup\n   */\n  open?: boolean | string\n  /**\n   * Configure custom proxy rules for the dev server. Expects an object\n   * of `{ key: options }` pairs.\n   * Uses [`http-proxy-3`](https://github.com/sagemathinc/http-proxy-3).\n   * Full options [here](https://github.com/sagemathinc/http-proxy-3#options).\n   *\n   * Example `vite.config.js`:\n   * ``` js\n   * module.exports = {\n   *   proxy: {\n   *     // string shorthand: /foo -> http://localhost:4567/foo\n   *     '/foo': 'http://localhost:4567',\n   *     // with options\n   *     '/api': {\n   *       target: 'http://jsonplaceholder.typicode.com',\n   *       changeOrigin: true,\n   *       rewrite: path => path.replace(/^\\/api/, '')\n   *     }\n   *   }\n   * }\n   * ```\n   */\n  proxy?: Record<string, string | ProxyOptions>\n  /**\n   * Configure CORS for the dev server.\n   * Uses https://github.com/expressjs/cors.\n   *\n   * When enabling this option, **we recommend setting a specific value\n   * rather than `true`** to avoid exposing the source code to untrusted origins.\n   *\n   * Set to `true` to allow all methods from any origin, or configure separately\n   * using an object.\n   *\n   * @default false\n   */\n  cors?: CorsOptions | boolean\n  /**\n   * Specify server response headers.\n   */\n  headers?: HttpServerHeaders\n}\n\n/**\n * https://github.com/expressjs/cors#configuration-options\n */\nexport interface CorsOptions {\n  /**\n   * Configures the Access-Control-Allow-Origin CORS header.\n   *\n   * **We recommend setting a specific value rather than\n   * `true`** to avoid exposing the source code to untrusted origins.\n   */\n  origin?:\n    | CorsOrigin\n    | ((\n        origin: string | undefined,\n        cb: (err: Error, origins: CorsOrigin) => void,\n      ) => void)\n  methods?: string | string[]\n  allowedHeaders?: string | string[]\n  exposedHeaders?: string | string[]\n  credentials?: boolean\n  maxAge?: number\n  preflightContinue?: boolean\n  optionsSuccessStatus?: number\n}\n\nexport type CorsOrigin = boolean | string | RegExp | (string | RegExp)[]\n\nexport async function resolveHttpServer(\n  app: Connect.Server,\n  httpsOptions?: HttpsServerOptions,\n): Promise<HttpServer> {\n  if (!httpsOptions) {\n    const { createServer } = await import('node:http')\n    return createServer(app)\n  }\n\n  const { createSecureServer } = await import('node:http2')\n  return createSecureServer(\n    {\n      // Manually increase the session memory to prevent 502 ENHANCE_YOUR_CALM\n      // errors on large numbers of requests\n      maxSessionMemory: 1000,\n      // Increase the stream reset rate limit to prevent net::ERR_HTTP2_PROTOCOL_ERROR\n      // errors on large numbers of requests\n      streamResetBurst: 100000,\n      streamResetRate: 33,\n      ...httpsOptions,\n      allowHTTP1: true,\n    },\n    // @ts-expect-error TODO: is this correct?\n    app,\n  )\n}\n\nexport async function resolveHttpsConfig(\n  https: HttpsServerOptions | undefined,\n): Promise<HttpsServerOptions | undefined> {\n  if (!https) return undefined\n\n  const [ca, cert, key, pfx] = await Promise.all([\n    readFileIfExists(https.ca),\n    readFileIfExists(https.cert),\n    readFileIfExists(https.key),\n    readFileIfExists(https.pfx),\n  ])\n  return { ...https, ca, cert, key, pfx }\n}\n\nasync function readFileIfExists(value?: string | Buffer | any[]) {\n  if (typeof value === 'string') {\n    return fsp.readFile(path.resolve(value)).catch(() => value)\n  }\n  return value\n}\n\n// Check if a port is available on wildcard addresses (0.0.0.0, ::)\nasync function isPortAvailable(port: number): Promise<boolean> {\n  for (const host of wildcardHosts) {\n    // Gracefully handle errors (e.g., IPv6 disabled on the system)\n    const available = await tryListen(port, host).catch(() => true)\n    if (!available) return false\n  }\n  return true\n}\n\nfunction tryListen(port: number, host: string): Promise<boolean> {\n  return new Promise((resolve) => {\n    const server = net.createServer()\n    server.once('error', (e: NodeJS.ErrnoException) => {\n      server.close(() => resolve(e.code !== 'EADDRINUSE'))\n    })\n    server.once('listening', () => {\n      server.close(() => resolve(true))\n    })\n    server.listen(port, host)\n  })\n}\n\nasync function tryBindServer(\n  httpServer: HttpServer,\n  port: number,\n  host: string | undefined,\n): Promise<\n  { success: true } | { success: false; error: NodeJS.ErrnoException }\n> {\n  return new Promise((resolve) => {\n    const onError = (e: NodeJS.ErrnoException) => {\n      httpServer.off('error', onError)\n      httpServer.off('listening', onListening)\n      resolve({ success: false, error: e })\n    }\n    const onListening = () => {\n      httpServer.off('error', onError)\n      httpServer.off('listening', onListening)\n      resolve({ success: true })\n    }\n\n    httpServer.on('error', onError)\n    httpServer.on('listening', onListening)\n\n    httpServer.listen(port, host)\n  })\n}\n\nconst MAX_PORT = 65535\n\nexport async function httpServerStart(\n  httpServer: HttpServer,\n  serverOptions: {\n    port: number\n    strictPort: boolean | undefined\n    host: string | undefined\n    logger: Logger\n  },\n): Promise<number> {\n  const { port: startPort, strictPort, host, logger } = serverOptions\n\n  for (let port = startPort; port <= MAX_PORT; port++) {\n    // Pre-check port availability on wildcard addresses (0.0.0.0, ::)\n    // so that we avoid conflicts with other servers listening on all interfaces\n    if (await isPortAvailable(port)) {\n      const result = await tryBindServer(httpServer, port, host)\n      if (result.success) {\n        return port\n      }\n      if (result.error.code !== 'EADDRINUSE') {\n        throw result.error\n      }\n    }\n\n    if (strictPort) {\n      throw new Error(`Port ${port} is already in use`)\n    }\n\n    logger.info(`Port ${port} is in use, trying another one...`)\n  }\n  throw new Error(\n    `No available ports found between ${startPort} and ${MAX_PORT}`,\n  )\n}\n\nexport function setClientErrorHandler(\n  server: HttpServer,\n  logger: Logger,\n): void {\n  server.on('clientError', (err, socket) => {\n    let msg = '400 Bad Request'\n    if ((err as any).code === 'HPE_HEADER_OVERFLOW') {\n      msg = '431 Request Header Fields Too Large'\n      logger.warn(\n        colors.yellow(\n          'Server responded with status code 431. ' +\n            'See https://vite.dev/guide/troubleshooting.html#_431-request-header-fields-too-large.',\n        ),\n      )\n    }\n    if ((err as any).code === 'ECONNRESET' || !socket.writable) {\n      return\n    }\n    socket.end(`HTTP/1.1 ${msg}\\r\\n\\r\\n`)\n  })\n}\n"
  },
  {
    "path": "packages/vite/src/node/idResolver.ts",
    "content": "import type { PartialResolvedId } from 'rolldown'\nimport aliasPlugin from '@rollup/plugin-alias'\nimport type { ResolvedConfig } from './config'\nimport type { EnvironmentPluginContainer } from './server/pluginContainer'\nimport { createEnvironmentPluginContainer } from './server/pluginContainer'\nimport { oxcResolvePlugin } from './plugins/resolve'\nimport type { InternalResolveOptions } from './plugins/resolve'\nimport type { Environment } from './environment'\nimport type { PartialEnvironment } from './baseEnvironment'\n\nexport type ResolveIdFn = (\n  environment: PartialEnvironment,\n  id: string,\n  importer?: string,\n  aliasOnly?: boolean,\n) => Promise<string | undefined>\n\n/**\n * Some projects like Astro were overriding config.createResolver to add a custom\n * alias plugin. For the client and ssr environments, we root through it to avoid\n * breaking changes for now.\n */\nexport function createBackCompatIdResolver(\n  config: ResolvedConfig,\n  options?: Partial<InternalResolveOptions>,\n): ResolveIdFn {\n  const compatResolve = config.createResolver(options)\n  let resolve: ResolveIdFn\n  return async (environment, id, importer, aliasOnly) => {\n    if (environment.name === 'client' || environment.name === 'ssr') {\n      return compatResolve(id, importer, aliasOnly, environment.name === 'ssr')\n    }\n    resolve ??= createIdResolver(config, options)\n    return resolve(environment, id, importer, aliasOnly)\n  }\n}\n\n/**\n * Create an internal resolver to be used in special scenarios, e.g.\n * optimizer and handling css @imports\n */\nexport function createIdResolver(\n  config: ResolvedConfig,\n  options?: Partial<InternalResolveOptions>,\n): ResolveIdFn {\n  const scan = options?.scan\n\n  const pluginContainerMap = new Map<\n    PartialEnvironment,\n    EnvironmentPluginContainer\n  >()\n  async function resolve(\n    environment: PartialEnvironment,\n    id: string,\n    importer?: string,\n  ): Promise<PartialResolvedId | null> {\n    let pluginContainer = pluginContainerMap.get(environment)\n    if (!pluginContainer) {\n      pluginContainer = await createEnvironmentPluginContainer(\n        environment as Environment,\n        [\n          // @ts-expect-error  the aliasPlugin uses rollup types\n          aliasPlugin({ entries: environment.config.resolve.alias }),\n          ...oxcResolvePlugin(\n            {\n              root: config.root,\n              isProduction: config.isProduction,\n              isBuild: config.command === 'build',\n              asSrc: true,\n              preferRelative: false,\n              tryIndex: true,\n              ...options,\n              // Ignore sideEffects and other computations as we only need the id\n              idOnly: true,\n            },\n            environment.config,\n          ),\n        ],\n        undefined,\n        false,\n      )\n      pluginContainerMap.set(environment, pluginContainer)\n    }\n    return await pluginContainer.resolveId(id, importer, { scan })\n  }\n\n  const aliasOnlyPluginContainerMap = new Map<\n    PartialEnvironment,\n    EnvironmentPluginContainer\n  >()\n  async function resolveAlias(\n    environment: PartialEnvironment,\n    id: string,\n    importer?: string,\n  ): Promise<PartialResolvedId | null> {\n    let pluginContainer = aliasOnlyPluginContainerMap.get(environment)\n    if (!pluginContainer) {\n      pluginContainer = await createEnvironmentPluginContainer(\n        environment as Environment,\n        // @ts-expect-error  the aliasPlugin uses rollup types\n        [aliasPlugin({ entries: environment.config.resolve.alias })],\n        undefined,\n        false,\n      )\n      aliasOnlyPluginContainerMap.set(environment, pluginContainer)\n    }\n    return await pluginContainer.resolveId(id, importer, { scan })\n  }\n\n  return async (environment, id, importer, aliasOnly) => {\n    const resolveFn = aliasOnly ? resolveAlias : resolve\n    // aliasPlugin and resolvePlugin are implemented to function with a Environment only,\n    // we cast it as PluginEnvironment to be able to use the pluginContainer\n    const resolved = await resolveFn(environment, id, importer)\n    return resolved?.id\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/index.ts",
    "content": "import type * as Rolldown from 'rolldown'\nimport {\n  parseAst as _parseAst,\n  parseAstAsync as _parseAstAsync,\n} from 'rolldown/parseAst'\nimport type * as Rollup from '#types/internal/rollupTypeCompat'\n\nexport type { Rollup, Rolldown }\nexport { esmExternalRequirePlugin } from 'rolldown/plugins'\nexport {\n  parse,\n  parseSync,\n  type ParserOptions,\n  type ParseResult,\n  minify,\n  minifySync,\n  type MinifyOptions,\n  type MinifyResult,\n  Visitor,\n  type VisitorObject,\n  type ESTree,\n} from 'rolldown/utils'\n\n/** @deprecated - use `parse` instead */\nexport const parseAst: typeof _parseAst = _parseAst\n/** @deprecated - use `parseAsync` instead */\nexport const parseAstAsync: typeof _parseAstAsync = _parseAstAsync\n\nexport {\n  defineConfig,\n  loadConfigFromFile,\n  resolveConfig,\n  sortUserPlugins,\n} from './config'\nexport { perEnvironmentPlugin } from './plugin'\nexport { perEnvironmentState } from './environment'\nexport { createServer } from './server'\nexport { preview } from './preview'\nexport { build, createBuilder } from './build'\n\nexport { optimizeDeps } from './optimizer'\nexport { createIdResolver } from './idResolver'\n\nexport { formatPostcssSourceMap, preprocessCSS } from './plugins/css'\nexport { transformWithEsbuild } from './plugins/esbuild'\nexport { transformWithOxc } from './plugins/oxc'\nexport { buildErrorMessage } from './server/middlewares/error'\n\nexport {\n  createRunnableDevEnvironment,\n  isRunnableDevEnvironment,\n  type RunnableDevEnvironment,\n  type RunnableDevEnvironmentContext,\n} from './server/environments/runnableEnvironment'\nexport {\n  createFetchableDevEnvironment,\n  isFetchableDevEnvironment,\n  type FetchableDevEnvironment,\n  type FetchableDevEnvironmentContext,\n} from './server/environments/fetchableEnvironments'\nexport {\n  DevEnvironment,\n  type DevEnvironmentContext,\n} from './server/environment'\nexport { runnerImport } from './ssr/runnerImport'\nexport { BuildEnvironment } from './build'\n\nexport { fetchModule, type FetchModuleOptions } from './ssr/fetchModule'\nexport {\n  createServerModuleRunner,\n  createServerModuleRunnerTransport,\n} from './ssr/runtime/serverModuleRunner'\nexport { createServerHotChannel } from './server/hmr'\nexport { ssrTransform as moduleRunnerTransform } from './ssr/ssrTransform'\nexport type { ModuleRunnerTransformOptions } from './ssr/ssrTransform'\n\nexport {\n  VERSION as version,\n  DEFAULT_CLIENT_CONDITIONS as defaultClientConditions,\n  DEFAULT_CLIENT_MAIN_FIELDS as defaultClientMainFields,\n  DEFAULT_EXTERNAL_CONDITIONS as defaultExternalConditions,\n  DEFAULT_SERVER_CONDITIONS as defaultServerConditions,\n  DEFAULT_SERVER_MAIN_FIELDS as defaultServerMainFields,\n  defaultAllowedOrigins,\n} from './constants'\n// NOTE: export for backward compat\nexport const esbuildVersion = '0.25.0'\nexport {\n  normalizePath,\n  mergeConfig,\n  mergeAlias,\n  createFilter,\n  withFilter,\n  isCSSRequest,\n  rollupVersion,\n  rolldownVersion,\n} from './utils'\nexport { send } from './server/send'\nexport { createLogger } from './logger'\nexport { searchForWorkspaceRoot } from './server/searchRoot'\n\nexport {\n  isFileServingAllowed,\n  isFileLoadingAllowed,\n} from './server/middlewares/static'\nexport { loadEnv, resolveEnvPrefix } from './env'\n\n// additional types\nexport type {\n  AppType,\n  ConfigEnv,\n  ExperimentalOptions,\n  HTMLOptions,\n  InlineConfig,\n  LegacyOptions,\n  PluginHookUtils,\n  ResolveFn,\n  ResolvedWorkerOptions,\n  ResolvedConfig,\n  UserConfig,\n  UserConfigExport,\n  UserConfigFn,\n  UserConfigFnObject,\n  UserConfigFnPromise,\n  EnvironmentOptions,\n  DevEnvironmentOptions,\n  ResolvedDevEnvironmentOptions,\n} from './config'\nexport type {\n  Plugin,\n  PluginOption,\n  HookHandler,\n  ConfigPluginContext,\n  MinimalPluginContextWithoutEnvironment,\n} from './plugin'\nexport type { Environment } from './environment'\nexport type { FilterPattern } from './utils'\nexport type { CorsOptions, CorsOrigin, CommonServerOptions } from './http'\nexport type {\n  ViteDevServer,\n  ServerOptions,\n  FileSystemServeOptions,\n  ServerHook,\n  ResolvedServerOptions,\n  ResolvedServerUrls,\n  HttpServer,\n} from './server'\nexport type {\n  ViteBuilder,\n  BuildAppHook,\n  BuilderOptions,\n  BuildOptions,\n  BuildEnvironmentOptions,\n  LibraryOptions,\n  LibraryFormats,\n  RenderBuiltAssetUrl,\n  ResolvedBuildOptions,\n  ResolvedBuildEnvironmentOptions,\n  ModulePreloadOptions,\n  ResolvedModulePreloadOptions,\n  ResolveModulePreloadDependenciesFn,\n} from './build'\nexport type {\n  PreviewOptions,\n  PreviewServer,\n  PreviewServerHook,\n  ResolvedPreviewOptions,\n} from './preview'\nexport type {\n  DepOptimizationMetadata,\n  DepOptimizationOptions,\n  DepOptimizationConfig,\n  OptimizedDepInfo,\n  ExportsData,\n} from './optimizer'\nexport type {\n  ResolvedSSROptions,\n  SsrDepOptimizationConfig,\n  SSROptions,\n  SSRTarget,\n} from './ssr'\nexport type {\n  Logger,\n  LogOptions,\n  LogErrorOptions,\n  LogLevel,\n  LogType,\n  LoggerOptions,\n} from './logger'\nexport type {\n  IndexHtmlTransform,\n  IndexHtmlTransformHook,\n  IndexHtmlTransformContext,\n  IndexHtmlTransformResult,\n  HtmlTagDescriptor,\n} from './plugins/html'\nexport type {\n  CSSOptions,\n  CSSModulesOptions,\n  PreprocessCSSResult,\n  ResolvedCSSOptions,\n  SassPreprocessorOptions,\n  LessPreprocessorOptions,\n  StylusPreprocessorOptions,\n} from './plugins/css'\nexport type { JsonOptions } from './plugins/json'\nexport type { ESBuildOptions } from './plugins/esbuild'\nexport type { EsbuildTransformOptions } from '#types/internal/esbuildOptions'\nexport type { OxcOptions } from './plugins/oxc'\nexport type { Manifest, ManifestChunk } from './plugins/manifest'\nexport type { ResolveOptions, InternalResolveOptions } from './plugins/resolve'\nexport type { TerserOptions } from './plugins/terser'\n\nexport type {\n  WebSocketServer,\n  WebSocketClient,\n  WebSocketCustomListener,\n} from './server/ws'\nexport type { SkipInformation, PluginContainer } from './server/pluginContainer'\nexport type {\n  EnvironmentModuleGraph,\n  EnvironmentModuleNode,\n  ResolvedUrl,\n} from './server/moduleGraph'\nexport type { SendOptions } from './server/send'\nexport type { ProxyOptions } from './server/middlewares/proxy'\nexport type {\n  TransformOptions,\n  TransformResult,\n} from './server/transformRequest'\nexport type {\n  HmrOptions,\n  HmrContext,\n  HotUpdateOptions,\n  HotChannelListener,\n  HotChannel,\n  ServerHotChannel,\n  HotChannelClient,\n  NormalizedHotChannel,\n  NormalizedHotChannelClient,\n  NormalizedServerHotChannel,\n} from './server/hmr'\n\nexport type { FetchFunction, FetchResult } from 'vite/module-runner'\nexport type { ServerModuleRunnerOptions } from './ssr/runtime/serverModuleRunner'\n\nexport type { BindCLIShortcutsOptions, CLIShortcut } from './shortcuts'\n\nexport type {\n  HMRPayload,\n  HotPayload,\n  ConnectedPayload,\n  UpdatePayload,\n  Update,\n  FullReloadPayload,\n  CustomPayload,\n  PrunePayload,\n  ErrorPayload,\n} from '#types/hmrPayload'\nexport type {\n  CustomEventMap,\n  InferCustomEventPayload,\n  InvalidatePayload,\n} from '#types/customEvent'\nexport type {\n  ImportGlobFunction,\n  ImportGlobOptions,\n  GeneralImportGlobOptions,\n  KnownAsTypeMap,\n} from '#types/importGlob'\nexport type { ChunkMetadata, CustomPluginOptionsVite } from '#types/metadata'\n\n// dep types\nexport type {\n  AliasOptions,\n  MapToFunction,\n  ResolverFunction,\n  ResolverObject,\n  Alias,\n} from '#dep-types/alias'\nexport type { Connect } from '#dep-types/connect'\nexport type { WebSocket, WebSocketAlias } from '#dep-types/ws'\nexport type * as HttpProxy from 'http-proxy-3'\nexport type { FSWatcher, WatchOptions } from '#dep-types/chokidar'\nexport type { Terser } from '#types/internal/terserOptions'\nexport type { RollupCommonJSOptions } from '#dep-types/commonjs'\nexport type { RollupDynamicImportVarsOptions } from '#dep-types/dynamicImportVars'\nexport type { Matcher, AnymatchPattern, AnymatchFn } from '#dep-types/anymatch'\nexport type { LightningCSSOptions } from '#types/internal/lightningcssOptions'\n\n// Backward compatibility\nexport type { ModuleGraph, ModuleNode } from './server/mixedModuleGraph'\n"
  },
  {
    "path": "packages/vite/src/node/internalIndex.ts",
    "content": "export { viteReactRefreshWrapperPlugin as reactRefreshWrapperPlugin } from 'rolldown/experimental'\n"
  },
  {
    "path": "packages/vite/src/node/logger.ts",
    "content": "/* eslint no-console: 0 */\n\nimport readline from 'node:readline'\nimport colors from 'picocolors'\nimport type { RollupError } from 'rolldown'\nimport type { ResolvedServerUrls } from './server'\n\nexport type LogType = 'error' | 'warn' | 'info'\nexport type LogLevel = LogType | 'silent'\nexport interface Logger {\n  info(msg: string, options?: LogOptions): void\n  warn(msg: string, options?: LogOptions): void\n  warnOnce(msg: string, options?: LogOptions): void\n  error(msg: string, options?: LogErrorOptions): void\n  clearScreen(type: LogType): void\n  hasErrorLogged(error: Error | RollupError): boolean\n  hasWarned: boolean\n}\n\nexport interface LogOptions {\n  clear?: boolean\n  timestamp?: boolean\n  environment?: string\n}\n\nexport interface LogErrorOptions extends LogOptions {\n  error?: Error | RollupError | null\n}\n\nexport const LogLevels: Record<LogLevel, number> = {\n  silent: 0,\n  error: 1,\n  warn: 2,\n  info: 3,\n}\n\nlet lastType: LogType | undefined\nlet lastMsg: string | undefined\nlet sameCount = 0\n\nfunction clearScreen() {\n  const repeatCount = process.stdout.rows - 2\n  const blank = repeatCount > 0 ? '\\n'.repeat(repeatCount) : ''\n  console.log(blank)\n  readline.cursorTo(process.stdout, 0, 0)\n  readline.clearScreenDown(process.stdout)\n}\n\nexport interface LoggerOptions {\n  prefix?: string\n  allowClearScreen?: boolean\n  customLogger?: Logger\n  console?: Console\n}\n\n// Only initialize the timeFormatter when the timestamp option is used, and\n// reuse it across all loggers\nlet timeFormatter: Intl.DateTimeFormat\nfunction getTimeFormatter() {\n  timeFormatter ??= new Intl.DateTimeFormat(undefined, {\n    hour: 'numeric',\n    minute: 'numeric',\n    second: 'numeric',\n  })\n  return timeFormatter\n}\n\nexport function createLogger(\n  level: LogLevel = 'info',\n  options: LoggerOptions = {},\n): Logger {\n  if (options.customLogger) {\n    return options.customLogger\n  }\n\n  const loggedErrors = new WeakSet<Error | RollupError>()\n  const {\n    prefix = '[vite]',\n    allowClearScreen = true,\n    console = globalThis.console,\n  } = options\n  const thresh = LogLevels[level]\n  const canClearScreen =\n    allowClearScreen && process.stdout.isTTY && !process.env.CI\n  const clear = canClearScreen ? clearScreen : () => {}\n\n  function format(type: LogType, msg: string, options: LogErrorOptions = {}) {\n    if (options.timestamp) {\n      let tag = ''\n      if (type === 'info') {\n        tag = colors.cyan(colors.bold(prefix))\n      } else if (type === 'warn') {\n        tag = colors.yellow(colors.bold(prefix))\n      } else {\n        tag = colors.red(colors.bold(prefix))\n      }\n      const environment = options.environment ? options.environment + ' ' : ''\n      return `${colors.dim(getTimeFormatter().format(new Date()))} ${tag} ${environment}${msg}`\n    } else {\n      return msg\n    }\n  }\n\n  function output(type: LogType, msg: string, options: LogErrorOptions = {}) {\n    if (thresh >= LogLevels[type]) {\n      const method = type === 'info' ? 'log' : type\n\n      if (options.error) {\n        loggedErrors.add(options.error)\n      }\n      if (canClearScreen) {\n        if (type === lastType && msg === lastMsg) {\n          sameCount++\n          clear()\n          console[method](\n            format(type, msg, options),\n            colors.yellow(`(x${sameCount + 1})`),\n          )\n        } else {\n          sameCount = 0\n          lastMsg = msg\n          lastType = type\n          if (options.clear) {\n            clear()\n          }\n          console[method](format(type, msg, options))\n        }\n      } else {\n        console[method](format(type, msg, options))\n      }\n    }\n  }\n\n  const warnedMessages = new Set<string>()\n\n  const logger: Logger = {\n    hasWarned: false,\n    info(msg, opts) {\n      output('info', msg, opts)\n    },\n    warn(msg, opts) {\n      logger.hasWarned = true\n      output('warn', msg, opts)\n    },\n    warnOnce(msg, opts) {\n      if (warnedMessages.has(msg)) return\n      logger.hasWarned = true\n      output('warn', msg, opts)\n      warnedMessages.add(msg)\n    },\n    error(msg, opts) {\n      logger.hasWarned = true\n      output('error', msg, opts)\n    },\n    clearScreen(type) {\n      if (thresh >= LogLevels[type]) {\n        clear()\n      }\n    },\n    hasErrorLogged(error) {\n      return loggedErrors.has(error)\n    },\n  }\n\n  return logger\n}\n\nexport function printServerUrls(\n  urls: ResolvedServerUrls,\n  optionsHost: string | boolean | undefined,\n  info: Logger['info'],\n): void {\n  const colorUrl = (url: string) =>\n    colors.cyan(url.replace(/:(\\d+)\\//, (_, port) => `:${colors.bold(port)}/`))\n  for (const url of urls.local) {\n    info(`  ${colors.green('➜')}  ${colors.bold('Local')}:   ${colorUrl(url)}`)\n  }\n  for (const url of urls.network) {\n    info(`  ${colors.green('➜')}  ${colors.bold('Network')}: ${colorUrl(url)}`)\n  }\n  if (urls.network.length === 0 && optionsHost === undefined) {\n    info(\n      colors.dim(`  ${colors.green('➜')}  ${colors.bold('Network')}: use `) +\n        colors.bold('--host') +\n        colors.dim(' to expose'),\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/nodeResolve.ts",
    "content": "import isModuleSyncConditionEnabled from '#module-sync-enabled'\nimport { DEFAULT_EXTENSIONS } from './constants'\nimport { tryNodeResolve } from './plugins/resolve'\nimport { nodeLikeBuiltins } from './utils'\n\nexport interface NodeResolveWithViteOptions {\n  root: string\n  isRequire?: boolean\n}\n\n/**\n * Resolve like Node.js using Vite's resolution algorithm with preconfigured options.\n */\nexport function nodeResolveWithVite(\n  id: string,\n  importer: string | undefined,\n  options: NodeResolveWithViteOptions,\n): string | undefined {\n  return tryNodeResolve(id, importer, {\n    root: options.root,\n    isBuild: true,\n    isProduction: true,\n    preferRelative: false,\n    tryIndex: true,\n    mainFields: [],\n    conditions: [\n      'node',\n      ...(isModuleSyncConditionEnabled ? ['module-sync'] : []),\n    ],\n    externalConditions: [],\n    external: [],\n    noExternal: [],\n    dedupe: [],\n    extensions: DEFAULT_EXTENSIONS,\n    preserveSymlinks: false,\n    tsconfigPaths: false,\n    // Intentionally disable package cache for now as consumers don't need it\n    packageCache: undefined,\n    isRequire: options.isRequire,\n    builtins: nodeLikeBuiltins,\n    disableOptionalPeerDepHandling: true,\n  })?.id\n}\n"
  },
  {
    "path": "packages/vite/src/node/optimizer/index.ts",
    "content": "import fs from 'node:fs'\nimport fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport { promisify } from 'node:util'\nimport { performance } from 'node:perf_hooks'\nimport colors from 'picocolors'\nimport { init, parse } from 'es-module-lexer'\nimport { isDynamicPattern } from 'tinyglobby'\nimport {\n  type RolldownOptions,\n  type RolldownOutput,\n  type OutputOptions as RolldownOutputOptions,\n  rolldown,\n} from 'rolldown'\nimport type { DepsOptimizerEsbuildOptions } from '#types/internal/esbuildOptions'\nimport type { ResolvedConfig } from '../config'\nimport {\n  arraify,\n  asyncFlatten,\n  createDebugger,\n  flattenId,\n  getHash,\n  isOptimizable,\n  lookupFile,\n  normalizeId,\n  normalizePath,\n  removeLeadingSlash,\n  tryStatSync,\n  unique,\n} from '../utils'\nimport {\n  ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET,\n  METADATA_FILENAME,\n} from '../constants'\nimport { isWindows } from '../../shared/utils'\nimport type { Environment } from '../environment'\nimport { transformWithOxc } from '../plugins/oxc'\nimport { ScanEnvironment, scanImports } from './scan'\nimport { createOptimizeDepsIncludeResolver, expandGlobIds } from './resolve'\nimport {\n  rolldownCjsExternalPlugin,\n  rolldownDepPlugin,\n} from './rolldownDepPlugin'\n\nconst debug = createDebugger('vite:deps')\n\nconst jsExtensionRE = /\\.js$/i\n\nexport type ExportsData = {\n  hasModuleSyntax: boolean\n  // exported names (for `export { a as b }`, `b` is exported name)\n  exports: readonly string[]\n  // hint if the dep requires loading as jsx\n  jsxLoader?: boolean\n}\n\nexport interface DepsOptimizer {\n  init: () => Promise<void>\n\n  metadata: DepOptimizationMetadata\n  scanProcessing?: Promise<void>\n  registerMissingImport: (id: string, resolved: string) => OptimizedDepInfo\n  run: () => void\n\n  isOptimizedDepFile: (id: string) => boolean\n  isOptimizedDepUrl: (url: string) => boolean\n  getOptimizedDepId: (depInfo: OptimizedDepInfo) => string\n\n  close: () => Promise<void>\n\n  options: DepOptimizationOptions\n}\n\nexport interface DepOptimizationConfig {\n  /**\n   * Force optimize listed dependencies (must be resolvable import paths,\n   * cannot be globs).\n   */\n  include?: string[]\n  /**\n   * Do not optimize these dependencies (must be resolvable import paths,\n   * cannot be globs).\n   */\n  exclude?: string[]\n  /**\n   * Forces ESM interop when importing these dependencies. Some legacy\n   * packages advertise themselves as ESM but use `require` internally\n   * @experimental\n   */\n  needsInterop?: string[]\n  /**\n   * Options to pass to esbuild during the dep scanning and optimization\n   *\n   * Certain options are omitted since changing them would not be compatible\n   * with Vite's dep optimization.\n   *\n   * - `external` is also omitted, use Vite's `optimizeDeps.exclude` option\n   * - `plugins` are merged with Vite's dep plugin\n   *\n   * https://esbuild.github.io/api\n   *\n   * @deprecated Use `rolldownOptions` instead.\n   */\n  esbuildOptions?: DepsOptimizerEsbuildOptions\n  /**\n   * @deprecated Use `rolldownOptions` instead.\n   */\n  rollupOptions?: Omit<RolldownOptions, 'input' | 'logLevel' | 'output'> & {\n    output?: Omit<\n      RolldownOutputOptions,\n      'format' | 'sourcemap' | 'dir' | 'banner'\n    >\n  }\n  /**\n   * Options to pass to rolldown during the dep scanning and optimization\n   *\n   * Certain options are omitted since changing them would not be compatible\n   * with Vite's dep optimization.\n   *\n   * - `plugins` are merged with Vite's dep plugin\n   */\n  rolldownOptions?: Omit<RolldownOptions, 'input' | 'logLevel' | 'output'> & {\n    output?: Omit<\n      RolldownOutputOptions,\n      'format' | 'sourcemap' | 'dir' | 'banner'\n    >\n  }\n  /**\n   * List of file extensions that can be optimized. A corresponding esbuild\n   * plugin must exist to handle the specific extension.\n   *\n   * By default, Vite can optimize `.mjs`, `.js`, `.ts`, and `.mts` files. This option\n   * allows specifying additional extensions.\n   *\n   * @experimental\n   */\n  extensions?: string[]\n  /**\n   * Deps optimization during build was removed in Vite 5.1. This option is\n   * now redundant and will be removed in a future version. Switch to using\n   * `optimizeDeps.noDiscovery` and an empty or undefined `optimizeDeps.include`.\n   * true or 'dev' disables the optimizer, false or 'build' leaves it enabled.\n   * @default 'build'\n   * @deprecated\n   * @experimental\n   */\n  disabled?: boolean | 'build' | 'dev'\n  /**\n   * Automatic dependency discovery. When `noDiscovery` is true, only dependencies\n   * listed in `include` will be optimized. The scanner isn't run for cold start\n   * in this case. CJS-only dependencies must be present in `include` during dev.\n   * @default false\n   */\n  noDiscovery?: boolean\n  /**\n   * When enabled, it will hold the first optimized deps results until all static\n   * imports are crawled on cold start. This avoids the need for full-page reloads\n   * when new dependencies are discovered and they trigger the generation of new\n   * common chunks. If all dependencies are found by the scanner plus the explicitly\n   * defined ones in `include`, it is better to disable this option to let the\n   * browser process more requests in parallel.\n   * @default true\n   * @experimental\n   */\n  holdUntilCrawlEnd?: boolean\n  /**\n   * When enabled, Vite will not throw an error when an outdated optimized\n   * dependency is requested. Enabling this option may cause a single module\n   * to have a multiple reference.\n   * @default false\n   * @experimental\n   */\n  ignoreOutdatedRequests?: boolean\n}\n\nexport type DepOptimizationOptions = DepOptimizationConfig & {\n  /**\n   * By default, Vite will crawl your `index.html` to detect dependencies that\n   * need to be pre-bundled. If `build.rollupOptions.input` is specified, Vite\n   * will crawl those entry points instead.\n   *\n   * If neither of these fit your needs, you can specify custom entries using\n   * this option - the value should be a tinyglobby pattern or array of patterns\n   * (https://github.com/SuperchupuDev/tinyglobby) that are relative from\n   * vite project root. This will overwrite default entries inference.\n   */\n  entries?: string | string[]\n  /**\n   * Force dep pre-optimization regardless of whether deps have changed.\n   * @experimental\n   */\n  force?: boolean\n}\n\nexport function isDepOptimizationDisabled(\n  optimizeDeps: DepOptimizationOptions,\n): boolean {\n  return (\n    optimizeDeps.disabled === true ||\n    optimizeDeps.disabled === 'dev' ||\n    (!!optimizeDeps.noDiscovery && !optimizeDeps.include?.length)\n  )\n}\n\nexport interface DepOptimizationResult {\n  metadata: DepOptimizationMetadata\n  /**\n   * When doing a re-run, if there are newly discovered dependencies\n   * the page reload will be delayed until the next rerun so we need\n   * to be able to discard the result\n   */\n  commit: () => Promise<void>\n  cancel: () => void\n}\n\nexport interface OptimizedDepInfo {\n  id: string\n  file: string\n  src?: string\n  needsInterop?: boolean\n  browserHash?: string\n  fileHash?: string\n  /**\n   * During optimization, ids can still be resolved to their final location\n   * but the bundles may not yet be saved to disk\n   */\n  processing?: Promise<void>\n  /**\n   * ExportData cache, discovered deps will parse the src entry to get exports\n   * data used both to define if interop is needed and when pre-bundling\n   */\n  exportsData?: Promise<ExportsData>\n  isDynamicEntry?: boolean\n}\n\nexport interface DepOptimizationMetadata {\n  /**\n   * The main hash is determined by user config and dependency lockfiles.\n   * This is checked on server startup to avoid unnecessary re-bundles.\n   */\n  hash: string\n  /**\n   * This hash is determined by dependency lockfiles.\n   * This is checked on server startup to avoid unnecessary re-bundles.\n   */\n  lockfileHash: string\n  /**\n   * This hash is determined by user config.\n   * This is checked on server startup to avoid unnecessary re-bundles.\n   */\n  configHash: string\n  /**\n   * The browser hash is determined by the main hash plus additional dependencies\n   * discovered at runtime. This is used to invalidate browser requests to\n   * optimized deps.\n   */\n  browserHash: string\n  /**\n   * Metadata for each already optimized dependency\n   */\n  optimized: Record<string, OptimizedDepInfo>\n  /**\n   * Metadata for non-entry optimized chunks and dynamic imports\n   */\n  chunks: Record<string, OptimizedDepInfo>\n  /**\n   * Metadata for each newly discovered dependency after processing\n   */\n  discovered: Record<string, OptimizedDepInfo>\n  /**\n   * OptimizedDepInfo list\n   */\n  depInfoList: OptimizedDepInfo[]\n}\n\n/**\n * Scan and optimize dependencies within a project.\n * Used by Vite CLI when running `vite optimize`.\n *\n * @deprecated the optimization process runs automatically and does not need to be called\n */\n\nexport async function optimizeDeps(\n  config: ResolvedConfig,\n  force: boolean | undefined = config.optimizeDeps.force,\n  asCommand = false,\n): Promise<DepOptimizationMetadata> {\n  const log = asCommand ? config.logger.info : debug\n\n  config.logger.warn(\n    colors.yellow(\n      'manually calling optimizeDeps is deprecated. This is done automatically and does not need to be called manually.',\n    ),\n  )\n\n  const environment = new ScanEnvironment('client', config)\n  await environment.init()\n\n  const cachedMetadata = await loadCachedDepOptimizationMetadata(\n    environment,\n    force,\n    asCommand,\n  )\n  if (cachedMetadata) {\n    return cachedMetadata\n  }\n\n  const deps = await discoverProjectDependencies(environment).result\n\n  await addManuallyIncludedOptimizeDeps(environment, deps)\n\n  const depsString = depsLogString(Object.keys(deps))\n  log?.(colors.green(`Optimizing dependencies:\\n  ${depsString}`))\n\n  const depsInfo = toDiscoveredDependencies(environment, deps)\n\n  const result = await runOptimizeDeps(environment, depsInfo).result\n\n  await result.commit()\n\n  return result.metadata\n}\n\nexport async function optimizeExplicitEnvironmentDeps(\n  environment: Environment,\n): Promise<DepOptimizationMetadata> {\n  const cachedMetadata = await loadCachedDepOptimizationMetadata(\n    environment,\n    environment.config.optimizeDeps.force ?? false,\n    false,\n  )\n  if (cachedMetadata) {\n    return cachedMetadata\n  }\n\n  const deps: Record<string, string> = {}\n\n  await addManuallyIncludedOptimizeDeps(environment, deps)\n\n  const depsInfo = toDiscoveredDependencies(environment, deps)\n\n  const result = await runOptimizeDeps(environment, depsInfo).result\n\n  await result.commit()\n\n  return result.metadata\n}\n\nexport function initDepsOptimizerMetadata(\n  environment: Environment,\n  timestamp?: string,\n): DepOptimizationMetadata {\n  const { lockfileHash, configHash, hash } = getDepHash(environment)\n  return {\n    hash,\n    lockfileHash,\n    configHash,\n    browserHash: getOptimizedBrowserHash(hash, {}, timestamp),\n    optimized: {},\n    chunks: {},\n    discovered: {},\n    depInfoList: [],\n  }\n}\n\nexport function addOptimizedDepInfo(\n  metadata: DepOptimizationMetadata,\n  type: 'optimized' | 'discovered' | 'chunks',\n  depInfo: OptimizedDepInfo,\n): OptimizedDepInfo {\n  metadata[type][depInfo.id] = depInfo\n  metadata.depInfoList.push(depInfo)\n  return depInfo\n}\n\nlet firstLoadCachedDepOptimizationMetadata = true\n\n/**\n * Creates the initial dep optimization metadata, loading it from the deps cache\n * if it exists and pre-bundling isn't forced\n */\nexport async function loadCachedDepOptimizationMetadata(\n  environment: Environment,\n  force: boolean = environment.config.optimizeDeps.force ?? false,\n  asCommand = false,\n): Promise<DepOptimizationMetadata | undefined> {\n  const log = asCommand ? environment.logger.info : debug\n\n  if (firstLoadCachedDepOptimizationMetadata) {\n    firstLoadCachedDepOptimizationMetadata = false\n    // Fire up a clean up of stale processing deps dirs if older process exited early\n    setTimeout(\n      () => cleanupDepsCacheStaleDirs(environment.getTopLevelConfig()),\n      0,\n    ).unref()\n  }\n\n  const depsCacheDir = getDepsCacheDir(environment)\n\n  if (!force) {\n    let cachedMetadata: DepOptimizationMetadata | undefined\n    try {\n      const cachedMetadataPath = path.join(depsCacheDir, METADATA_FILENAME)\n      cachedMetadata = parseDepsOptimizerMetadata(\n        await fsp.readFile(cachedMetadataPath, 'utf-8'),\n        depsCacheDir,\n      )\n    } catch {}\n    // hash is consistent, no need to re-bundle\n    if (cachedMetadata) {\n      if (cachedMetadata.lockfileHash !== getLockfileHash(environment)) {\n        environment.logger.info(\n          'Re-optimizing dependencies because lockfile has changed',\n          {\n            timestamp: true,\n          },\n        )\n      } else if (cachedMetadata.configHash !== getConfigHash(environment)) {\n        environment.logger.info(\n          'Re-optimizing dependencies because vite config has changed',\n          {\n            timestamp: true,\n          },\n        )\n      } else {\n        log?.(\n          `(${environment.name}) Hash is consistent. Skipping. Use --force to override.`,\n        )\n        // Nothing to commit or cancel as we are using the cache, we only\n        // need to resolve the processing promise so requests can move on\n        return cachedMetadata\n      }\n    }\n  } else {\n    environment.logger.info('Forced re-optimization of dependencies', {\n      timestamp: true,\n    })\n  }\n\n  // Start with a fresh cache\n  debug?.(\n    `(${environment.name}) ${colors.green(`removing old cache dir ${depsCacheDir}`)}`,\n  )\n  await fsp.rm(depsCacheDir, { recursive: true, force: true })\n}\n\n/**\n * Initial optimizeDeps at server start. Perform a fast scan using esbuild to\n * find deps to pre-bundle and include user hard-coded dependencies\n */\nexport function discoverProjectDependencies(environment: ScanEnvironment): {\n  cancel: () => Promise<void>\n  result: Promise<Record<string, string>>\n} {\n  const { cancel, result } = scanImports(environment)\n\n  return {\n    cancel,\n    result: result.then(({ deps, missing }) => {\n      const missingIds = Object.keys(missing)\n      if (missingIds.length) {\n        throw new Error(\n          `The following dependencies are imported but could not be resolved:\\n\\n  ${missingIds\n            .map(\n              (id) =>\n                `${colors.cyan(id)} ${colors.white(\n                  colors.dim(`(imported by ${missing[id]})`),\n                )}`,\n            )\n            .join(`\\n  `)}\\n\\nAre they installed?`,\n        )\n      }\n\n      return deps\n    }),\n  }\n}\n\nexport function toDiscoveredDependencies(\n  environment: Environment,\n  deps: Record<string, string>,\n  timestamp?: string,\n): Record<string, OptimizedDepInfo> {\n  const browserHash = getOptimizedBrowserHash(\n    getDepHash(environment).hash,\n    deps,\n    timestamp,\n  )\n  const discovered: Record<string, OptimizedDepInfo> = {}\n  for (const id in deps) {\n    const src = deps[id]\n    discovered[id] = {\n      id,\n      file: getOptimizedDepPath(environment, id),\n      src,\n      browserHash: browserHash,\n      exportsData: extractExportsData(environment, src),\n    }\n  }\n  return discovered\n}\n\nexport function depsLogString(qualifiedIds: string[]): string {\n  return colors.yellow(qualifiedIds.join(`, `))\n}\n\n/**\n * Internally, Vite uses this function to prepare a optimizeDeps run. When Vite starts, we can get\n * the metadata and start the server without waiting for the optimizeDeps processing to be completed\n */\nexport function runOptimizeDeps(\n  environment: Environment,\n  depsInfo: Record<string, OptimizedDepInfo>,\n): {\n  cancel: () => Promise<void>\n  result: Promise<DepOptimizationResult>\n} {\n  const optimizerContext = { cancelled: false }\n\n  const depsCacheDir = getDepsCacheDir(environment)\n  const processingCacheDir = getProcessingDepsCacheDir(environment)\n\n  // Create a temporary directory so we don't need to delete optimized deps\n  // until they have been processed. This also avoids leaving the deps cache\n  // directory in a corrupted state if there is an error\n  fs.mkdirSync(processingCacheDir, { recursive: true })\n\n  // a hint for Node.js\n  // all files in the cache directory should be recognized as ES modules\n  debug?.(colors.green(`creating package.json in ${processingCacheDir}`))\n  fs.writeFileSync(\n    path.resolve(processingCacheDir, 'package.json'),\n    `{\\n  \"type\": \"module\"\\n}\\n`,\n  )\n\n  const metadata = initDepsOptimizerMetadata(environment)\n\n  metadata.browserHash = getOptimizedBrowserHash(\n    metadata.hash,\n    depsFromOptimizedDepInfo(depsInfo),\n  )\n\n  // We prebundle dependencies with esbuild and cache them, but there is no need\n  // to wait here. Code that needs to access the cached deps needs to await\n  // the optimizedDepInfo.processing promise for each dep\n\n  const qualifiedIds = Object.keys(depsInfo)\n  let cleaned = false\n  let committed = false\n  const cleanUp = () => {\n    // If commit was already called, ignore the clean up even if a cancel was requested\n    // This minimizes the chances of leaving the deps cache in a corrupted state\n    if (!cleaned && !committed) {\n      cleaned = true\n      // No need to wait, we can clean up in the background because temp folders\n      // are unique per run\n      debug?.(colors.green(`removing cache dir ${processingCacheDir}`))\n      try {\n        // When exiting the process, `fsp.rm` may not take effect, so we use `fs.rmSync`\n        fs.rmSync(processingCacheDir, { recursive: true, force: true })\n      } catch {\n        // Ignore errors\n      }\n    }\n  }\n\n  const successfulResult: DepOptimizationResult = {\n    metadata,\n    cancel: cleanUp,\n    commit: async () => {\n      if (cleaned) {\n        throw new Error(\n          'Can not commit a Deps Optimization run as it was cancelled',\n        )\n      }\n      // Ignore clean up requests after this point so the temp folder isn't deleted before\n      // we finish committing the new deps cache files to the deps folder\n      committed = true\n\n      // Write metadata file, then commit the processing folder to the global deps cache\n      // Rewire the file paths from the temporary processing dir to the final deps cache dir\n      const dataPath = path.join(processingCacheDir, METADATA_FILENAME)\n      debug?.(\n        colors.green(`creating ${METADATA_FILENAME} in ${processingCacheDir}`),\n      )\n      fs.writeFileSync(\n        dataPath,\n        stringifyDepsOptimizerMetadata(metadata, depsCacheDir),\n      )\n\n      // In order to minimize the time where the deps folder isn't in a consistent state,\n      // we first rename the old depsCacheDir to a temporary path, then we rename the\n      // new processing cache dir to the depsCacheDir. In systems where doing so in sync\n      // is safe, we do an atomic operation (at least for this thread). For Windows, we\n      // found there are cases where the rename operation may finish before it's done\n      // so we do a graceful rename checking that the folder has been properly renamed.\n      // We found that the rename-rename (then delete the old folder in the background)\n      // is safer than a delete-rename operation.\n      const temporaryPath = depsCacheDir + getTempSuffix()\n      const depsCacheDirPresent = fs.existsSync(depsCacheDir)\n      if (isWindows) {\n        if (depsCacheDirPresent) {\n          debug?.(colors.green(`renaming ${depsCacheDir} to ${temporaryPath}`))\n          await safeRename(depsCacheDir, temporaryPath)\n        }\n        debug?.(\n          colors.green(`renaming ${processingCacheDir} to ${depsCacheDir}`),\n        )\n        await safeRename(processingCacheDir, depsCacheDir)\n      } else {\n        if (depsCacheDirPresent) {\n          debug?.(colors.green(`renaming ${depsCacheDir} to ${temporaryPath}`))\n          fs.renameSync(depsCacheDir, temporaryPath)\n        }\n        debug?.(\n          colors.green(`renaming ${processingCacheDir} to ${depsCacheDir}`),\n        )\n        fs.renameSync(processingCacheDir, depsCacheDir)\n      }\n\n      // Delete temporary path in the background\n      if (depsCacheDirPresent) {\n        debug?.(colors.green(`removing cache temp dir ${temporaryPath}`))\n        fsp.rm(temporaryPath, { recursive: true, force: true })\n      }\n    },\n  }\n\n  if (!qualifiedIds.length) {\n    // No deps to optimize, we still commit the processing cache dir to remove\n    // the previous optimized deps if they exist, and let the next server start\n    // skip the scanner step if the lockfile hasn't changed\n    return {\n      cancel: async () => cleanUp(),\n      result: Promise.resolve(successfulResult),\n    }\n  }\n\n  const cancelledResult: DepOptimizationResult = {\n    metadata,\n    commit: async () => cleanUp(),\n    cancel: cleanUp,\n  }\n\n  const start = performance.now()\n\n  const preparedRun = prepareRolldownOptimizerRun(\n    environment,\n    depsInfo,\n    processingCacheDir,\n    optimizerContext,\n  )\n\n  const runResult = preparedRun.then(({ context, idToExports }) => {\n    if (!context || optimizerContext.cancelled) {\n      return cancelledResult\n    }\n\n    return context\n      .build()\n      .then((result) => {\n        const depForEntryFileName: Record<string, OptimizedDepInfo> = {}\n        for (const dep of Object.values(depsInfo)) {\n          const entryFileName = flattenId(dep.id) + '.js'\n          depForEntryFileName[entryFileName] = dep\n        }\n\n        for (const chunk of result.output) {\n          if (chunk.type !== 'chunk') continue\n\n          if (chunk.isEntry) {\n            const { exportsData, file, id, ...info } =\n              depForEntryFileName[chunk.fileName]\n            addOptimizedDepInfo(metadata, 'optimized', {\n              id,\n              file,\n              ...info,\n              // We only need to hash the chunk.imports in to check for stability, but adding the hash\n              // and file path gives us a unique hash that may be useful for other things in the future\n              fileHash: getHash(\n                metadata.hash + file + JSON.stringify(chunk.imports),\n              ),\n              browserHash: metadata.browserHash,\n              // After bundling we have more information and can warn the user about legacy packages\n              // that require manual configuration\n              needsInterop: needsInterop(\n                environment,\n                id,\n                idToExports[id],\n                chunk,\n              ),\n            })\n          } else {\n            const id = chunk.fileName.replace(jsExtensionRE, '')\n            const file = normalizePath(\n              path.resolve(getDepsCacheDir(environment), chunk.fileName),\n            )\n            if (\n              !findOptimizedDepInfoInRecord(\n                metadata.optimized,\n                (depInfo) => depInfo.file === file,\n              )\n            ) {\n              addOptimizedDepInfo(metadata, 'chunks', {\n                id,\n                file,\n                needsInterop: false,\n                browserHash: metadata.browserHash,\n                isDynamicEntry: chunk.isDynamicEntry,\n              })\n            }\n          }\n        }\n\n        debug?.(\n          `Dependencies bundled in ${(performance.now() - start).toFixed(2)}ms`,\n        )\n\n        return successfulResult\n      })\n\n      .catch((e) => {\n        if (e.errors && e.message.includes('The build was canceled')) {\n          // an error happens when cancelling, but this is expected so\n          // return an empty result instead\n          return cancelledResult\n        }\n        const prependMessage = colors.red(\n          'Error during dependency optimization:\\n\\n',\n        )\n        e.message = prependMessage + e.message\n        throw e\n      })\n  })\n\n  runResult.catch(() => {\n    cleanUp()\n  })\n\n  return {\n    async cancel() {\n      optimizerContext.cancelled = true\n      const { context } = await preparedRun\n      context?.cancel()\n      cleanUp()\n    },\n    result: runResult,\n  }\n}\n\nasync function prepareRolldownOptimizerRun(\n  environment: Environment,\n  depsInfo: Record<string, OptimizedDepInfo>,\n  processingCacheDir: string,\n  optimizerContext: { cancelled: boolean },\n): Promise<{\n  context?: { build: () => Promise<RolldownOutput>; cancel: () => void }\n  idToExports: Record<string, ExportsData>\n}> {\n  // esbuild generates nested directory output with lowest common ancestor base\n  // this is unpredictable and makes it difficult to analyze entry / output\n  // mapping. So what we do here is:\n  // 1. flatten all ids to eliminate slash\n  // 2. in the plugin, read the entry ourselves as virtual files to retain the\n  //    path.\n  const flatIdDeps: Record<string, string> = {}\n  const idToExports: Record<string, ExportsData> = {}\n\n  const { optimizeDeps } = environment.config\n\n  const { plugins: pluginsFromConfig = [], ...rolldownOptions } =\n    optimizeDeps.rolldownOptions ?? {}\n\n  let jsxLoader = false\n  await Promise.all(\n    Object.keys(depsInfo).map(async (id) => {\n      const src = depsInfo[id].src!\n      const exportsData = await (depsInfo[id].exportsData ??\n        extractExportsData(environment, src))\n      if (exportsData.jsxLoader) {\n        // Ensure that optimization won't fail by defaulting '.js' to the JSX parser.\n        // This is useful for packages such as Gatsby.\n        jsxLoader = true\n      }\n      const flatId = flattenId(id)\n      flatIdDeps[flatId] = isWindows ? src.replaceAll('/', '\\\\') : src\n      idToExports[id] = exportsData\n    }),\n  )\n\n  if (optimizerContext.cancelled) return { context: undefined, idToExports }\n\n  const define = {\n    'process.env.NODE_ENV': environment.config.keepProcessEnv\n      ? // define process.env.NODE_ENV even for keepProcessEnv === true\n        // as esbuild will replace it automatically when `platform` is `'browser'`\n        'process.env.NODE_ENV'\n      : JSON.stringify(process.env.NODE_ENV || environment.config.mode),\n    ...rolldownOptions.transform?.define,\n  }\n\n  const platform =\n    optimizeDeps.rolldownOptions?.platform ??\n    // We generally don't want to use platform 'neutral', as esbuild has custom handling\n    // when the platform is 'node' or 'browser' that can't be emulated by using mainFields\n    // and conditions\n    (environment.config.consumer === 'client' ||\n    environment.config.ssr.target === 'webworker'\n      ? 'browser'\n      : 'node')\n\n  const external = [...(optimizeDeps.exclude ?? [])]\n\n  const plugins = await asyncFlatten(arraify(pluginsFromConfig))\n  if (external.length) {\n    plugins.push(rolldownCjsExternalPlugin(external, platform))\n  }\n  plugins.push(...rolldownDepPlugin(environment, flatIdDeps, external))\n\n  let canceled = false\n  async function build() {\n    const bundle = await rolldown({\n      ...rolldownOptions,\n      input: flatIdDeps,\n      logLevel: 'silent',\n      plugins,\n      platform,\n      transform: {\n        ...rolldownOptions.transform,\n        target: ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET,\n        define,\n      },\n      resolve: {\n        extensions: ['.tsx', '.ts', '.jsx', '.js', '.css', '.json'],\n        ...rolldownOptions.resolve,\n      },\n      // TODO: remove this and enable rolldown's CSS support later\n      moduleTypes: {\n        '.css': 'js',\n        ...rolldownOptions.moduleTypes,\n        ...(jsxLoader ? { '.js': 'jsx' } : {}),\n      },\n    })\n    if (canceled) {\n      await bundle.close()\n      throw new Error('The build was canceled')\n    }\n    const result = await bundle.write({\n      ...rolldownOptions.output,\n      format: 'esm',\n      sourcemap: true,\n      dir: processingCacheDir,\n      entryFileNames: '[name].js',\n    })\n    await bundle.close()\n    return result\n  }\n\n  function cancel() {\n    canceled = true\n  }\n\n  return { context: { build, cancel }, idToExports }\n}\n\nexport async function addManuallyIncludedOptimizeDeps(\n  environment: Environment,\n  deps: Record<string, string>,\n): Promise<void> {\n  const { logger } = environment\n  const { optimizeDeps } = environment.config\n  const optimizeDepsInclude = optimizeDeps.include ?? []\n  if (optimizeDepsInclude.length) {\n    const unableToOptimize = (id: string, msg: string) => {\n      if (optimizeDepsInclude.includes(id)) {\n        logger.warn(\n          `${msg}: ${colors.cyan(id)}, present in ${environment.name} 'optimizeDeps.include'`,\n        )\n      }\n    }\n\n    const includes = [...optimizeDepsInclude]\n    for (let i = 0; i < includes.length; i++) {\n      const id = includes[i]\n      if (isDynamicPattern(id)) {\n        const globIds = expandGlobIds(id, environment.getTopLevelConfig())\n        includes.splice(i, 1, ...globIds)\n        i += globIds.length - 1\n      }\n    }\n\n    const resolve = createOptimizeDepsIncludeResolver(environment)\n    for (const id of includes) {\n      // normalize 'foo   >bar` as 'foo > bar' to prevent same id being added\n      // and for pretty printing\n      const normalizedId = normalizeId(id)\n      if (!deps[normalizedId]) {\n        const entry = await resolve(id)\n        if (entry) {\n          if (isOptimizable(entry, optimizeDeps)) {\n            deps[normalizedId] = entry\n          } else {\n            unableToOptimize(id, 'Cannot optimize dependency')\n          }\n        } else {\n          unableToOptimize(id, 'Failed to resolve dependency')\n        }\n      }\n    }\n  }\n}\n\n// Convert to { id: src }\nexport function depsFromOptimizedDepInfo(\n  depsInfo: Record<string, OptimizedDepInfo>,\n): Record<string, string> {\n  const obj: Record<string, string> = {}\n  for (const key in depsInfo) {\n    obj[key] = depsInfo[key].src!\n  }\n  return obj\n}\n\nexport function getOptimizedDepPath(\n  environment: Environment,\n  id: string,\n): string {\n  return normalizePath(\n    path.resolve(getDepsCacheDir(environment), flattenId(id) + '.js'),\n  )\n}\n\nfunction getDepsCacheSuffix(environment: Environment): string {\n  return environment.name === 'client' ? '' : `_${environment.name}`\n}\n\nexport function getDepsCacheDir(environment: Environment): string {\n  return getDepsCacheDirPrefix(environment) + getDepsCacheSuffix(environment)\n}\n\nfunction getProcessingDepsCacheDir(environment: Environment) {\n  return (\n    getDepsCacheDirPrefix(environment) +\n    getDepsCacheSuffix(environment) +\n    getTempSuffix()\n  )\n}\n\nfunction getTempSuffix() {\n  return (\n    '_temp_' +\n    getHash(\n      `${process.pid}:${Date.now().toString()}:${Math.random()\n        .toString(16)\n        .slice(2)}`,\n    )\n  )\n}\n\nfunction getDepsCacheDirPrefix(environment: Environment): string {\n  return normalizePath(path.resolve(environment.config.cacheDir, 'deps'))\n}\n\nexport function createIsOptimizedDepFile(\n  environment: Environment,\n): (id: string) => boolean {\n  const depsCacheDirPrefix = getDepsCacheDirPrefix(environment)\n  return (id) => id.startsWith(depsCacheDirPrefix)\n}\n\nexport function createIsOptimizedDepUrl(\n  environment: Environment,\n): (url: string) => boolean {\n  const { root } = environment.config\n  const depsCacheDir = getDepsCacheDirPrefix(environment)\n\n  // determine the url prefix of files inside cache directory\n  const depsCacheDirRelative = normalizePath(path.relative(root, depsCacheDir))\n  const depsCacheDirPrefix = depsCacheDirRelative.startsWith('../')\n    ? // if the cache directory is outside root, the url prefix would be something\n      // like '/@fs/absolute/path/to/node_modules/.vite'\n      `/@fs/${removeLeadingSlash(normalizePath(depsCacheDir))}`\n    : // if the cache directory is inside root, the url prefix would be something\n      // like '/node_modules/.vite'\n      `/${depsCacheDirRelative}`\n\n  return function isOptimizedDepUrl(url: string): boolean {\n    return url.startsWith(depsCacheDirPrefix)\n  }\n}\n\nfunction parseDepsOptimizerMetadata(\n  jsonMetadata: string,\n  depsCacheDir: string,\n): DepOptimizationMetadata | undefined {\n  const { hash, lockfileHash, configHash, browserHash, optimized, chunks } =\n    JSON.parse(jsonMetadata, (key: string, value: string) => {\n      // Paths can be absolute or relative to the deps cache dir where\n      // the _metadata.json is located\n      if (key === 'file' || key === 'src') {\n        return normalizePath(path.resolve(depsCacheDir, value))\n      }\n      return value\n    })\n  if (\n    !chunks ||\n    Object.values(optimized).some((depInfo: any) => !depInfo.fileHash)\n  ) {\n    // outdated _metadata.json version, ignore\n    return\n  }\n  const metadata = {\n    hash,\n    lockfileHash,\n    configHash,\n    browserHash,\n    optimized: {},\n    discovered: {},\n    chunks: {},\n    depInfoList: [],\n  }\n  for (const id of Object.keys(optimized)) {\n    addOptimizedDepInfo(metadata, 'optimized', {\n      ...optimized[id],\n      id,\n      browserHash,\n    })\n  }\n  for (const id of Object.keys(chunks)) {\n    addOptimizedDepInfo(metadata, 'chunks', {\n      ...chunks[id],\n      id,\n      browserHash,\n      needsInterop: false,\n    })\n  }\n  return metadata\n}\n\n/**\n * Stringify metadata for deps cache. Remove processing promises\n * and individual dep info browserHash. Once the cache is reload\n * the next time the server start we need to use the global\n * browserHash to allow long term caching\n */\nfunction stringifyDepsOptimizerMetadata(\n  metadata: DepOptimizationMetadata,\n  depsCacheDir: string,\n) {\n  const { hash, configHash, lockfileHash, browserHash, optimized, chunks } =\n    metadata\n  return JSON.stringify(\n    {\n      hash,\n      configHash,\n      lockfileHash,\n      browserHash,\n      optimized: Object.fromEntries(\n        Object.values(optimized).map(\n          ({ id, src, file, fileHash, needsInterop, isDynamicEntry }) => [\n            id,\n            {\n              src,\n              file,\n              fileHash,\n              needsInterop,\n              isDynamicEntry,\n            },\n          ],\n        ),\n      ),\n      chunks: Object.fromEntries(\n        Object.values(chunks).map(({ id, file, isDynamicEntry }) => [\n          id,\n          { file, isDynamicEntry },\n        ]),\n      ),\n    },\n    (key: string, value: string) => {\n      // Paths can be absolute or relative to the deps cache dir where\n      // the _metadata.json is located\n      if (key === 'file' || key === 'src') {\n        return normalizePath(path.relative(depsCacheDir, value))\n      }\n      return value\n    },\n    2,\n  )\n}\n\nexport async function extractExportsData(\n  environment: Environment,\n  filePath: string,\n): Promise<ExportsData> {\n  await init\n\n  const { optimizeDeps } = environment.config\n\n  const rolldownOptions = optimizeDeps.rolldownOptions ?? {}\n  if (optimizeDeps.extensions?.some((ext) => filePath.endsWith(ext))) {\n    // For custom supported extensions, build the entry file to transform it into JS,\n    // and then parse with es-module-lexer. Note that the `bundle` option is not `true`,\n    // so only the entry file is being transformed.\n    const { plugins: pluginsFromConfig = [], ...remainingRolldownOptions } =\n      rolldownOptions\n    const plugins = await asyncFlatten(arraify(pluginsFromConfig))\n    plugins.unshift({\n      name: 'externalize',\n      resolveId(id, importer) {\n        if (importer !== undefined) {\n          return { id, external: true }\n        }\n      },\n    })\n    const build = await rolldown({\n      ...remainingRolldownOptions,\n      plugins,\n      input: [filePath],\n      // TODO: remove this and enable rolldown's CSS support later\n      moduleTypes: {\n        '.css': 'js',\n        ...remainingRolldownOptions.moduleTypes,\n      },\n    })\n    const result = await build.generate({\n      ...rolldownOptions.output,\n      format: 'esm',\n      sourcemap: false,\n    })\n    const [, exports, , hasModuleSyntax] = parse(result.output[0].code)\n    return {\n      hasModuleSyntax,\n      exports: exports.map((e) => e.n),\n    }\n  }\n\n  let parseResult: ReturnType<typeof parse>\n  let usedJsxLoader = false\n\n  const entryContent = fs.readFileSync(filePath, 'utf-8')\n  try {\n    parseResult = parse(entryContent)\n  } catch {\n    const lang = rolldownOptions.moduleTypes?.[path.extname(filePath)] || 'jsx'\n    debug?.(\n      `Unable to parse: ${filePath}.\\n Trying again with a ${lang} transform.`,\n    )\n    if (lang !== 'jsx' && lang !== 'tsx' && lang !== 'ts') {\n      throw new Error(`Unable to parse : ${filePath}.`)\n    }\n    const transformed = await transformWithOxc(\n      entryContent,\n      filePath,\n      { lang },\n      undefined,\n      environment.config,\n    )\n    parseResult = parse(transformed.code)\n    usedJsxLoader = true\n  }\n\n  const [, exports, , hasModuleSyntax] = parseResult\n  const exportsData: ExportsData = {\n    hasModuleSyntax,\n    exports: exports.map((e) => e.n),\n    jsxLoader: usedJsxLoader,\n  }\n  return exportsData\n}\n\nfunction needsInterop(\n  environment: Environment,\n  id: string,\n  exportsData: ExportsData,\n  output?: { exports: string[] },\n): boolean {\n  if (environment.config.optimizeDeps.needsInterop?.includes(id)) {\n    return true\n  }\n  const { hasModuleSyntax, exports } = exportsData\n  // entry has no ESM syntax - likely CJS or UMD\n  if (!hasModuleSyntax) {\n    return true\n  }\n\n  if (output) {\n    // if a peer dependency used require() on an ESM dependency, esbuild turns the\n    // ESM dependency's entry chunk into a single default export... detect\n    // such cases by checking exports mismatch, and force interop.\n    const generatedExports: string[] = output.exports\n\n    if (\n      isSingleDefaultExport(generatedExports) &&\n      !isSingleDefaultExport(exports)\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\nfunction isSingleDefaultExport(exports: readonly string[]) {\n  return exports.length === 1 && exports[0] === 'default'\n}\n\nconst lockfileFormats = [\n  {\n    path: 'node_modules/.package-lock.json',\n    checkPatchesDir: 'patches',\n    manager: 'npm',\n  },\n  {\n    // Yarn non-PnP\n    path: 'node_modules/.yarn-state.yml',\n    checkPatchesDir: false,\n    manager: 'yarn',\n  },\n  {\n    // Yarn v3+ PnP\n    path: '.pnp.cjs',\n    checkPatchesDir: '.yarn/patches',\n    manager: 'yarn',\n  },\n  {\n    // Yarn v2 PnP\n    path: '.pnp.js',\n    checkPatchesDir: '.yarn/patches',\n    manager: 'yarn',\n  },\n  {\n    // yarn 1\n    path: 'node_modules/.yarn-integrity',\n    checkPatchesDir: 'patches',\n    manager: 'yarn',\n  },\n  {\n    path: 'node_modules/.pnpm/lock.yaml',\n    // Included in lockfile\n    checkPatchesDir: false,\n    manager: 'pnpm',\n  },\n  {\n    path: '.rush/temp/shrinkwrap-deps.json',\n    // Included in lockfile\n    checkPatchesDir: false,\n    manager: 'pnpm',\n  },\n  {\n    path: 'bun.lock',\n    checkPatchesDir: 'patches',\n    manager: 'bun',\n  },\n  {\n    path: 'bun.lockb',\n    checkPatchesDir: 'patches',\n    manager: 'bun',\n  },\n].sort((_, { manager }) => {\n  return process.env.npm_config_user_agent?.startsWith(manager) ? 1 : -1\n})\nconst lockfilePaths = lockfileFormats.map((l) => l.path)\n\nfunction getConfigHash(environment: Environment): string {\n  // Take config into account\n  // only a subset of config options that can affect dep optimization\n  const { config } = environment\n  const { optimizeDeps } = config\n  const content = JSON.stringify(\n    {\n      define: !config.keepProcessEnv\n        ? process.env.NODE_ENV || config.mode\n        : null,\n      root: config.root,\n      resolve: config.resolve,\n      assetsInclude: config.assetsInclude,\n      plugins: config.plugins.map((p) => p.name),\n      optimizeDeps: {\n        include: optimizeDeps.include\n          ? unique(optimizeDeps.include).sort()\n          : undefined,\n        exclude: optimizeDeps.exclude\n          ? unique(optimizeDeps.exclude).sort()\n          : undefined,\n        rolldownOptions: {\n          ...optimizeDeps.rolldownOptions,\n          plugins: undefined, // included in optimizeDepsPluginNames\n          onLog: undefined,\n          onwarn: undefined,\n          checks: undefined,\n          output: {\n            ...optimizeDeps.rolldownOptions?.output,\n            plugins: undefined, // included in optimizeDepsPluginNames\n          },\n        },\n      },\n      optimizeDepsPluginNames: config.optimizeDepsPluginNames,\n    },\n    (_, value) => {\n      if (typeof value === 'function' || value instanceof RegExp) {\n        return value.toString()\n      }\n      return value\n    },\n  )\n  return getHash(content)\n}\n\nfunction getLockfileHash(environment: Environment): string {\n  const lockfilePath = lookupFile(environment.config.root, lockfilePaths)\n  let content = lockfilePath ? fs.readFileSync(lockfilePath, 'utf-8') : ''\n  if (lockfilePath) {\n    const normalizedLockfilePath = lockfilePath.replaceAll('\\\\', '/')\n    const lockfileFormat = lockfileFormats.find((f) =>\n      normalizedLockfilePath.endsWith(f.path),\n    )!\n    if (lockfileFormat.checkPatchesDir) {\n      // Default of https://github.com/ds300/patch-package\n      const baseDir = lockfilePath.slice(0, -lockfileFormat.path.length)\n      const fullPath = path.join(\n        baseDir,\n        lockfileFormat.checkPatchesDir as string,\n      )\n      const stat = tryStatSync(fullPath)\n      if (stat?.isDirectory()) {\n        content += stat.mtimeMs.toString()\n      }\n    }\n  }\n  return getHash(content)\n}\n\nfunction getDepHash(environment: Environment): {\n  lockfileHash: string\n  configHash: string\n  hash: string\n} {\n  const lockfileHash = getLockfileHash(environment)\n  const configHash = getConfigHash(environment)\n  const hash = getHash(lockfileHash + configHash)\n  return {\n    hash,\n    lockfileHash,\n    configHash,\n  }\n}\n\nfunction getOptimizedBrowserHash(\n  hash: string,\n  deps: Record<string, string>,\n  timestamp = '',\n) {\n  return getHash(hash + JSON.stringify(deps) + timestamp)\n}\n\nexport function optimizedDepInfoFromId(\n  metadata: DepOptimizationMetadata,\n  id: string,\n): OptimizedDepInfo | undefined {\n  return (\n    metadata.optimized[id] || metadata.discovered[id] || metadata.chunks[id]\n  )\n}\n\nexport function optimizedDepInfoFromFile(\n  metadata: DepOptimizationMetadata,\n  file: string,\n): OptimizedDepInfo | undefined {\n  return metadata.depInfoList.find((depInfo) => depInfo.file === file)\n}\n\nfunction findOptimizedDepInfoInRecord(\n  dependenciesInfo: Record<string, OptimizedDepInfo>,\n  callbackFn: (depInfo: OptimizedDepInfo, id: string) => any,\n): OptimizedDepInfo | undefined {\n  for (const o of Object.keys(dependenciesInfo)) {\n    const info = dependenciesInfo[o]\n    if (callbackFn(info, o)) {\n      return info\n    }\n  }\n}\n\nexport async function optimizedDepNeedsInterop(\n  environment: Environment,\n  metadata: DepOptimizationMetadata,\n  file: string,\n): Promise<boolean | undefined> {\n  const depInfo = optimizedDepInfoFromFile(metadata, file)\n  if (depInfo?.src && depInfo.needsInterop === undefined) {\n    depInfo.exportsData ??= extractExportsData(environment, depInfo.src)\n    depInfo.needsInterop = needsInterop(\n      environment,\n      depInfo.id,\n      await depInfo.exportsData,\n    )\n  }\n  return depInfo?.needsInterop\n}\n\nconst MAX_TEMP_DIR_AGE_MS = 24 * 60 * 60 * 1000\nexport async function cleanupDepsCacheStaleDirs(\n  config: ResolvedConfig,\n): Promise<void> {\n  try {\n    const cacheDir = path.resolve(config.cacheDir)\n    if (fs.existsSync(cacheDir)) {\n      const dirents = await fsp.readdir(cacheDir, { withFileTypes: true })\n      for (const dirent of dirents) {\n        if (dirent.isDirectory() && dirent.name.includes('_temp_')) {\n          const tempDirPath = path.resolve(config.cacheDir, dirent.name)\n          const stats = await fsp.stat(tempDirPath).catch(() => null)\n          if (\n            stats?.mtime &&\n            Date.now() - stats.mtime.getTime() > MAX_TEMP_DIR_AGE_MS\n          ) {\n            debug?.(`removing stale cache temp dir ${tempDirPath}`)\n            await fsp.rm(tempDirPath, { recursive: true, force: true })\n          }\n        }\n      }\n    }\n  } catch (err) {\n    config.logger.error(err)\n  }\n}\n\n// We found issues with renaming folders in some systems. This is a custom\n// implementation for the optimizer. It isn't intended to be a general utility\n\n// Based on node-graceful-fs\n\n// The ISC License\n// Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors\n// https://github.com/isaacs/node-graceful-fs/blob/main/LICENSE\n\n// On Windows, A/V software can lock the directory, causing this\n// to fail with an EACCES or EPERM if the directory contains newly\n// created files. The original tried for up to 60 seconds, we only\n// wait for 5 seconds, as a longer time would be seen as an error\n\nconst GRACEFUL_RENAME_TIMEOUT = 5000\nconst safeRename = promisify(function gracefulRename(\n  from: string,\n  to: string,\n  cb: (error: NodeJS.ErrnoException | null) => void,\n) {\n  const start = Date.now()\n  let backoff = 0\n  fs.rename(from, to, function CB(er) {\n    if (\n      er &&\n      (er.code === 'EACCES' || er.code === 'EPERM') &&\n      Date.now() - start < GRACEFUL_RENAME_TIMEOUT\n    ) {\n      setTimeout(function () {\n        fs.stat(to, function (stater, _st) {\n          if (stater && stater.code === 'ENOENT') fs.rename(from, to, CB)\n          else CB(er)\n        })\n      }, backoff)\n      if (backoff < 100) backoff += 10\n      return\n    }\n    cb(er)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/optimizer/optimizer.ts",
    "content": "import colors from 'picocolors'\nimport { createDebugger, getHash } from '../utils'\nimport {\n  type PromiseWithResolvers,\n  promiseWithResolvers,\n} from '../../shared/utils'\nimport type { DevEnvironment } from '../server/environment'\nimport { devToScanEnvironment } from './scan'\nimport {\n  addManuallyIncludedOptimizeDeps,\n  addOptimizedDepInfo,\n  createIsOptimizedDepFile,\n  createIsOptimizedDepUrl,\n  depsFromOptimizedDepInfo,\n  depsLogString,\n  discoverProjectDependencies,\n  extractExportsData,\n  getOptimizedDepPath,\n  initDepsOptimizerMetadata,\n  loadCachedDepOptimizationMetadata,\n  optimizeExplicitEnvironmentDeps,\n  runOptimizeDeps,\n  toDiscoveredDependencies,\n} from './index'\nimport type {\n  DepOptimizationMetadata,\n  DepOptimizationResult,\n  DepsOptimizer,\n  OptimizedDepInfo,\n} from './index'\n\nconst debug = createDebugger('vite:deps')\n\n/**\n * The amount to wait for requests to register newly found dependencies before triggering\n * a re-bundle + page reload\n */\nconst debounceMs = 100\n\nexport function createDepsOptimizer(\n  environment: DevEnvironment,\n): DepsOptimizer {\n  const { logger } = environment\n  const sessionTimestamp = Date.now().toString()\n\n  let debounceProcessingHandle: NodeJS.Timeout | undefined\n\n  let closed = false\n\n  const options = environment.config.optimizeDeps\n\n  const { noDiscovery, holdUntilCrawlEnd } = options\n\n  let metadata: DepOptimizationMetadata = initDepsOptimizerMetadata(\n    environment,\n    sessionTimestamp,\n  )\n\n  const depsOptimizer: DepsOptimizer = {\n    init,\n    metadata,\n    registerMissingImport,\n    run: () => debouncedProcessing(0),\n    isOptimizedDepFile: createIsOptimizedDepFile(environment),\n    isOptimizedDepUrl: createIsOptimizedDepUrl(environment),\n    getOptimizedDepId: (depInfo: OptimizedDepInfo) =>\n      `${depInfo.file}?v=${depInfo.browserHash}`,\n    close,\n    options,\n  }\n\n  let newDepsDiscovered = false\n\n  let newDepsToLog: string[] = []\n  let newDepsToLogHandle: NodeJS.Timeout | undefined\n  const logNewlyDiscoveredDeps = () => {\n    if (newDepsToLog.length) {\n      logger.info(\n        colors.green(\n          `✨ new dependencies optimized: ${depsLogString(newDepsToLog)}`,\n        ),\n        {\n          timestamp: true,\n        },\n      )\n      newDepsToLog = []\n    }\n  }\n\n  let discoveredDepsWhileScanning: string[] = []\n  const logDiscoveredDepsWhileScanning = () => {\n    if (discoveredDepsWhileScanning.length) {\n      logger.info(\n        colors.green(\n          `✨ discovered while scanning: ${depsLogString(\n            discoveredDepsWhileScanning,\n          )}`,\n        ),\n        {\n          timestamp: true,\n        },\n      )\n      discoveredDepsWhileScanning = []\n    }\n  }\n\n  let depOptimizationProcessing = promiseWithResolvers<void>()\n  let depOptimizationProcessingQueue: PromiseWithResolvers<void>[] = []\n  const resolveEnqueuedProcessingPromises = () => {\n    // Resolve all the processings (including the ones which were delayed)\n    for (const processing of depOptimizationProcessingQueue) {\n      processing.resolve()\n    }\n    depOptimizationProcessingQueue = []\n  }\n\n  let enqueuedRerun: (() => void) | undefined\n  let currentlyProcessing = false\n\n  let firstRunCalled = false\n  let warnAboutMissedDependencies = false\n\n  // If this is a cold run, we wait for static imports discovered\n  // from the first request before resolving to minimize full page reloads.\n  // On warm start or after the first optimization is run, we use a simpler\n  // debounce strategy each time a new dep is discovered.\n  let waitingForCrawlEnd = false\n\n  let optimizationResult:\n    | {\n        cancel: () => Promise<void>\n        result: Promise<DepOptimizationResult>\n      }\n    | undefined\n\n  let discover:\n    | {\n        cancel: () => Promise<void>\n        result: Promise<Record<string, string>>\n      }\n    | undefined\n\n  async function close() {\n    closed = true\n    await Promise.allSettled([\n      discover?.cancel(),\n      depsOptimizer.scanProcessing,\n      optimizationResult?.cancel(),\n    ])\n  }\n\n  let inited = false\n  async function init() {\n    if (inited) return\n    inited = true\n\n    const cachedMetadata = await loadCachedDepOptimizationMetadata(environment)\n\n    firstRunCalled = !!cachedMetadata\n\n    metadata = depsOptimizer.metadata =\n      cachedMetadata || initDepsOptimizerMetadata(environment, sessionTimestamp)\n\n    if (!cachedMetadata) {\n      waitingForCrawlEnd = true\n\n      // Enter processing state until crawl of static imports ends\n      currentlyProcessing = true\n\n      // Initialize discovered deps with manually added optimizeDeps.include info\n\n      const manuallyIncludedDeps: Record<string, string> = {}\n      await addManuallyIncludedOptimizeDeps(environment, manuallyIncludedDeps)\n\n      const manuallyIncludedDepsInfo = toDiscoveredDependencies(\n        environment,\n        manuallyIncludedDeps,\n        sessionTimestamp,\n      )\n\n      for (const depInfo of Object.values(manuallyIncludedDepsInfo)) {\n        addOptimizedDepInfo(metadata, 'discovered', {\n          ...depInfo,\n          processing: depOptimizationProcessing.promise,\n        })\n        newDepsDiscovered = true\n      }\n\n      environment.waitForRequestsIdle().then(onCrawlEnd)\n\n      if (noDiscovery) {\n        // We don't need to scan for dependencies or wait for the static crawl to end\n        // Run the first optimization run immediately\n        runOptimizer()\n      } else {\n        // Important, the scanner is dev only\n        depsOptimizer.scanProcessing = new Promise((resolve) => {\n          // Runs in the background in case blocking high priority tasks\n          ;(async () => {\n            try {\n              debug?.(colors.green(`scanning for dependencies...`))\n\n              let deps: Record<string, string>\n              try {\n                discover = discoverProjectDependencies(\n                  devToScanEnvironment(environment),\n                )\n                deps = await discover.result\n                discover = undefined\n              } catch (e) {\n                environment.logger.error(\n                  colors.red(\n                    '(!) Failed to run dependency scan. ' +\n                      'Skipping dependency pre-bundling. ' +\n                      e.stack,\n                  ),\n                )\n                return\n              }\n\n              const manuallyIncluded = Object.keys(manuallyIncludedDepsInfo)\n              discoveredDepsWhileScanning.push(\n                ...Object.keys(metadata.discovered).filter(\n                  (dep) => !deps[dep] && !manuallyIncluded.includes(dep),\n                ),\n              )\n\n              // Add these dependencies to the discovered list, as these are currently\n              // used by the preAliasPlugin to support aliased and optimized deps.\n              // This is also used by the CJS externalization heuristics in legacy mode\n              for (const id of Object.keys(deps)) {\n                if (!metadata.discovered[id]) {\n                  addMissingDep(id, deps[id])\n                }\n              }\n\n              const knownDeps = prepareKnownDeps()\n              startNextDiscoveredBatch()\n\n              // For dev, we run the scanner and the first optimization\n              // run on the background\n              optimizationResult = runOptimizeDeps(environment, knownDeps)\n\n              // If the holdUntilCrawlEnd strategy is used, we wait until crawling has\n              // ended to decide if we send this result to the browser or we need to\n              // do another optimize step\n              if (!holdUntilCrawlEnd) {\n                // If not, we release the result to the browser as soon as the scanner\n                // is done. If the scanner missed any dependency, and a new dependency\n                // is discovered while crawling static imports, then there will be a\n                // full-page reload if new common chunks are generated between the old\n                // and new optimized deps.\n                optimizationResult.result.then((result) => {\n                  // Check if the crawling of static imports has already finished. In that\n                  // case, the result is handled by the onCrawlEnd callback\n                  if (!waitingForCrawlEnd) return\n\n                  optimizationResult = undefined // signal that we'll be using the result\n\n                  runOptimizer(result)\n                })\n              }\n            } catch (e) {\n              logger.error(e.stack || e.message)\n            } finally {\n              resolve()\n              depsOptimizer.scanProcessing = undefined\n            }\n          })()\n        })\n      }\n    }\n  }\n\n  function startNextDiscoveredBatch() {\n    newDepsDiscovered = false\n\n    // Add the current depOptimizationProcessing to the queue, these\n    // promises are going to be resolved once a rerun is committed\n    depOptimizationProcessingQueue.push(depOptimizationProcessing)\n\n    // Create a new promise for the next rerun, discovered missing\n    // dependencies will be assigned this promise from this point\n    depOptimizationProcessing = promiseWithResolvers()\n  }\n\n  function prepareKnownDeps() {\n    const knownDeps: Record<string, OptimizedDepInfo> = {}\n    // Clone optimized info objects, fileHash, browserHash may be changed for them\n    const metadata = depsOptimizer.metadata!\n    for (const dep of Object.keys(metadata.optimized)) {\n      knownDeps[dep] = { ...metadata.optimized[dep] }\n    }\n    for (const dep of Object.keys(metadata.discovered)) {\n      // Clone the discovered info discarding its processing promise\n      const { processing, ...info } = metadata.discovered[dep]\n      knownDeps[dep] = info\n    }\n    return knownDeps\n  }\n\n  async function runOptimizer(preRunResult?: DepOptimizationResult) {\n    // a successful completion of the optimizeDeps rerun will end up\n    // creating new bundled version of all current and discovered deps\n    // in the cache dir and a new metadata info object assigned\n    // to _metadata. A fullReload is only issued if the previous bundled\n    // dependencies have changed.\n\n    // if the rerun fails, _metadata remains untouched, current discovered\n    // deps are cleaned, and a fullReload is issued\n\n    // All deps, previous known and newly discovered are rebundled,\n    // respect insertion order to keep the metadata file stable\n\n    const isRerun = firstRunCalled\n    firstRunCalled = true\n\n    // Ensure that rerun is called sequentially\n    enqueuedRerun = undefined\n\n    // Ensure that a rerun will not be issued for current discovered deps\n    if (debounceProcessingHandle) clearTimeout(debounceProcessingHandle)\n\n    if (closed) {\n      currentlyProcessing = false\n      depOptimizationProcessing.resolve()\n      resolveEnqueuedProcessingPromises()\n      return\n    }\n\n    currentlyProcessing = true\n\n    try {\n      let processingResult: DepOptimizationResult\n      if (preRunResult) {\n        processingResult = preRunResult\n      } else {\n        const knownDeps = prepareKnownDeps()\n        startNextDiscoveredBatch()\n\n        optimizationResult = runOptimizeDeps(environment, knownDeps)\n        processingResult = await optimizationResult.result\n        optimizationResult = undefined\n      }\n\n      if (closed) {\n        currentlyProcessing = false\n        processingResult.cancel()\n        resolveEnqueuedProcessingPromises()\n        return\n      }\n\n      const newData = processingResult.metadata\n\n      const needsInteropMismatch = findInteropMismatches(\n        metadata.discovered,\n        newData.optimized,\n      )\n\n      // After a re-optimization, if the internal bundled chunks change a full page reload\n      // is required. If the files are stable, we can avoid the reload that is expensive\n      // for large applications. Comparing their fileHash we can find out if it is safe to\n      // keep the current browser state.\n      const needsReload =\n        needsInteropMismatch.length > 0 ||\n        metadata.hash !== newData.hash ||\n        Object.keys(metadata.optimized).some((dep) => {\n          return (\n            metadata.optimized[dep].fileHash !== newData.optimized[dep].fileHash\n          )\n        })\n\n      const commitProcessing = async () => {\n        await processingResult.commit()\n\n        // While optimizeDeps is running, new missing deps may be discovered,\n        // in which case they will keep being added to metadata.discovered\n        for (const id in metadata.discovered) {\n          if (!newData.optimized[id]) {\n            addOptimizedDepInfo(newData, 'discovered', metadata.discovered[id])\n          }\n        }\n\n        // If we don't reload the page, we need to keep browserHash stable\n        if (!needsReload) {\n          newData.browserHash = metadata.browserHash\n          for (const dep in newData.chunks) {\n            newData.chunks[dep].browserHash = metadata.browserHash\n          }\n          for (const dep in newData.optimized) {\n            newData.optimized[dep].browserHash = (\n              metadata.optimized[dep] || metadata.discovered[dep]\n            ).browserHash\n          }\n        }\n\n        // Commit hash and needsInterop changes to the discovered deps info\n        // object. Allow for code to await for the discovered processing promise\n        // and use the information in the same object\n        for (const o in newData.optimized) {\n          const discovered = metadata.discovered[o]\n          if (discovered) {\n            const optimized = newData.optimized[o]\n            discovered.browserHash = optimized.browserHash\n            discovered.fileHash = optimized.fileHash\n            discovered.needsInterop = optimized.needsInterop\n            discovered.processing = undefined\n          }\n        }\n\n        if (isRerun) {\n          newDepsToLog.push(\n            ...Object.keys(newData.optimized).filter(\n              (dep) => !metadata.optimized[dep],\n            ),\n          )\n        }\n\n        metadata = depsOptimizer.metadata = newData\n        resolveEnqueuedProcessingPromises()\n      }\n\n      if (!needsReload) {\n        await commitProcessing()\n\n        if (!debug) {\n          if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle)\n          newDepsToLogHandle = setTimeout(() => {\n            newDepsToLogHandle = undefined\n            logNewlyDiscoveredDeps()\n            if (warnAboutMissedDependencies) {\n              logDiscoveredDepsWhileScanning()\n              logger.info(\n                colors.magenta(\n                  `❗ add these dependencies to optimizeDeps.include to speed up cold start`,\n                ),\n                { timestamp: true },\n              )\n              warnAboutMissedDependencies = false\n            }\n          }, 2 * debounceMs)\n        } else {\n          debug(\n            colors.green(\n              `✨ ${\n                !isRerun\n                  ? `dependencies optimized`\n                  : `optimized dependencies unchanged`\n              }`,\n            ),\n          )\n        }\n      } else {\n        if (newDepsDiscovered) {\n          // There are newly discovered deps, and another rerun is about to be\n          // executed. Avoid the current full reload discarding this rerun result\n          // We don't resolve the processing promise, as they will be resolved\n          // once a rerun is committed\n          processingResult.cancel()\n\n          debug?.(\n            colors.green(\n              `✨ delaying reload as new dependencies have been found...`,\n            ),\n          )\n        } else {\n          await commitProcessing()\n\n          if (!debug) {\n            if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle)\n            newDepsToLogHandle = undefined\n            logNewlyDiscoveredDeps()\n            if (warnAboutMissedDependencies) {\n              logDiscoveredDepsWhileScanning()\n              logger.info(\n                colors.magenta(\n                  `❗ add these dependencies to optimizeDeps.include to avoid a full page reload during cold start`,\n                ),\n                { timestamp: true },\n              )\n              warnAboutMissedDependencies = false\n            }\n          }\n\n          logger.info(\n            colors.green(`✨ optimized dependencies changed. reloading`),\n            {\n              timestamp: true,\n            },\n          )\n          if (needsInteropMismatch.length > 0) {\n            logger.warn(\n              `Mixed ESM and CJS detected in ${colors.yellow(\n                needsInteropMismatch.join(', '),\n              )}, add ${\n                needsInteropMismatch.length === 1 ? 'it' : 'them'\n              } to optimizeDeps.needsInterop to speed up cold start`,\n              {\n                timestamp: true,\n              },\n            )\n          }\n\n          fullReload()\n        }\n      }\n    } catch (e) {\n      logger.error(\n        colors.red(`error while updating dependencies:\\n${e.stack}`),\n        { timestamp: true, error: e },\n      )\n      resolveEnqueuedProcessingPromises()\n\n      // Reset missing deps, let the server rediscover the dependencies\n      metadata.discovered = {}\n    }\n\n    currentlyProcessing = false\n    // @ts-expect-error `enqueuedRerun` could exist because `debouncedProcessing` may run while awaited\n    enqueuedRerun?.()\n  }\n\n  function fullReload() {\n    // Cached transform results have stale imports (resolved to\n    // old locations) so they need to be invalidated before the page is\n    // reloaded.\n    environment.moduleGraph.invalidateAll()\n\n    environment.hot.send({\n      type: 'full-reload',\n      path: '*',\n    })\n  }\n\n  async function rerun() {\n    // debounce time to wait for new missing deps finished, issue a new\n    // optimization of deps (both old and newly found) once the previous\n    // optimizeDeps processing is finished\n    const deps = Object.keys(metadata.discovered)\n    const depsString = depsLogString(deps)\n    debug?.(colors.green(`new dependencies found: ${depsString}`))\n    runOptimizer()\n  }\n\n  function getDiscoveredBrowserHash(\n    hash: string,\n    deps: Record<string, string>,\n    missing: Record<string, string>,\n  ) {\n    return getHash(\n      hash + JSON.stringify(deps) + JSON.stringify(missing) + sessionTimestamp,\n    )\n  }\n\n  function registerMissingImport(\n    id: string,\n    resolved: string,\n  ): OptimizedDepInfo {\n    const optimized = metadata.optimized[id]\n    if (optimized) {\n      return optimized\n    }\n    const chunk = metadata.chunks[id]\n    if (chunk) {\n      return chunk\n    }\n    let missing = metadata.discovered[id]\n    if (missing) {\n      // We are already discover this dependency\n      // It will be processed in the next rerun call\n      return missing\n    }\n\n    missing = addMissingDep(id, resolved)\n\n    // Until the first optimize run is called, avoid triggering processing\n    // We'll wait until the user codebase is eagerly processed by Vite so\n    // we can get a list of every missing dependency before giving to the\n    // browser a dependency that may be outdated, thus avoiding full page reloads\n\n    if (!waitingForCrawlEnd) {\n      // Debounced rerun, let other missing dependencies be discovered before\n      // the running next optimizeDeps\n      debouncedProcessing()\n    }\n\n    // Return the path for the optimized bundle, this path is known before\n    // esbuild is run to generate the pre-bundle\n    return missing\n  }\n\n  function addMissingDep(id: string, resolved: string) {\n    newDepsDiscovered = true\n\n    return addOptimizedDepInfo(metadata, 'discovered', {\n      id,\n      file: getOptimizedDepPath(environment, id),\n      src: resolved,\n      // Adding a browserHash to this missing dependency that is unique to\n      // the current state of known + missing deps. If its optimizeDeps run\n      // doesn't alter the bundled files of previous known dependencies,\n      // we don't need a full reload and this browserHash will be kept\n      browserHash: getDiscoveredBrowserHash(\n        metadata.hash,\n        depsFromOptimizedDepInfo(metadata.optimized),\n        depsFromOptimizedDepInfo(metadata.discovered),\n      ),\n      // loading of this pre-bundled dep needs to await for its processing\n      // promise to be resolved\n      processing: depOptimizationProcessing.promise,\n      exportsData: extractExportsData(environment, resolved),\n    })\n  }\n\n  function debouncedProcessing(timeout = debounceMs) {\n    // Debounced rerun, let other missing dependencies be discovered before\n    // the next optimizeDeps run\n    enqueuedRerun = undefined\n    if (debounceProcessingHandle) clearTimeout(debounceProcessingHandle)\n    if (newDepsToLogHandle) clearTimeout(newDepsToLogHandle)\n    newDepsToLogHandle = undefined\n    debounceProcessingHandle = setTimeout(() => {\n      debounceProcessingHandle = undefined\n      enqueuedRerun = rerun\n      if (!currentlyProcessing) {\n        enqueuedRerun()\n      }\n    }, timeout)\n  }\n\n  // onCrawlEnd is called once when the server starts and all static\n  // imports after the first request have been crawled (dynamic imports may also\n  // be crawled if the browser requests them right away).\n  async function onCrawlEnd() {\n    // switch after this point to a simple debounce strategy\n    waitingForCrawlEnd = false\n\n    debug?.(colors.green(`✨ static imports crawl ended`))\n    if (closed) {\n      return\n    }\n\n    // Await for the scan+optimize step running in the background\n    // It normally should be over by the time crawling of user code ended\n    await depsOptimizer.scanProcessing\n\n    if (optimizationResult && !options.noDiscovery) {\n      // In the holdUntilCrawlEnd strategy, we don't release the result of the\n      // post-scanner optimize step to the browser until we reach this point\n      // If there are new dependencies, we do another optimize run, if not, we\n      // use the post-scanner optimize result\n      // If holdUntilCrawlEnd is false and we reach here, it means that the\n      // scan+optimize step finished after crawl end. We follow the same\n      // process as in the holdUntilCrawlEnd in this case.\n      const afterScanResult = optimizationResult.result\n      optimizationResult = undefined // signal that we'll be using the result\n\n      const result = await afterScanResult\n      currentlyProcessing = false\n\n      const crawlDeps = Object.keys(metadata.discovered)\n      const scanDeps = Object.keys(result.metadata.optimized)\n\n      if (scanDeps.length === 0 && crawlDeps.length === 0) {\n        debug?.(\n          colors.green(\n            `✨ no dependencies found by the scanner or crawling static imports`,\n          ),\n        )\n        // We still commit the result so the scanner isn't run on the next cold start\n        // for projects without dependencies\n        startNextDiscoveredBatch()\n        runOptimizer(result)\n        return\n      }\n\n      const needsInteropMismatch = findInteropMismatches(\n        metadata.discovered,\n        result.metadata.optimized,\n      )\n      const scannerMissedDeps = crawlDeps.some((dep) => !scanDeps.includes(dep))\n      const outdatedResult =\n        needsInteropMismatch.length > 0 || scannerMissedDeps\n\n      if (outdatedResult) {\n        // Drop this scan result, and perform a new optimization to avoid a full reload\n        result.cancel()\n\n        // Add deps found by the scanner to the discovered deps while crawling\n        for (const dep of scanDeps) {\n          if (!crawlDeps.includes(dep)) {\n            addMissingDep(dep, result.metadata.optimized[dep].src!)\n          }\n        }\n        if (scannerMissedDeps) {\n          debug?.(\n            colors.yellow(\n              `✨ new dependencies were found while crawling that weren't detected by the scanner`,\n            ),\n          )\n        }\n        debug?.(colors.green(`✨ re-running optimizer`))\n        debouncedProcessing(0)\n      } else {\n        debug?.(\n          colors.green(\n            `✨ using post-scan optimizer result, the scanner found every used dependency`,\n          ),\n        )\n        startNextDiscoveredBatch()\n        runOptimizer(result)\n      }\n    } else if (!holdUntilCrawlEnd) {\n      // The post-scanner optimize result has been released to the browser\n      // If new deps have been discovered, issue a regular rerun of the\n      // optimizer. A full page reload may still be avoided if the new\n      // optimize result is compatible in this case\n      if (newDepsDiscovered) {\n        debug?.(\n          colors.green(\n            `✨ new dependencies were found while crawling static imports, re-running optimizer`,\n          ),\n        )\n        warnAboutMissedDependencies = true\n        debouncedProcessing(0)\n      }\n    } else {\n      const crawlDeps = Object.keys(metadata.discovered)\n      currentlyProcessing = false\n\n      if (crawlDeps.length === 0) {\n        debug?.(\n          colors.green(\n            `✨ no dependencies found while crawling the static imports`,\n          ),\n        )\n        firstRunCalled = true\n      }\n\n      // queue the first optimizer run, even without deps so the result is cached\n      debouncedProcessing(0)\n    }\n  }\n\n  return depsOptimizer\n}\n\nexport function createExplicitDepsOptimizer(\n  environment: DevEnvironment,\n): DepsOptimizer {\n  const depsOptimizer = {\n    metadata: initDepsOptimizerMetadata(environment),\n    isOptimizedDepFile: createIsOptimizedDepFile(environment),\n    isOptimizedDepUrl: createIsOptimizedDepUrl(environment),\n    getOptimizedDepId: (depInfo: OptimizedDepInfo) =>\n      `${depInfo.file}?v=${depInfo.browserHash}`,\n\n    registerMissingImport: () => {\n      throw new Error(\n        `Vite Internal Error: registerMissingImport is not supported in dev ${environment.name}`,\n      )\n    },\n    init,\n    // noop, there is no scanning during dev SSR\n    // the optimizer blocks the server start\n    run: () => {},\n\n    close: async () => {},\n    options: environment.config.optimizeDeps,\n  }\n\n  let inited = false\n  async function init() {\n    if (inited) return\n    inited = true\n\n    depsOptimizer.metadata = await optimizeExplicitEnvironmentDeps(environment)\n  }\n\n  return depsOptimizer\n}\n\nfunction findInteropMismatches(\n  discovered: Record<string, OptimizedDepInfo>,\n  optimized: Record<string, OptimizedDepInfo>,\n) {\n  const needsInteropMismatch = []\n  for (const dep in discovered) {\n    const discoveredDepInfo = discovered[dep]\n    if (discoveredDepInfo.needsInterop === undefined) continue\n\n    const depInfo = optimized[dep]\n    if (!depInfo) continue\n\n    if (depInfo.needsInterop !== discoveredDepInfo.needsInterop) {\n      // This only happens when a discovered dependency has mixed ESM and CJS syntax\n      // and it hasn't been manually added to optimizeDeps.needsInterop\n      needsInteropMismatch.push(dep)\n      debug?.(colors.cyan(`✨ needsInterop mismatch detected for ${dep}`))\n    }\n  }\n  return needsInteropMismatch\n}\n"
  },
  {
    "path": "packages/vite/src/node/optimizer/pluginConverter.ts",
    "content": "import { dirname } from 'node:path'\nimport type * as esbuild from 'esbuild'\nimport type {\n  ImportKind,\n  LoadResult,\n  PartialResolvedId,\n  PluginContext,\n  ResolveIdResult,\n  Plugin as RolldownPlugin,\n  RolldownPluginOption,\n} from 'rolldown'\n\ntype MaybePromise<T> = T | Promise<T>\ntype EsbuildOnResolveCallback = (\n  args: esbuild.OnResolveArgs,\n) => MaybePromise<esbuild.OnResolveResult | null | undefined>\ntype EsbuildOnLoadCallback = (\n  args: esbuild.OnLoadArgs,\n) => MaybePromise<esbuild.OnLoadResult | null | undefined>\ntype ResolveIdHandler = (\n  this: PluginContext,\n  id: string,\n  importer: string | undefined,\n  opts: { kind: ImportKind },\n) => MaybePromise<\n  | (PartialResolvedId & { namespace?: string })\n  | Exclude<ResolveIdResult, PartialResolvedId>\n>\ntype LoadHandler = (this: PluginContext, id: string) => MaybePromise<LoadResult>\n\nexport function convertEsbuildPluginToRolldownPlugin(\n  esbuildPlugin: esbuild.Plugin,\n): RolldownPlugin {\n  const onStartCallbacks: Array<() => void> = []\n  const onEndCallbacks: Array<(buildResult: esbuild.BuildResult) => void> = []\n  const onDisposeCallbacks: Array<() => void> = []\n  let resolveIdHandlers: ResolveIdHandler[]\n  let loadHandlers: LoadHandler[]\n\n  let isSetupDone = false\n  const setup = async (\n    plugins: RolldownPluginOption[],\n    platform: 'browser' | 'node' | 'neutral',\n  ) => {\n    const onResolveCallbacks: Array<\n      [options: esbuild.OnResolveOptions, callback: EsbuildOnResolveCallback]\n    > = []\n    const onLoadCallbacks: Array<\n      [options: esbuild.OnLoadOptions, callback: EsbuildOnLoadCallback]\n    > = []\n\n    const pluginBuild: esbuild.PluginBuild = {\n      initialOptions: new Proxy(\n        {\n          platform,\n          plugins:\n            plugins?.flatMap((p) =>\n              p && 'name' in p\n                ? [\n                    {\n                      name: p.name,\n                      // eslint-disable-next-line @typescript-eslint/no-empty-function\n                      setup() {},\n                    },\n                  ]\n                : [],\n            ) ?? [],\n        },\n        {\n          get(target, p, _receiver) {\n            if (p in target) return (target as any)[p]\n            throw new Error('Not implemented')\n          },\n        },\n      ) as esbuild.BuildOptions,\n      resolve() {\n        throw new Error('Not implemented')\n      },\n      onStart(callback) {\n        onStartCallbacks.push(callback)\n      },\n      onEnd(callback) {\n        onEndCallbacks.push(callback)\n      },\n      onResolve(options, callback) {\n        onResolveCallbacks.push([options, callback])\n      },\n      onLoad(options, callback) {\n        onLoadCallbacks.push([options, callback])\n      },\n      onDispose(callback) {\n        onDisposeCallbacks.push(callback)\n      },\n      get esbuild(): esbuild.PluginBuild['esbuild'] {\n        throw new Error('Not implemented')\n      },\n      set esbuild(_: unknown) {\n        throw new Error('Not implemented')\n      },\n    }\n\n    await esbuildPlugin.setup(pluginBuild)\n\n    resolveIdHandlers = onResolveCallbacks.map(([options, callback]) =>\n      createResolveIdHandler(options, callback),\n    )\n    loadHandlers = onLoadCallbacks.map(([options, callback]) =>\n      createLoadHandler(options, callback),\n    )\n    isSetupDone = true\n  }\n\n  const usedNamespaces = new Set<string>()\n  return {\n    name: esbuildPlugin.name,\n    async options(inputOptions) {\n      await setup(\n        inputOptions.plugins as RolldownPluginOption[],\n        inputOptions.platform ?? 'node',\n      )\n    },\n    async buildStart(inputOptions) {\n      // options hook is not called for scanner\n      if (!isSetupDone) {\n        // inputOptions.plugins is not available for buildStart hook\n        // put a dummy plugin to tell that this is a scan\n        await setup(\n          [{ name: 'vite:dep-scan' }],\n          inputOptions.platform ?? 'node',\n        )\n      }\n\n      for (const cb of onStartCallbacks) {\n        cb()\n      }\n    },\n    generateBundle() {\n      const buildResult = new Proxy(\n        {},\n        {\n          get(_target, _prop) {\n            throw new Error('Not implemented')\n          },\n        },\n      ) as esbuild.BuildResult\n      for (const cb of onEndCallbacks) {\n        cb(buildResult)\n      }\n    },\n    async resolveId(id, importer, opts) {\n      for (const handler of resolveIdHandlers) {\n        const result = await handler.call(this, id, importer, opts)\n        if (result) {\n          if (typeof result === 'object' && result.namespace) {\n            usedNamespaces.add(result.namespace)\n          }\n          return result\n        }\n      }\n      if (usedNamespaces.size) {\n        const [importerWithoutNamespace, namespaceFromImporter] =\n          idToPathAndNamespace(importer)\n        if (usedNamespaces.has(namespaceFromImporter)) {\n          return await this.resolve(id, importerWithoutNamespace, opts)\n        }\n      }\n    },\n    async load(id) {\n      for (const handler of loadHandlers) {\n        const result = await handler.call(this, id)\n        if (result) {\n          return result\n        }\n      }\n    },\n    closeBundle() {\n      if (!this.meta.watchMode) {\n        for (const cb of onDisposeCallbacks) {\n          cb()\n        }\n      }\n    },\n    closeWatcher() {\n      for (const cb of onDisposeCallbacks) {\n        cb()\n      }\n    },\n  }\n}\n\nfunction createResolveIdHandler(\n  options: esbuild.OnResolveOptions,\n  callback: EsbuildOnResolveCallback,\n): ResolveIdHandler {\n  return async function (id, importer, opts) {\n    const [importerWithoutNamespace, importerNamespace] =\n      idToPathAndNamespace(importer)\n    if (\n      options.namespace !== undefined &&\n      options.namespace !== importerNamespace\n    ) {\n      return\n    }\n    if (options.filter !== undefined && !options.filter.test(id)) {\n      return\n    }\n\n    const result = await callback({\n      path: id,\n      importer: importerWithoutNamespace ?? '',\n      namespace: importerNamespace,\n      resolveDir: dirname(importerWithoutNamespace ?? ''),\n      kind:\n        importerWithoutNamespace === undefined\n          ? 'entry-point'\n          : opts.kind === 'new-url' || opts.kind === 'hot-accept'\n            ? 'dynamic-import'\n            : opts.kind,\n      pluginData: {},\n      with: {},\n    })\n    if (!result) return\n    if (result.errors && result.errors.length > 0) {\n      throw new AggregateError(result.errors)\n    }\n    if (\n      (result.warnings && result.warnings.length > 0) ||\n      (result.watchDirs && result.watchDirs.length > 0) ||\n      !result.path\n    ) {\n      throw new Error('not implemented')\n    }\n    for (const file of result.watchFiles ?? []) {\n      this.addWatchFile(file)\n    }\n\n    return {\n      id: result.namespace ? `${result.namespace}:${result.path}` : result.path,\n      external: result.external,\n      moduleSideEffects: result.sideEffects,\n      namespace: result.namespace,\n    }\n  }\n}\n\nfunction createLoadHandler(\n  options: esbuild.OnLoadOptions,\n  callback: EsbuildOnLoadCallback,\n): LoadHandler {\n  const textDecoder = new TextDecoder()\n  return async function (id) {\n    const [idWithoutNamespace, idNamespace] = idToPathAndNamespace(id)\n    if (\n      options.namespace !== undefined &&\n      options.namespace !== 'file' &&\n      options.namespace !== idNamespace\n    ) {\n      return\n    }\n    if (options.filter !== undefined && !options.filter.test(id)) {\n      return\n    }\n\n    const result = await callback.call(this, {\n      path: idWithoutNamespace,\n      namespace: idNamespace,\n      suffix: '',\n      pluginData: {},\n      with: {},\n    })\n    if (!result) return\n    if (result.errors && result.errors.length > 0) {\n      throw new AggregateError(result.errors)\n    }\n    if (\n      (result.warnings && result.warnings.length > 0) ||\n      (result.watchDirs && result.watchDirs.length > 0) ||\n      result.contents == null\n    ) {\n      throw new Error('not implemented')\n    }\n    for (const file of result.watchFiles ?? []) {\n      this.addWatchFile(file)\n    }\n\n    return {\n      code:\n        typeof result.contents === 'string'\n          ? result.contents\n          : textDecoder.decode(result.contents),\n      moduleType: result.loader,\n    }\n  }\n}\n\nfunction idToPathAndNamespace(id: string): [path: string, namespace: string]\nfunction idToPathAndNamespace(\n  id: string | undefined,\n): [path: string | undefined, namespace: string]\nfunction idToPathAndNamespace(\n  id: string | undefined,\n): [path: string | undefined, namespace: string] {\n  if (id === undefined) return [undefined, 'file']\n\n  const namespaceIndex = id.indexOf(':')\n  if (namespaceIndex >= 0) {\n    return [id.slice(namespaceIndex + 1), id.slice(0, namespaceIndex)]\n  } else {\n    return [id, 'file']\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/optimizer/resolve.ts",
    "content": "import path from 'node:path'\nimport picomatch from 'picomatch'\nimport { globSync } from 'tinyglobby'\nimport type { ResolvedConfig } from '../config'\nimport { escapeRegex, getNpmPackageName } from '../utils'\nimport { resolvePackageData } from '../packages'\nimport { slash } from '../../shared/utils'\nimport type { Environment } from '../environment'\nimport { createBackCompatIdResolver } from '../idResolver'\n\nexport function createOptimizeDepsIncludeResolver(\n  environment: Environment,\n): (id: string) => Promise<string | undefined> {\n  const topLevelConfig = environment.getTopLevelConfig()\n  const resolve = createBackCompatIdResolver(topLevelConfig, {\n    asSrc: false,\n    scan: true,\n    packageCache: new Map(),\n  })\n\n  return async (id: string) => {\n    const lastArrowIndex = id.lastIndexOf('>')\n    if (lastArrowIndex === -1) {\n      return await resolve(environment, id, undefined)\n    }\n    // split nested selected id by last '>', for example:\n    // 'foo > bar > baz' => 'foo > bar' & 'baz'\n    const nestedRoot = id.substring(0, lastArrowIndex).trim()\n    const nestedPath = id.substring(lastArrowIndex + 1).trim()\n    const basedir = nestedResolveBasedir(\n      nestedRoot,\n      topLevelConfig.root,\n      topLevelConfig.resolve.preserveSymlinks,\n    )\n    return await resolve(\n      environment,\n      nestedPath,\n      path.resolve(basedir, 'package.json'),\n    )\n  }\n}\n\n/**\n * Expand the glob syntax in `optimizeDeps.include` to proper import paths\n */\nexport function expandGlobIds(id: string, config: ResolvedConfig): string[] {\n  const pkgName = getNpmPackageName(id)\n  if (!pkgName) return []\n\n  const pkgData = resolvePackageData(\n    pkgName,\n    config.root,\n    config.resolve.preserveSymlinks,\n    config.packageCache,\n  )\n  if (!pkgData) return []\n\n  const pattern = '.' + id.slice(pkgName.length)\n  const exports = pkgData.data.exports\n\n  // if package has exports field, get all possible export paths and apply\n  // glob on them with picomatch\n  if (exports) {\n    if (typeof exports === 'string' || Array.isArray(exports)) {\n      return [pkgName]\n    }\n\n    const possibleExportPaths: string[] = []\n    for (const key in exports) {\n      if (key[0] === '.') {\n        if (key.includes('*')) {\n          // \"./glob/*\": {\n          //   \"browser\": \"./dist/glob/*-browser/*.js\", <-- get this one\n          //   \"default\": \"./dist/glob/*/*.js\"\n          // }\n          // NOTE: theoretically the \"default\" condition could map to a different\n          // set of files, but that complicates the resolve logic, so we assume\n          // all conditions map to the same set of files, and get the first one.\n          const exportsValue = getFirstExportStringValue(exports[key])\n          if (!exportsValue) continue\n\n          // \"./dist/glob/*-browser/*.js\" => \"./dist/glob/**/*-browser/**/*.js\"\n          // NOTE: in some cases, this could expand to consecutive /**/*/**/* etc\n          // but it's fine since `tinyglobby` handles it the same.\n          const exportValuePattern = exportsValue.replace(/\\*/g, '**/*')\n          // \"./dist/glob/*-browser/*.js\" => /dist\\/glob\\/(.*)-browser\\/(.*)\\.js/\n          const exportsValueGlobRe = new RegExp(\n            exportsValue.split('*').map(escapeRegex).join('(.*)'),\n          )\n\n          possibleExportPaths.push(\n            ...globSync(exportValuePattern, {\n              cwd: pkgData.dir,\n              expandDirectories: false,\n              ignore: ['node_modules'],\n            })\n              .map((filePath) => {\n                // `tinyglobby` returns paths as they are formatted by the underlying `fdir`.\n                // Both `globSync(\"./some-dir/**/*\")` and `globSync(\"./**/*\")` result in\n                // `\"some-dir/somefile\"` being returned, so we ensure the correct prefix manually.\n                if (exportsValue.startsWith('./')) {\n                  filePath = './' + filePath\n                }\n\n                // \"./glob/*\": \"./dist/glob/*-browser/*.js\"\n                // `filePath`: \"./dist/glob/foo-browser/foo.js\"\n                // we need to revert the file path back to the export key by\n                // matching value regex and replacing the capture groups to the key\n                const matched = exportsValueGlobRe.exec(slash(filePath))\n                // `matched`: [..., 'foo', 'foo']\n                if (matched) {\n                  let allGlobSame = matched.length === 2\n                  // exports key can only have one *, so for >=2 matched groups,\n                  // make sure they have the same value\n                  if (!allGlobSame) {\n                    // assume true, if one group is different, set false and break\n                    allGlobSame = true\n                    for (let i = 2; i < matched.length; i++) {\n                      if (matched[i] !== matched[i - 1]) {\n                        allGlobSame = false\n                        break\n                      }\n                    }\n                  }\n                  if (allGlobSame) {\n                    return key.replace('*', matched[1]).slice(2)\n                  }\n                }\n                return ''\n              })\n              .filter(Boolean),\n          )\n        } else {\n          possibleExportPaths.push(key.slice(2))\n        }\n      }\n    }\n\n    const isMatch = picomatch(pattern)\n    const matched = possibleExportPaths\n      .filter((p) => isMatch(p))\n      .map((match) => path.posix.join(pkgName, match))\n    matched.unshift(pkgName)\n    return matched\n  } else {\n    // for packages without exports, we can do a simple glob\n    const matched = globSync(pattern, {\n      cwd: pkgData.dir,\n      expandDirectories: false,\n      ignore: ['node_modules'],\n    }).map((match) => path.posix.join(pkgName, slash(match)))\n    matched.unshift(pkgName)\n    return matched\n  }\n}\n\nfunction getFirstExportStringValue(\n  obj: string | string[] | Record<string, any>,\n): string | undefined {\n  if (typeof obj === 'string') {\n    return obj\n  } else if (Array.isArray(obj)) {\n    return obj[0]\n  } else {\n    for (const key in obj) {\n      return getFirstExportStringValue(obj[key])\n    }\n  }\n}\n\n/**\n * Continuously resolve the basedir of packages separated by '>'\n */\nfunction nestedResolveBasedir(\n  id: string,\n  basedir: string,\n  preserveSymlinks = false,\n) {\n  const pkgs = id.split('>').map((pkg) => pkg.trim())\n  for (const pkg of pkgs) {\n    basedir = resolvePackageData(pkg, basedir, preserveSymlinks)?.dir || basedir\n  }\n  return basedir\n}\n"
  },
  {
    "path": "packages/vite/src/node/optimizer/rolldownDepPlugin.ts",
    "content": "import path from 'node:path'\nimport type { ImportKind, Plugin, RolldownPlugin } from 'rolldown'\nimport { prefixRegex } from 'rolldown/filter'\nimport MagicString from 'magic-string'\nimport { stripLiteral } from 'strip-literal'\nimport { JS_TYPES_RE, KNOWN_ASSET_TYPES } from '../constants'\nimport type { PackageCache } from '../packages'\nimport {\n  escapeRegex,\n  flattenId,\n  isBuiltin,\n  isCSSRequest,\n  isDataUrl,\n  isExternalUrl,\n  isNodeBuiltin,\n  moduleListContains,\n  normalizePath,\n} from '../utils'\nimport { browserExternalId, optionalPeerDepId } from '../plugins/resolve'\nimport { isModuleCSSRequest } from '../plugins/css'\nimport type { Environment } from '../environment'\nimport { createBackCompatIdResolver } from '../idResolver'\nimport { isWindows } from '../../shared/utils'\nimport { hasViteIgnoreRE } from '../plugins/importAnalysis'\nimport { assetImportMetaUrlRE } from '../plugins/assetImportMetaUrl'\n\nconst externalWithConversionNamespace =\n  'vite:dep-pre-bundle:external-conversion'\nconst convertedExternalPrefix = 'vite-dep-pre-bundle-external:'\n\nconst cjsExternalFacadeNamespace = 'vite:cjs-external-facade'\nconst nonFacadePrefix = 'vite-cjs-external-facade:'\n\nconst externalTypes = [\n  'css',\n  // supported pre-processor types\n  'less',\n  'sass',\n  'scss',\n  'styl',\n  'stylus',\n  'pcss',\n  'postcss',\n  // wasm\n  'wasm',\n  // known SFC types\n  'vue',\n  'svelte',\n  'marko',\n  'astro',\n  'imba',\n  // JSX/TSX may be configured to be compiled differently from how esbuild\n  // handles it by default, so exclude them as well\n  'jsx',\n  'tsx',\n  ...KNOWN_ASSET_TYPES,\n]\n\nconst optionalPeerDepNamespace = 'optional-peer-dep:'\nconst browserExternalNamespace = 'browser-external:'\n\nexport function rolldownDepPlugin(\n  environment: Environment,\n  qualified: Record<string, string>,\n  external: string[],\n): RolldownPlugin[] {\n  const { isProduction } = environment.config\n  const { extensions } = environment.config.optimizeDeps\n\n  // remove optimizable extensions from `externalTypes` list\n  const allExternalTypes = extensions\n    ? externalTypes.filter((type) => !extensions.includes('.' + type))\n    : externalTypes\n\n  // use separate package cache for optimizer as it caches paths around node_modules\n  // and it's unlikely for the core Vite process to traverse into node_modules again\n  const esmPackageCache: PackageCache = new Map()\n  const cjsPackageCache: PackageCache = new Map()\n\n  const resolveAssets = (resolved: string, kind: ImportKind) => {\n    if (kind === 'require-call') {\n      // here it is not set to `external: true` to convert `require` to `import`\n      return {\n        id: externalWithConversionNamespace + resolved,\n      }\n    }\n    return {\n      id: resolved,\n      external: 'absolute' as const,\n    }\n  }\n\n  // default resolver which prefers ESM\n  const _resolve = createBackCompatIdResolver(environment.getTopLevelConfig(), {\n    asSrc: false,\n    scan: true,\n    packageCache: esmPackageCache,\n  })\n\n  // cjs resolver that prefers Node\n  const _resolveRequire = createBackCompatIdResolver(\n    environment.getTopLevelConfig(),\n    {\n      asSrc: false,\n      isRequire: true,\n      scan: true,\n      packageCache: cjsPackageCache,\n    },\n  )\n\n  const resolve = (\n    id: string,\n    importer: string | undefined,\n    kind: ImportKind,\n  ): Promise<string | undefined> => {\n    // map importer ids to file paths for correct resolution\n    const _importer =\n      importer && importer in qualified ? qualified[importer] : importer\n    const resolver = kind.startsWith('require') ? _resolveRequire : _resolve\n    return resolver(environment, id, _importer)\n  }\n\n  const resolveResult = (id: string, resolved: string, kind: ImportKind) => {\n    if (resolved.startsWith(browserExternalId)) {\n      return {\n        id: browserExternalNamespace + id,\n      }\n    }\n    if (resolved.startsWith(optionalPeerDepId)) {\n      return {\n        id: optionalPeerDepNamespace + resolved,\n      }\n    }\n    if (allExternalTypesReg.test(resolved)) {\n      return resolveAssets(resolved, kind)\n    }\n    if (isBuiltin(environment.config.resolve.builtins, resolved)) {\n      return\n    }\n    if (isExternalUrl(resolved)) {\n      return {\n        id: resolved,\n        external: 'absolute',\n      }\n    }\n    return {\n      id: path.resolve(resolved),\n    }\n  }\n\n  const allExternalTypesReg = new RegExp(\n    `\\\\.(` + allExternalTypes.join('|') + `)(\\\\?.*)?$`,\n  )\n\n  function resolveEntry(id: string) {\n    const flatId = flattenId(id)\n    if (flatId in qualified) {\n      return {\n        id: qualified[flatId],\n      }\n    }\n  }\n\n  const bundleOutputDir = path.join(environment.config.cacheDir, 'deps')\n\n  return [\n    {\n      name: 'vite:dep-pre-bundle-assets',\n      // externalize assets and commonly known non-js file types\n      // See #8459 for more details about this require-import conversion\n      resolveId: {\n        filter: { id: allExternalTypesReg },\n        async handler(id, importer, options) {\n          const kind = options.kind\n          // if the prefix exist, it is already converted to `import`, so set `external: true`\n          if (id.startsWith(convertedExternalPrefix)) {\n            return {\n              id: id.slice(convertedExternalPrefix.length),\n              external: 'absolute',\n            }\n          }\n\n          const resolved = await resolve(id, importer, kind)\n          if (resolved) {\n            // `resolved` can be javascript even when `id` matches `allExternalTypes`\n            // due to cjs resolution (e.g. require(\"./test.pdf\") for \"./test.pdf.js\")\n            // or package name (e.g. import \"some-package.pdf\")\n            if (JS_TYPES_RE.test(resolved)) {\n              return {\n                // normalize to \\\\ on windows for esbuild/rolldown behavior difference: https://github.com/sapphi-red-repros/rolldown-esbuild-path-normalization\n                id: isWindows ? resolved.replaceAll('/', '\\\\') : resolved,\n                external: false,\n              }\n            }\n            return resolveAssets(resolved, kind)\n          }\n        },\n      },\n      load: {\n        filter: {\n          id: prefixRegex(externalWithConversionNamespace),\n        },\n        handler(id) {\n          const path = id.slice(externalWithConversionNamespace.length)\n          // import itself with prefix (this is the actual part of require-import conversion)\n          const modulePath = `\"${convertedExternalPrefix}${path}\"`\n          return {\n            code:\n              isCSSRequest(path) && !isModuleCSSRequest(path)\n                ? `import ${modulePath};`\n                : `export { default } from ${modulePath};` +\n                  `export * from ${modulePath};`,\n          }\n        },\n      },\n    },\n    {\n      name: 'vite:dep-pre-bundle',\n      // clear package cache when build is finished\n      buildEnd() {\n        esmPackageCache.clear()\n        cjsPackageCache.clear()\n      },\n      resolveId: {\n        filter: { id: /^[\\w@][^:]/ },\n        async handler(id, importer, options) {\n          const kind = options.kind\n\n          if (moduleListContains(external, id)) {\n            return {\n              id: id,\n              external: 'absolute',\n            }\n          }\n\n          // ensure rolldown uses our resolved entries\n          let entry: { id: string } | undefined\n          // if this is an entry, return entry namespace resolve result\n          if (!importer) {\n            if ((entry = resolveEntry(id))) return entry\n            // check if this is aliased to an entry - also return entry namespace\n            const aliased = await _resolve(environment, id, undefined, true)\n            if (aliased && (entry = resolveEntry(aliased))) {\n              return entry\n            }\n          }\n\n          // use vite's own resolver\n          const resolved = await resolve(id, importer, kind)\n          if (resolved) {\n            return resolveResult(id, resolved, kind)\n          }\n        },\n      },\n      load: {\n        filter: {\n          id: [\n            prefixRegex(browserExternalNamespace),\n            prefixRegex(optionalPeerDepNamespace),\n          ],\n        },\n        handler(id) {\n          if (id.startsWith(browserExternalNamespace)) {\n            const path = id.slice(browserExternalNamespace.length)\n            if (isProduction) {\n              return {\n                code: 'module.exports = {}',\n              }\n            } else {\n              return {\n                // Return in CJS to intercept named imports. Use `Object.create` to\n                // create the Proxy in the prototype to workaround esbuild issue. Why?\n                //\n                // In short, esbuild cjs->esm flow:\n                // 1. Create empty object using `Object.create(Object.getPrototypeOf(module.exports))`.\n                // 2. Assign props of `module.exports` to the object.\n                // 3. Return object for ESM use.\n                //\n                // If we do `module.exports = new Proxy({}, {})`, step 1 returns empty object,\n                // step 2 does nothing as there's no props for `module.exports`. The final object\n                // is just an empty object.\n                //\n                // Creating the Proxy in the prototype satisfies step 1 immediately, which means\n                // the returned object is a Proxy that we can intercept.\n                //\n                // Note: Skip keys that are accessed by esbuild and browser devtools.\n                code: `\\\n    module.exports = Object.create(new Proxy({}, {\n        get(_, key) {\n        if (\n            key !== '__esModule' &&\n            key !== '__proto__' &&\n            key !== 'constructor' &&\n            key !== 'splice'\n        ) {\n            console.warn(\\`Module \"${path}\" has been externalized for browser compatibility. Cannot access \"${path}.\\${key}\" in client code. See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.\\`)\n        }\n        }\n    }))`,\n              }\n            }\n          }\n\n          if (id.startsWith(optionalPeerDepNamespace)) {\n            const path = id.slice(optionalPeerDepNamespace.length)\n            const [, peerDep, parentDep] = path.split(':')\n            return {\n              code:\n                'module.exports = {};' +\n                `throw new Error(\\`Could not resolve \"${peerDep}\" imported by \"${parentDep}\". Is it installed?\\`)`,\n            }\n          }\n        },\n      },\n      transform: {\n        filter: {\n          code: assetImportMetaUrlRE,\n        },\n        async handler(code, id) {\n          let s: MagicString | undefined\n          const re = new RegExp(assetImportMetaUrlRE)\n          const cleanString = stripLiteral(code)\n\n          let match: RegExpExecArray | null\n          while ((match = re.exec(cleanString))) {\n            const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!\n            if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue\n\n            const rawUrl = code.slice(urlStart, urlEnd)\n\n            if (rawUrl[0] === '`' && rawUrl.includes('${')) {\n              // We skip dynamic template strings in the optimizer for now as they\n              // require complex glob transformation that is handled by the main asset plugin.\n              continue\n            }\n\n            const url = rawUrl.slice(1, -1)\n            if (isDataUrl(url) || isExternalUrl(url) || url.startsWith('/')) {\n              continue\n            }\n\n            if (!s) s = new MagicString(code)\n\n            // we resolve the relative path from the original library file (id) and\n            // then rewrite it relative to the bundle (deps) directory.\n            const absolutePath = path.resolve(path.dirname(id), url)\n            const relativePath = path.relative(bundleOutputDir, absolutePath)\n            const normalizedRelativePath = normalizePath(relativePath)\n            s.update(\n              startIndex,\n              endIndex,\n              // NOTE: add `'' +` to opt-out rolldown's transform: https://github.com/rolldown/rolldown/issues/2745\n              `new URL('' + ${JSON.stringify(\n                normalizedRelativePath,\n              )}, import.meta.url)`,\n            )\n          }\n\n          if (s) {\n            return {\n              code: s.toString(),\n              map: s.generateMap({ hires: 'boundary' }),\n            }\n          }\n        },\n      },\n    },\n  ]\n}\n\nconst matchesEntireLine = (text: string) => `^${escapeRegex(text)}$`\n\n// rolldown (and esbuild) doesn't transpile `require('foo')` into `import` statements if 'foo' is externalized\n// https://rolldown.rs/in-depth/bundling-cjs#require-external-modules\nexport function rolldownCjsExternalPlugin(\n  externals: string[],\n  platform: 'node' | 'browser' | 'neutral',\n): Plugin | undefined {\n  // Skip this plugin for `platform: 'node'` as `require` is available in Node\n  // and that is more accurate than converting to `import`\n  if (platform === 'node') {\n    return undefined\n  }\n  // Skip this plugin for `platform: 'neutral'` as we are not sure whether `require` is available\n  if (platform === 'neutral') {\n    return undefined\n  }\n\n  // Apply this plugin for `platform: 'browser'` as `require` is not available in browser and\n  // converting to `import` would be necessary to make the code work\n  platform satisfies 'browser'\n\n  const filter = new RegExp(externals.map(matchesEntireLine).join('|'))\n\n  return {\n    name: 'cjs-external',\n    resolveId: {\n      filter: { id: [prefixRegex(nonFacadePrefix), filter] },\n      handler(id, _importer, options) {\n        if (id.startsWith(nonFacadePrefix)) {\n          return {\n            id: id.slice(nonFacadePrefix.length),\n            external: 'absolute',\n          }\n        }\n        if (options.kind === 'require-call') {\n          return {\n            id: cjsExternalFacadeNamespace + id,\n          }\n        }\n        return {\n          id,\n          external: 'absolute',\n        }\n      },\n    },\n    load: {\n      filter: { id: prefixRegex(cjsExternalFacadeNamespace) },\n      handler(id) {\n        const idWithoutNamespace = id.slice(cjsExternalFacadeNamespace.length)\n        return {\n          code: `\\\nimport * as m from ${JSON.stringify(nonFacadePrefix + idWithoutNamespace)};\nmodule.exports = ${isNodeBuiltin(idWithoutNamespace) ? 'm.default' : '{ ...m }'};\n`,\n        }\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/optimizer/scan.ts",
    "content": "import fs from 'node:fs'\nimport fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport { scan } from 'rolldown/experimental'\nimport { transformSync } from 'rolldown/utils'\nimport type { PartialResolvedId, Plugin } from 'rolldown'\nimport colors from 'picocolors'\nimport { glob } from 'tinyglobby'\nimport {\n  CSS_LANGS_RE,\n  JS_TYPES_RE,\n  KNOWN_ASSET_TYPES,\n  SPECIAL_QUERY_RE,\n} from '../constants'\nimport {\n  arraify,\n  asyncFlatten,\n  createDebugger,\n  dataUrlRE,\n  deepClone,\n  externalRE,\n  isInNodeModules,\n  isObject,\n  isOptimizable,\n  moduleListContains,\n  multilineCommentsRE,\n  normalizePath,\n  singlelineCommentsRE,\n  virtualModulePrefix,\n  virtualModuleRE,\n} from '../utils'\nimport type { EnvironmentPluginContainer } from '../server/pluginContainer'\nimport { createEnvironmentPluginContainer } from '../server/pluginContainer'\nimport { BaseEnvironment } from '../baseEnvironment'\nimport type { DevEnvironment } from '../server/environment'\nimport { transformGlobImport } from '../plugins/importMetaGlob'\nimport { cleanUrl } from '../../shared/utils'\nimport { getRollupJsxPresets } from '../plugins/oxc'\n\nexport class ScanEnvironment extends BaseEnvironment {\n  mode = 'scan' as const\n\n  get pluginContainer(): EnvironmentPluginContainer {\n    if (!this._pluginContainer)\n      throw new Error(\n        `${this.name} environment.pluginContainer called before initialized`,\n      )\n    return this._pluginContainer\n  }\n  /**\n   * @internal\n   */\n  _pluginContainer: EnvironmentPluginContainer | undefined\n\n  async init(): Promise<void> {\n    if (this._initiated) {\n      return\n    }\n    this._initiated = true\n    this._pluginContainer = await createEnvironmentPluginContainer(\n      this,\n      this.plugins,\n      undefined,\n      false,\n    )\n  }\n}\n\n// Restrict access to the module graph and the server while scanning\nexport function devToScanEnvironment(\n  environment: DevEnvironment,\n): ScanEnvironment {\n  return {\n    mode: 'scan',\n    get name() {\n      return environment.name\n    },\n    getTopLevelConfig() {\n      return environment.getTopLevelConfig()\n    },\n    get config() {\n      return environment.config\n    },\n    get logger() {\n      return environment.logger\n    },\n    get pluginContainer() {\n      return environment.pluginContainer\n    },\n    get plugins() {\n      return environment.plugins\n    },\n  } as unknown as ScanEnvironment\n}\n\nconst debug = createDebugger('vite:deps')\n\nconst htmlTypesRE = /\\.(?:html|vue|svelte|astro|imba)$/\n\n// A simple regex to detect import sources. This is only used on\n// <script lang=\"ts\"> blocks in vue (setup only) or svelte files, since\n// seemingly unused imports are dropped by esbuild when transpiling TS which\n// prevents it from crawling further.\n// We can't use es-module-lexer because it can't handle TS, and don't want to\n// use Acorn because it's slow. Luckily this doesn't have to be bullet proof\n// since even missed imports can be caught at runtime, and false positives will\n// simply be ignored.\nexport const importsRE: RegExp =\n  /(?<!\\/\\/.*)(?<=^|;|\\*\\/)\\s*import(?!\\s+type)(?:[\\w*{}\\n\\r\\t, ]+from)?\\s*(\"[^\"]+\"|'[^']+')\\s*(?=$|;|\\/\\/|\\/\\*)/gm\n\nexport function scanImports(environment: ScanEnvironment): {\n  cancel: () => Promise<void>\n  result: Promise<{\n    deps: Record<string, string>\n    missing: Record<string, string>\n  }>\n} {\n  const start = performance.now()\n  const { config } = environment\n\n  const scanContext = { cancelled: false }\n  async function cancel() {\n    scanContext.cancelled = true\n  }\n\n  async function scan() {\n    const entries = await computeEntries(environment)\n    if (!entries.length) {\n      if (!config.optimizeDeps.entries && !config.optimizeDeps.include) {\n        environment.logger.warn(\n          colors.yellow(\n            '(!) Could not auto-determine entry point from rollupOptions or html files ' +\n              'and there are no explicit optimizeDeps.include patterns. ' +\n              'Skipping dependency pre-bundling.',\n          ),\n        )\n      }\n      return\n    }\n    if (scanContext.cancelled) return\n\n    debug?.(\n      `Crawling dependencies using entries: ${entries\n        .map((entry) => `\\n  ${colors.dim(entry)}`)\n        .join('')}`,\n    )\n    const deps: Record<string, string> = {}\n    const missing: Record<string, string> = {}\n\n    const context = await prepareRolldownScanner(\n      environment,\n      entries,\n      deps,\n      missing,\n    )\n    if (scanContext.cancelled) return\n\n    try {\n      await context.build()\n      return {\n        // Ensure a fixed order so hashes are stable and improve logs\n        deps: orderedDependencies(deps),\n        missing,\n      }\n    } catch (e) {\n      const prependMessage = colors.red(`\\\n  Failed to scan for dependencies from entries:\n  ${entries.join('\\n')}\n\n  `)\n      e.message = prependMessage + e.message\n      throw e\n    } finally {\n      if (debug) {\n        const duration = (performance.now() - start).toFixed(2)\n        const depsStr =\n          Object.keys(orderedDependencies(deps))\n            .sort()\n            .map((id) => `\\n  ${colors.cyan(id)} -> ${colors.dim(deps[id])}`)\n            .join('') || colors.dim('no dependencies found')\n        debug(`Scan completed in ${duration}ms: ${depsStr}`)\n      }\n    }\n  }\n  const result = scan()\n\n  return {\n    cancel,\n    result: result.then((res) => res ?? { deps: {}, missing: {} }),\n  }\n}\n\nasync function computeEntries(environment: ScanEnvironment) {\n  let entries: string[] = []\n\n  const explicitEntryPatterns = environment.config.optimizeDeps.entries\n  const buildInput = environment.config.build.rollupOptions.input\n\n  if (explicitEntryPatterns) {\n    entries = await globEntries(explicitEntryPatterns, environment)\n  } else if (buildInput) {\n    const resolvePath = async (p: string) => {\n      // rollup resolves the input from process.cwd()\n      const id = (\n        await environment.pluginContainer.resolveId(\n          p,\n          path.join(process.cwd(), '*'),\n          {\n            isEntry: true,\n            scan: true,\n          },\n        )\n      )?.id\n      if (id === undefined) {\n        throw new Error(\n          `failed to resolve rollupOptions.input value: ${JSON.stringify(p)}.`,\n        )\n      }\n      return id\n    }\n    if (typeof buildInput === 'string') {\n      entries = [await resolvePath(buildInput)]\n    } else if (Array.isArray(buildInput)) {\n      entries = await Promise.all(buildInput.map(resolvePath))\n    } else if (isObject(buildInput)) {\n      entries = await Promise.all(Object.values(buildInput).map(resolvePath))\n    } else {\n      throw new Error('invalid rollupOptions.input value.')\n    }\n  } else {\n    entries = await globEntries('**/*.html', environment)\n  }\n\n  // Non-supported entry file types and virtual files should not be scanned for\n  // dependencies.\n  entries = entries.filter(\n    (entry) =>\n      isScannable(entry, environment.config.optimizeDeps.extensions) &&\n      fs.existsSync(entry),\n  )\n\n  return entries\n}\n\nasync function prepareRolldownScanner(\n  environment: ScanEnvironment,\n  entries: string[],\n  deps: Record<string, string>,\n  missing: Record<string, string>,\n): Promise<{ build: () => Promise<void> }> {\n  const { plugins: pluginsFromConfig = [], ...rolldownOptions } =\n    environment.config.optimizeDeps.rolldownOptions ?? {}\n\n  const plugins = await asyncFlatten(arraify(pluginsFromConfig))\n  plugins.push(...rolldownScanPlugin(environment, deps, missing, entries))\n\n  const transformOptions = deepClone(rolldownOptions.transform) ?? {}\n  if (transformOptions.jsx === undefined) {\n    transformOptions.jsx = {}\n  } else if (\n    transformOptions.jsx === 'react' ||\n    transformOptions.jsx === 'react-jsx'\n  ) {\n    transformOptions.jsx = getRollupJsxPresets(transformOptions.jsx)\n  }\n  if (typeof transformOptions.jsx === 'object') {\n    transformOptions.jsx.development ??= !environment.config.isProduction\n  }\n\n  async function build() {\n    await scan({\n      ...rolldownOptions,\n      transform: transformOptions,\n      input: entries,\n      logLevel: 'silent',\n      plugins,\n    })\n  }\n\n  return { build }\n}\n\nfunction orderedDependencies(deps: Record<string, string>) {\n  const depsList = Object.entries(deps)\n  // Ensure the same browserHash for the same set of dependencies\n  depsList.sort((a, b) => a[0].localeCompare(b[0]))\n  return Object.fromEntries(depsList)\n}\n\nasync function globEntries(\n  patterns: string | string[],\n  environment: ScanEnvironment,\n) {\n  const nodeModulesPatterns: string[] = []\n  const regularPatterns: string[] = []\n\n  for (const pattern of arraify(patterns)) {\n    if (pattern.includes('node_modules')) {\n      nodeModulesPatterns.push(pattern)\n    } else {\n      regularPatterns.push(pattern)\n    }\n  }\n\n  const sharedOptions = {\n    absolute: true,\n    cwd: environment.config.root,\n    ignore: [\n      `**/${environment.config.build.outDir}/**`,\n      // if there aren't explicit entries, also ignore other common folders\n      ...(environment.config.optimizeDeps.entries\n        ? []\n        : [`**/__tests__/**`, `**/coverage/**`]),\n    ],\n  }\n\n  const results = await Promise.all([\n    glob(nodeModulesPatterns, sharedOptions),\n    glob(regularPatterns, {\n      ...sharedOptions,\n      ignore: [...sharedOptions.ignore, '**/node_modules/**'],\n    }),\n  ])\n\n  return results.flat()\n}\n\ntype Loader = 'js' | 'ts' | 'jsx' | 'tsx'\n\nexport const scriptRE: RegExp =\n  /(<script(?:\\s+[a-z_:][-\\w:]*(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\"'<>=\\s]+))?)*\\s*>)(.*?)<\\/script>/gis\nexport const commentRE: RegExp = /<!--.*?-->/gs\nconst srcRE = /\\bsrc\\s*=\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\\s'\">]+))/i\nconst typeRE = /\\btype\\s*=\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\\s'\">]+))/i\nconst langRE = /\\blang\\s*=\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\\s'\">]+))/i\nconst svelteScriptModuleRE =\n  /\\bcontext\\s*=\\s*(?:\"([^\"]+)\"|'([^']+)'|([^\\s'\">]+))/i\nconst svelteModuleRE = /\\smodule\\b/i\n\nfunction rolldownScanPlugin(\n  environment: ScanEnvironment,\n  depImports: Record<string, string>,\n  missing: Record<string, string>,\n  entries: string[],\n): Plugin[] {\n  const seen = new Map<string, string | undefined>()\n  async function resolveId(\n    id: string,\n    importer?: string,\n  ): Promise<PartialResolvedId | null> {\n    return environment.pluginContainer.resolveId(\n      id,\n      importer && normalizePath(importer),\n      { scan: true },\n    )\n  }\n  const resolve = async (id: string, importer?: string) => {\n    const key = id + (importer && path.dirname(importer))\n    if (seen.has(key)) {\n      return seen.get(key)\n    }\n    const resolved = await resolveId(id, importer)\n    const res = resolved?.id\n    seen.set(key, res)\n    return res\n  }\n\n  const optimizeDepsOptions = environment.config.optimizeDeps\n  const include = optimizeDepsOptions.include\n  const exclude = [\n    ...(optimizeDepsOptions.exclude ?? []),\n    '@vite/client',\n    '@vite/env',\n  ]\n\n  const externalUnlessEntry = ({ path }: { path: string }) => ({\n    id: path,\n    external: !entries.includes(path),\n  })\n\n  const doTransformGlobImport = async (\n    contents: string,\n    id: string,\n    loader: Loader,\n  ) => {\n    let transpiledContents: string\n    // transpile because `transformGlobImport` only expects js\n    if (loader !== 'js') {\n      const result = transformSync(id, contents, {\n        lang: loader,\n        tsconfig: false,\n      })\n      if (result.errors.length > 0) {\n        throw new AggregateError(result.errors, 'oxc transform error')\n      }\n      transpiledContents = result.code\n    } else {\n      transpiledContents = contents\n    }\n\n    const result = await transformGlobImport(\n      transpiledContents,\n      id,\n      environment.config.root,\n      resolve,\n    )\n\n    return result?.s.toString() || transpiledContents\n  }\n\n  const scripts: Record<\n    string,\n    {\n      contents: string\n      loader: Loader\n    }\n  > = {}\n\n  const htmlTypeOnLoadCallback = async (id: string): Promise<string> => {\n    let raw = await fsp.readFile(id, 'utf-8')\n    // Avoid matching the content of the comment\n    raw = raw.replace(commentRE, '<!---->')\n    const isHtml = id.endsWith('.html')\n    let js = ''\n    let scriptId = 0\n    const matches = raw.matchAll(scriptRE)\n    for (const [, openTag, content] of matches) {\n      const typeMatch = typeRE.exec(openTag)\n      const type = typeMatch && (typeMatch[1] || typeMatch[2] || typeMatch[3])\n      const langMatch = langRE.exec(openTag)\n      const lang = langMatch && (langMatch[1] || langMatch[2] || langMatch[3])\n      // skip non type module script\n      if (isHtml && type !== 'module') {\n        continue\n      }\n      // skip type=\"application/ld+json\" and other non-JS types\n      if (\n        type &&\n        !(\n          type.includes('javascript') ||\n          type.includes('ecmascript') ||\n          type === 'module'\n        )\n      ) {\n        continue\n      }\n      let loader: Loader = 'js'\n      if (lang === 'ts' || lang === 'tsx' || lang === 'jsx') {\n        loader = lang\n      } else if (id.endsWith('.astro')) {\n        loader = 'ts'\n      }\n      const srcMatch = srcRE.exec(openTag)\n      if (srcMatch) {\n        const src = srcMatch[1] || srcMatch[2] || srcMatch[3]\n        js += `import ${JSON.stringify(src)}\\n`\n      } else if (content.trim()) {\n        // The reason why virtual modules are needed:\n        // 1. There can be module scripts (`<script context=\"module\">` in Svelte and `<script>` in Vue)\n        // or local scripts (`<script>` in Svelte and `<script setup>` in Vue)\n        // 2. There can be multiple module scripts in html\n        // We need to handle these separately in case variable names are reused between them\n\n        // append imports in TS to prevent esbuild from removing them\n        // since they may be used in the template\n        const contents =\n          content + (loader.startsWith('ts') ? extractImportPaths(content) : '')\n\n        const key = `${id}?id=${scriptId++}`\n        if (contents.includes('import.meta.glob')) {\n          scripts[key] = {\n            loader: 'js', // since it is transpiled\n            contents: await doTransformGlobImport(contents, id, loader),\n          }\n        } else {\n          scripts[key] = {\n            loader,\n            contents,\n          }\n        }\n\n        const virtualModulePath = JSON.stringify(virtualModulePrefix + key)\n\n        let addedImport = false\n\n        // For Svelte files, exports in <script context=\"module\"> or <script module> means module exports,\n        // exports in <script> means component props. To avoid having two same export name from the\n        // star exports, we need to ignore exports in <script>\n        if (id.endsWith('.svelte')) {\n          let isModule = svelteModuleRE.test(openTag) // test for svelte5 <script module> syntax\n          if (!isModule) {\n            // fallback, test for svelte4 <script context=\"module\"> syntax\n            const contextMatch = svelteScriptModuleRE.exec(openTag)\n            const context =\n              contextMatch &&\n              (contextMatch[1] || contextMatch[2] || contextMatch[3])\n            isModule = context === 'module'\n          }\n          if (!isModule) {\n            addedImport = true\n            js += `import ${virtualModulePath}\\n`\n          }\n        }\n\n        if (!addedImport) {\n          js += `export * from ${virtualModulePath}\\n`\n        }\n      }\n    }\n\n    // This will trigger incorrectly if `export default` is contained\n    // anywhere in a string. Svelte and Astro files can't have\n    // `export default` as code so we know if it's encountered it's a\n    // false positive (e.g. contained in a string)\n    if (!id.endsWith('.vue') || !js.includes('export default')) {\n      js += '\\nexport default {}'\n    }\n\n    return js\n  }\n\n  const ASSET_TYPE_RE = new RegExp(`\\\\.(${KNOWN_ASSET_TYPES.join('|')})$`)\n\n  return [\n    {\n      name: 'vite:dep-scan:resolve-external-url',\n      resolveId: {\n        // external urls\n        filter: { id: externalRE },\n        handler: (id) => ({ id, external: true }),\n      },\n    },\n    {\n      name: 'vite:dep-scan:resolve-data-url',\n      resolveId: {\n        // data urls\n        filter: { id: dataUrlRE },\n        handler: (id) => ({ id, external: true }),\n      },\n    },\n    {\n      // local scripts (`<script>` in Svelte and `<script setup>` in Vue)\n      name: 'vite:dep-scan:local-scripts',\n      resolveId: {\n        filter: { id: virtualModuleRE },\n        handler: (id) => ({ id }),\n      },\n      load: {\n        filter: { id: virtualModuleRE },\n        handler(id) {\n          const script = scripts[id.replace(virtualModulePrefix, '')]\n          return {\n            code: script.contents,\n            moduleType: script.loader,\n          }\n        },\n      },\n    },\n\n    {\n      name: 'vite:dep-scan:resolve',\n      async resolveId(id, importer) {\n        // Make sure virtual module importer can be resolve\n        importer =\n          importer && virtualModuleRE.test(importer)\n            ? importer.replace(virtualModulePrefix, '')\n            : importer\n\n        // html types: extract script contents -----------------------------------\n        if (htmlTypesRE.test(id)) {\n          const resolved = await resolve(id, importer)\n          if (!resolved) return\n          // It is possible for the scanner to scan html types in node_modules.\n          // If we can optimize this html type, skip it so it's handled by the\n          // bare import resolve, and recorded as optimization dep.\n          if (\n            isInNodeModules(resolved) &&\n            isOptimizable(resolved, optimizeDepsOptions)\n          )\n            return\n          if (shouldExternalizeDep(resolved, id)) {\n            return externalUnlessEntry({ path: id })\n          }\n          return resolved\n        }\n\n        // bare imports: record and externalize ----------------------------------\n        // avoid matching windows volume\n        if (/^[\\w@][^:]/.test(id)) {\n          if (moduleListContains(exclude, id)) {\n            return externalUnlessEntry({ path: id })\n          }\n          if (depImports[id]) {\n            return externalUnlessEntry({ path: id })\n          }\n          const resolved = await resolve(id, importer)\n          if (resolved) {\n            if (shouldExternalizeDep(resolved, id)) {\n              return externalUnlessEntry({ path: id })\n            }\n            if (isInNodeModules(resolved) || include?.includes(id)) {\n              // dependency or forced included, externalize and stop crawling\n              if (isOptimizable(resolved, optimizeDepsOptions)) {\n                depImports[id] = resolved\n              }\n              return externalUnlessEntry({ path: id })\n            } else if (isScannable(resolved, optimizeDepsOptions.extensions)) {\n              // linked package, keep crawling\n              return path.resolve(resolved)\n            } else {\n              return externalUnlessEntry({ path: id })\n            }\n          } else {\n            missing[id] = normalizePath(importer!)\n          }\n        }\n\n        // Externalized file types -----------------------------------------------\n        // these are done on raw ids using esbuild's native regex filter so it\n        // should be faster than doing it in the catch-all via js\n        // they are done after the bare import resolve because a package name\n        // may end with these extensions\n\n        // css\n        if (CSS_LANGS_RE.test(id)) {\n          return externalUnlessEntry({ path: id })\n        }\n\n        // json & wasm\n        if (/\\.(?:json|json5|wasm)$/.test(id)) {\n          return externalUnlessEntry({ path: id })\n        }\n\n        // known asset types\n        if (ASSET_TYPE_RE.test(id)) {\n          return externalUnlessEntry({ path: id })\n        }\n\n        // known vite query types: ?worker, ?raw\n        if (SPECIAL_QUERY_RE.test(id)) {\n          return {\n            id,\n            external: true,\n          }\n        }\n\n        // catch all -------------------------------------------------------------\n\n        // use vite resolver to support urls and omitted extensions\n        const resolved = await resolve(id, importer)\n        if (resolved) {\n          if (\n            shouldExternalizeDep(resolved, id) ||\n            !isScannable(resolved, optimizeDepsOptions.extensions)\n          ) {\n            return externalUnlessEntry({ path: id })\n          }\n          return path.resolve(cleanUrl(resolved))\n        }\n\n        // resolve failed... probably unsupported type\n        return externalUnlessEntry({ path: id })\n      },\n    },\n    {\n      name: 'vite:dep-scan:load:html',\n      load: {\n        // extract scripts inside HTML-like files and treat it as a js module\n        filter: { id: htmlTypesRE },\n        async handler(id) {\n          return {\n            code: await htmlTypeOnLoadCallback(id),\n            moduleType: 'js',\n          }\n        },\n      },\n    },\n    // for jsx/tsx, we need to access the content and check for\n    // presence of import.meta.glob, since it results in import relationships\n    // but isn't crawled by esbuild.\n    ...(environment.config.esbuild && environment.config.esbuild.jsxInject\n      ? [\n          {\n            name: 'vite:dep-scan:transform:jsx-inject',\n            transform: {\n              filter: {\n                id: /\\.[jt]sx$/,\n              },\n              handler(code) {\n                const esbuildConfig = environment.config.esbuild\n                if (esbuildConfig && esbuildConfig.jsxInject) {\n                  code = esbuildConfig.jsxInject + `\\n` + code\n                }\n                return code\n              },\n            },\n          } satisfies Plugin,\n        ]\n      : []),\n    {\n      name: 'vite:dep-scan:transform:js-glob',\n      transform: {\n        filter: {\n          code: 'import.meta.glob',\n        },\n        async handler(code, id) {\n          if (JS_TYPES_RE.test(id)) {\n            let ext = path.extname(id).slice(1)\n            if (ext === 'mjs') ext = 'js'\n            const loader = ext as 'js' | 'ts' | 'jsx' | 'tsx'\n            return {\n              moduleType: 'js',\n              code: await doTransformGlobImport(code, id, loader),\n            }\n          }\n        },\n      },\n    },\n  ]\n}\n\n/**\n * when using TS + (Vue + `<script setup>`) or Svelte, imports may seem\n * unused to esbuild and dropped in the build output, which prevents\n * esbuild from crawling further.\n * the solution is to add `import 'x'` for every source to force\n * esbuild to keep crawling due to potential side effects.\n */\nfunction extractImportPaths(code: string) {\n  // empty singleline & multiline comments to avoid matching comments\n  code = code\n    .replace(multilineCommentsRE, '/* */')\n    .replace(singlelineCommentsRE, '')\n\n  let js = ''\n  let m\n  importsRE.lastIndex = 0\n  while ((m = importsRE.exec(code)) != null) {\n    js += `\\nimport ${m[1]}`\n  }\n  return js\n}\n\nfunction shouldExternalizeDep(resolvedId: string, rawId: string): boolean {\n  // not a valid file path\n  if (!path.isAbsolute(resolvedId)) {\n    return true\n  }\n  // virtual id\n  if (resolvedId === rawId || resolvedId.includes('\\0')) {\n    return true\n  }\n  return false\n}\n\nfunction isScannable(id: string, extensions: string[] | undefined): boolean {\n  return (\n    JS_TYPES_RE.test(id) ||\n    htmlTypesRE.test(id) ||\n    extensions?.includes(path.extname(id)) ||\n    false\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/node/packages.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { createRequire } from 'node:module'\nimport {\n  createFilter,\n  isInNodeModules,\n  normalizePath,\n  safeRealpathSync,\n  stripBomTag,\n  tryStatSync,\n} from './utils'\nimport type { Plugin } from './plugin'\nimport type { InternalResolveOptions } from './plugins/resolve'\n\nlet pnp: typeof import('pnpapi') | undefined\nif (process.versions.pnp) {\n  try {\n    pnp = createRequire(/** #__KEEP__ */ import.meta.url)('pnpapi')\n  } catch {}\n}\n\n/** Cache for package.json resolution and package.json contents */\nexport type PackageCache = Map<string, PackageData>\n\nexport interface PackageData {\n  dir: string\n  hasSideEffects: (id: string) => boolean | 'no-treeshake' | null\n  setResolvedCache: (\n    key: string,\n    entry: string,\n    options: InternalResolveOptions,\n  ) => void\n  getResolvedCache: (\n    key: string,\n    options: InternalResolveOptions,\n  ) => string | undefined\n  data: {\n    [field: string]: any\n    name: string\n    type: string\n    version: string\n    main: string\n    module: string\n    browser: string | Record<string, string | false>\n    exports: string | Record<string, any> | string[]\n    imports: Record<string, any>\n    dependencies: Record<string, string>\n  }\n}\n\nfunction invalidatePackageData(\n  packageCache: PackageCache,\n  pkgPath: string,\n): void {\n  const pkgDir = normalizePath(path.dirname(pkgPath))\n  packageCache.forEach((pkg, cacheKey) => {\n    if (pkg.dir === pkgDir) {\n      packageCache.delete(cacheKey)\n    }\n  })\n}\n\nexport function resolvePackageData(\n  pkgName: string,\n  basedir: string,\n  preserveSymlinks = false,\n  packageCache?: PackageCache,\n): PackageData | null {\n  if (pnp) {\n    const cacheKey = getRpdCacheKey(pkgName, basedir, preserveSymlinks)\n    if (packageCache?.has(cacheKey)) return packageCache.get(cacheKey)!\n\n    try {\n      const pkg = pnp.resolveToUnqualified(pkgName, basedir, {\n        considerBuiltins: false,\n      })\n      if (!pkg) return null\n\n      const pkgData = loadPackageData(path.join(pkg, 'package.json'))\n      packageCache?.set(cacheKey, pkgData)\n      return pkgData\n    } catch {\n      return null\n    }\n  }\n\n  const originalBasedir = basedir\n  while (basedir) {\n    if (packageCache) {\n      const cached = getRpdCache(\n        packageCache,\n        pkgName,\n        basedir,\n        originalBasedir,\n        preserveSymlinks,\n      )\n      if (cached) return cached\n    }\n\n    const pkg = path.join(basedir, 'node_modules', pkgName, 'package.json')\n    try {\n      if (fs.existsSync(pkg)) {\n        const pkgPath = preserveSymlinks ? pkg : safeRealpathSync(pkg)\n        const pkgData = loadPackageData(pkgPath)\n\n        if (packageCache) {\n          setRpdCache(\n            packageCache,\n            pkgData,\n            pkgName,\n            basedir,\n            originalBasedir,\n            preserveSymlinks,\n          )\n        }\n\n        return pkgData\n      }\n    } catch {}\n\n    const nextBasedir = path.dirname(basedir)\n    if (nextBasedir === basedir) break\n    basedir = nextBasedir\n  }\n\n  return null\n}\n\nexport function findNearestPackageData(\n  basedir: string,\n  packageCache?: PackageCache,\n): PackageData | null {\n  const originalBasedir = basedir\n  while (basedir) {\n    if (packageCache) {\n      const cached = getFnpdCache(packageCache, basedir, originalBasedir)\n      if (cached) return cached\n    }\n\n    const pkgPath = path.join(basedir, 'package.json')\n    if (tryStatSync(pkgPath)?.isFile()) {\n      try {\n        const pkgData = loadPackageData(pkgPath)\n\n        if (packageCache) {\n          setFnpdCache(packageCache, pkgData, basedir, originalBasedir)\n        }\n\n        return pkgData\n      } catch {}\n    }\n\n    const nextBasedir = path.dirname(basedir)\n    if (nextBasedir === basedir) break\n    basedir = nextBasedir\n  }\n\n  return null\n}\n\n// Finds the nearest package.json with a `name` field\nexport function findNearestMainPackageData(\n  basedir: string,\n  packageCache?: PackageCache,\n): PackageData | null {\n  const nearestPackage = findNearestPackageData(basedir, packageCache)\n  return (\n    nearestPackage &&\n    (nearestPackage.data.name\n      ? nearestPackage\n      : findNearestMainPackageData(\n          path.dirname(nearestPackage.dir),\n          packageCache,\n        ))\n  )\n}\n\nexport function loadPackageData(pkgPath: string): PackageData {\n  const data = JSON.parse(stripBomTag(fs.readFileSync(pkgPath, 'utf-8')))\n  const pkgDir = normalizePath(path.dirname(pkgPath))\n  const { sideEffects } = data\n  let hasSideEffects: (id: string) => boolean | null\n  if (typeof sideEffects === 'boolean') {\n    hasSideEffects = () => sideEffects\n  } else if (Array.isArray(sideEffects)) {\n    if (sideEffects.length <= 0) {\n      // createFilter always returns true if `includes` is an empty array\n      // but here we want it to always return false\n      hasSideEffects = () => false\n    } else {\n      const finalPackageSideEffects = sideEffects.map((sideEffect) => {\n        /*\n         * The array accepts simple glob patterns to the relevant files... Patterns like *.css, which do not include a /, will be treated like **\\/*.css.\n         * https://webpack.js.org/guides/tree-shaking/\n         * https://github.com/vitejs/vite/pull/11807\n         */\n        if (sideEffect.includes('/')) {\n          return sideEffect\n        }\n        return `**/${sideEffect}`\n      })\n\n      hasSideEffects = createFilter(finalPackageSideEffects, null, {\n        resolve: pkgDir,\n      })\n    }\n  } else {\n    hasSideEffects = () => null\n  }\n\n  const resolvedCache: Record<string, string | undefined> = {}\n  const pkg: PackageData = {\n    dir: pkgDir,\n    data,\n    hasSideEffects,\n    setResolvedCache(key, entry, options) {\n      resolvedCache[getResolveCacheKey(key, options)] = entry\n    },\n    getResolvedCache(key, options) {\n      return resolvedCache[getResolveCacheKey(key, options)]\n    },\n  }\n\n  return pkg\n}\n\nfunction getResolveCacheKey(key: string, options: InternalResolveOptions) {\n  // cache key needs to include options which affect\n  // `resolvePackageEntry` or `resolveDeepImport`\n  return [\n    key,\n    options.isRequire ? '1' : '0',\n    options.conditions.join('_'),\n    options.extensions.join('_'),\n    options.mainFields.join('_'),\n  ].join('|')\n}\n\nexport function findNearestNodeModules(basedir: string): string | null {\n  while (basedir) {\n    const pkgPath = path.join(basedir, 'node_modules')\n    if (tryStatSync(pkgPath)?.isDirectory()) {\n      return pkgPath\n    }\n\n    const nextBasedir = path.dirname(basedir)\n    if (nextBasedir === basedir) break\n    basedir = nextBasedir\n  }\n\n  return null\n}\n\nexport function watchPackageDataPlugin(packageCache: PackageCache): Plugin {\n  // a list of files to watch before the plugin is ready\n  const watchQueue = new Set<string>()\n  const watchedDirs = new Set<string>()\n\n  const watchFileStub = (id: string) => {\n    watchQueue.add(id)\n  }\n  let watchFile = watchFileStub\n\n  const setPackageData = packageCache.set.bind(packageCache)\n  packageCache.set = (id, pkg) => {\n    if (!isInNodeModules(pkg.dir) && !watchedDirs.has(pkg.dir)) {\n      watchedDirs.add(pkg.dir)\n      watchFile(path.join(pkg.dir, 'package.json'))\n    }\n    return setPackageData(id, pkg)\n  }\n\n  return {\n    name: 'vite:watch-package-data',\n    buildStart() {\n      watchFile = this.addWatchFile.bind(this)\n      watchQueue.forEach(watchFile)\n      watchQueue.clear()\n    },\n    buildEnd() {\n      watchFile = watchFileStub\n    },\n    watchChange(id) {\n      if (id.endsWith('/package.json')) {\n        invalidatePackageData(packageCache, path.normalize(id))\n      }\n    },\n  }\n}\n\n/**\n * Get cached `resolvePackageData` value based on `basedir`. When one is found,\n * and we've already traversed some directories between `basedir` and `originalBasedir`,\n * we cache the value for those in-between directories as well.\n *\n * This makes it so the fs is only read once for a shared `basedir`.\n */\nfunction getRpdCache(\n  packageCache: PackageCache,\n  pkgName: string,\n  basedir: string,\n  originalBasedir: string,\n  preserveSymlinks: boolean,\n) {\n  const cacheKey = getRpdCacheKey(pkgName, basedir, preserveSymlinks)\n  const pkgData = packageCache.get(cacheKey)\n  if (pkgData) {\n    traverseBetweenDirs(originalBasedir, basedir, (dir) => {\n      packageCache.set(getRpdCacheKey(pkgName, dir, preserveSymlinks), pkgData)\n    })\n    return pkgData\n  }\n}\n\nfunction setRpdCache(\n  packageCache: PackageCache,\n  pkgData: PackageData,\n  pkgName: string,\n  basedir: string,\n  originalBasedir: string,\n  preserveSymlinks: boolean,\n) {\n  packageCache.set(getRpdCacheKey(pkgName, basedir, preserveSymlinks), pkgData)\n  traverseBetweenDirs(originalBasedir, basedir, (dir) => {\n    packageCache.set(getRpdCacheKey(pkgName, dir, preserveSymlinks), pkgData)\n  })\n}\n\n// package cache key for `resolvePackageData`\nfunction getRpdCacheKey(\n  pkgName: string,\n  basedir: string,\n  preserveSymlinks: boolean,\n) {\n  return `rpd_${pkgName}_${basedir}_${preserveSymlinks}`\n}\n\n/**\n * Get cached `findNearestPackageData` value based on `basedir`. When one is found,\n * and we've already traversed some directories between `basedir` and `originalBasedir`,\n * we cache the value for those in-between directories as well.\n *\n * This makes it so the fs is only read once for a shared `basedir`.\n */\nfunction getFnpdCache(\n  packageCache: PackageCache,\n  basedir: string,\n  originalBasedir: string,\n) {\n  const cacheKey = getFnpdCacheKey(basedir)\n  const pkgData = packageCache.get(cacheKey)\n  if (pkgData) {\n    traverseBetweenDirs(originalBasedir, basedir, (dir) => {\n      packageCache.set(getFnpdCacheKey(dir), pkgData)\n    })\n    return pkgData\n  }\n}\n\nfunction setFnpdCache(\n  packageCache: PackageCache,\n  pkgData: PackageData,\n  basedir: string,\n  originalBasedir: string,\n) {\n  packageCache.set(getFnpdCacheKey(basedir), pkgData)\n  traverseBetweenDirs(originalBasedir, basedir, (dir) => {\n    packageCache.set(getFnpdCacheKey(dir), pkgData)\n  })\n}\n\n// package cache key for `findNearestPackageData`\nfunction getFnpdCacheKey(basedir: string) {\n  return `fnpd_${basedir}`\n}\n\n/**\n * Traverse between `longerDir` (inclusive) and `shorterDir` (exclusive) and call `cb` for each dir.\n * @param longerDir Longer dir path, e.g. `/User/foo/bar/baz`\n * @param shorterDir Shorter dir path, e.g. `/User/foo`\n */\nfunction traverseBetweenDirs(\n  longerDir: string,\n  shorterDir: string,\n  cb: (dir: string) => void,\n) {\n  while (longerDir !== shorterDir) {\n    cb(longerDir)\n    longerDir = path.dirname(longerDir)\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugin.ts",
    "content": "import type {\n  CustomPluginOptions,\n  ImportKind,\n  LoadResult,\n  MinimalPluginContext,\n  ModuleType,\n  ModuleTypeFilter,\n  ObjectHook,\n  PluginContext,\n  PluginContextMeta,\n  ResolveIdResult,\n  Plugin as RolldownPlugin,\n  TransformPluginContext,\n  TransformResult,\n} from 'rolldown'\nimport type {\n  ConfigEnv,\n  EnvironmentOptions,\n  ResolvedConfig,\n  UserConfig,\n} from './config'\nimport type { ServerHook } from './server'\nimport type { BuildAppHook } from './build'\nimport type { IndexHtmlTransform } from './plugins/html'\nimport type { EnvironmentModuleNode } from './server/moduleGraph'\nimport type { ModuleNode } from './server/mixedModuleGraph'\nimport type { HmrContext, HotUpdateOptions } from './server/hmr'\nimport type { DevEnvironment } from './server/environment'\nimport type { Environment } from './environment'\nimport type { PartialEnvironment } from './baseEnvironment'\nimport type { PreviewServerHook } from './preview'\nimport { arraify, asyncFlatten } from './utils'\nimport type { StringFilter } from './plugins/pluginFilter'\n\n/**\n * Vite plugins extends the Rollup plugin interface with a few extra\n * vite-specific options. A valid vite plugin is also a valid Rollup plugin.\n * On the contrary, a Rollup plugin may or may NOT be a valid vite universal\n * plugin, since some Rollup features do not make sense in an unbundled\n * dev server context. That said, as long as a rollup plugin doesn't have strong\n * coupling between its bundle phase and output phase hooks then it should\n * just work (that means, most of them).\n *\n * By default, the plugins are run during both serve and build. When a plugin\n * is applied during serve, it will only run **non output plugin hooks** (see\n * rollup type definition of {@link rollup#PluginHooks}). You can think of the\n * dev server as only running `const bundle = rollup.rollup()` but never calling\n * `bundle.generate()`.\n *\n * A plugin that expects to have different behavior depending on serve/build can\n * export a factory function that receives the command being run via options.\n *\n * If a plugin should be applied only for server or build, a function format\n * config file can be used to conditional determine the plugins to use.\n *\n * The current environment can be accessed from the context for the all non-global\n * hooks (it is not available in config, configResolved, configureServer, etc).\n * It can be a dev, build, or scan environment.\n * Plugins can use this.environment.mode === 'dev' to guard for dev specific APIs.\n */\n\nexport interface PluginContextExtension {\n  /**\n   * Vite-specific environment instance\n   */\n  environment: Environment\n}\n\nexport interface PluginContextMetaExtension {\n  viteVersion: string\n}\n\nexport interface ConfigPluginContext extends Omit<\n  MinimalPluginContext,\n  'meta' | 'environment'\n> {\n  meta: Omit<PluginContextMeta, 'watchMode'>\n}\n\nexport interface MinimalPluginContextWithoutEnvironment extends Omit<\n  MinimalPluginContext,\n  'environment'\n> {}\n\n// Augment Rolldown types to have the PluginContextExtension\ndeclare module 'rolldown' {\n  export interface MinimalPluginContext extends PluginContextExtension {}\n  export interface PluginContextMeta extends PluginContextMetaExtension {}\n}\n\n/**\n * There are two types of plugins in Vite. App plugins and environment plugins.\n * Environment Plugins are defined by a constructor function that will be called\n * once per each environment allowing users to have completely different plugins\n * for each of them. The constructor gets the resolved environment after the server\n * and builder has already been created simplifying config access and cache\n * management for environment specific plugins.\n * Environment Plugins are closer to regular rollup plugins. They can't define\n * app level hooks (like config, configResolved, configureServer, etc).\n */\nexport interface Plugin<A = any> extends RolldownPlugin<A> {\n  /**\n   * Perform custom handling of HMR updates.\n   * The handler receives an options containing changed filename, timestamp, a\n   * list of modules affected by the file change, and the dev server instance.\n   *\n   * - The hook can return a filtered list of modules to narrow down the update.\n   *   e.g. for a Vue SFC, we can narrow down the part to update by comparing\n   *   the descriptors.\n   *\n   * - The hook can also return an empty array and then perform custom updates\n   *   by sending a custom hmr payload via environment.hot.send().\n   *\n   * - If the hook doesn't return a value, the hmr update will be performed as\n   *   normal.\n   */\n  hotUpdate?: ObjectHook<\n    (\n      this: MinimalPluginContext & { environment: DevEnvironment },\n      options: HotUpdateOptions,\n    ) =>\n      | Array<EnvironmentModuleNode>\n      | void\n      | Promise<Array<EnvironmentModuleNode> | void>\n  >\n\n  /**\n   * extend hooks with ssr flag\n   */\n  resolveId?: ObjectHook<\n    (\n      this: PluginContext,\n      source: string,\n      importer: string | undefined,\n      options: {\n        kind?: ImportKind\n        custom?: CustomPluginOptions\n        ssr?: boolean | undefined\n        /**\n         * @internal\n         */\n        scan?: boolean | undefined\n        isEntry: boolean\n      },\n    ) => Promise<ResolveIdResult> | ResolveIdResult,\n    { filter?: { id?: StringFilter<RegExp> } }\n  >\n  load?: ObjectHook<\n    (\n      this: PluginContext,\n      id: string,\n      options?: {\n        ssr?: boolean | undefined\n      },\n    ) => Promise<LoadResult> | LoadResult,\n    { filter?: { id?: StringFilter } }\n  >\n  transform?: ObjectHook<\n    (\n      this: TransformPluginContext,\n      code: string,\n      id: string,\n      options?: {\n        moduleType: ModuleType\n        ssr?: boolean | undefined\n      },\n    ) => Promise<TransformResult> | TransformResult,\n    {\n      filter?: {\n        id?: StringFilter\n        code?: StringFilter\n        moduleType?: ModuleTypeFilter\n      }\n    }\n  >\n  /**\n   * Opt-in this plugin into the shared plugins pipeline.\n   * For backward-compatibility, plugins are re-recreated for each environment\n   * during `vite build --app`\n   * We have an opt-in per plugin, and a general `builder.sharedPlugins`\n   * In a future major, we'll flip the default to be shared by default\n   * @experimental\n   */\n  sharedDuringBuild?: boolean\n  /**\n   * Opt-in this plugin into per-environment buildStart and buildEnd during dev.\n   * For backward-compatibility, the buildStart hook is called only once during\n   * dev, for the client environment. Plugins can opt-in to be called\n   * per-environment, aligning with the build hook behavior.\n   * @experimental\n   */\n  perEnvironmentStartEndDuringDev?: boolean\n  /**\n   * Opt-in this plugin into per-environment watchChange during dev.\n   * For backward-compatibility, the watchChange hook is called only once during\n   * dev, for the client environment. Plugins can opt-in to be called\n   * per-environment, aligning with the watchChange hook behavior.\n   * @experimental\n   */\n  perEnvironmentWatchChangeDuringDev?: boolean\n  /**\n   * Enforce plugin invocation tier similar to webpack loaders. Hooks ordering\n   * is still subject to the `order` property in the hook object.\n   *\n   * Plugin invocation order:\n   * - alias resolution\n   * - `enforce: 'pre'` plugins\n   * - vite core plugins\n   * - normal plugins\n   * - vite build plugins\n   * - `enforce: 'post'` plugins\n   * - vite build post plugins\n   */\n  enforce?: 'pre' | 'post'\n  /**\n   * Apply the plugin only for serve or build, or on certain conditions.\n   */\n  apply?:\n    | 'serve'\n    | 'build'\n    | ((this: void, config: UserConfig, env: ConfigEnv) => boolean)\n  /**\n   * Define environments where this plugin should be active\n   * By default, the plugin is active in all environments\n   * @experimental\n   */\n  applyToEnvironment?: (\n    environment: PartialEnvironment,\n  ) => boolean | Promise<boolean> | PluginOption\n  /**\n   * Modify vite config before it's resolved. The hook can either mutate the\n   * passed-in config directly, or return a partial config object that will be\n   * deeply merged into existing config.\n   *\n   * Note: User plugins are resolved before running this hook so injecting other\n   * plugins inside  the `config` hook will have no effect.\n   */\n  config?: ObjectHook<\n    (\n      this: ConfigPluginContext,\n      config: UserConfig,\n      env: ConfigEnv,\n    ) =>\n      | Omit<UserConfig, 'plugins'>\n      | null\n      | void\n      | Promise<Omit<UserConfig, 'plugins'> | null | void>\n  >\n  /**\n   * Modify environment configs before it's resolved. The hook can either mutate the\n   * passed-in environment config directly, or return a partial config object that will be\n   * deeply merged into existing config.\n   * This hook is called for each environment with a partially resolved environment config\n   * that already accounts for the default environment config values set at the root level.\n   * If plugins need to modify the config of a given environment, they should do it in this\n   * hook instead of the config hook. Leaving the config hook only for modifying the root\n   * default environment config.\n   */\n  configEnvironment?: ObjectHook<\n    (\n      this: ConfigPluginContext,\n      name: string,\n      config: EnvironmentOptions,\n      env: ConfigEnv & {\n        /**\n         * Whether this environment is SSR environment and `ssr.target` is set to `'webworker'`.\n         * Only intended to be used for backward compatibility.\n         */\n        isSsrTargetWebworker?: boolean\n      },\n    ) =>\n      | EnvironmentOptions\n      | null\n      | void\n      | Promise<EnvironmentOptions | null | void>\n  >\n  /**\n   * Use this hook to read and store the final resolved vite config.\n   */\n  configResolved?: ObjectHook<\n    (\n      this: MinimalPluginContextWithoutEnvironment,\n      config: ResolvedConfig,\n    ) => void | Promise<void>\n  >\n  /**\n   * Configure the vite server. The hook receives the {@link ViteDevServer}\n   * instance. This can also be used to store a reference to the server\n   * for use in other hooks.\n   *\n   * The hooks will be called before internal middlewares are applied. A hook\n   * can return a post hook that will be called after internal middlewares\n   * are applied. Hook can be async functions and will be called in series.\n   */\n  configureServer?: ObjectHook<ServerHook>\n  /**\n   * Configure the preview server. The hook receives the {@link PreviewServer}\n   * instance. This can also be used to store a reference to the server\n   * for use in other hooks.\n   *\n   * The hooks are called before other middlewares are applied. A hook can\n   * return a post hook that will be called after other middlewares are\n   * applied. Hooks can be async functions and will be called in series.\n   */\n  configurePreviewServer?: ObjectHook<PreviewServerHook>\n  /**\n   * Transform index.html.\n   * The hook receives the following arguments:\n   *\n   * - html: string\n   * - ctx: IndexHtmlTransformContext, which contains:\n   *    - path: public path when served\n   *    - filename: filename on disk\n   *    - server?: ViteDevServer (only present during serve)\n   *    - bundle?: rollup.OutputBundle (only present during build)\n   *    - chunk?: rollup.OutputChunk\n   *    - originalUrl?: string\n   *\n   * It can either return a transformed string, or a list of html tag\n   * descriptors that will be injected into the `<head>` or `<body>`.\n   *\n   * By default the transform is applied **after** vite's internal html\n   * transform. If you need to apply the transform before vite, use an object:\n   * `{ order: 'pre', handler: hook }`\n   */\n  transformIndexHtml?: IndexHtmlTransform\n  /**\n   * Build Environments\n   *\n   * @experimental\n   */\n  buildApp?: ObjectHook<BuildAppHook>\n  /**\n   * Perform custom handling of HMR updates.\n   * The handler receives a context containing changed filename, timestamp, a\n   * list of modules affected by the file change, and the dev server instance.\n   *\n   * - The hook can return a filtered list of modules to narrow down the update.\n   *   e.g. for a Vue SFC, we can narrow down the part to update by comparing\n   *   the descriptors.\n   *\n   * - The hook can also return an empty array and then perform custom updates\n   *   by sending a custom hmr payload via server.ws.send().\n   *\n   * - If the hook doesn't return a value, the hmr update will be performed as\n   *   normal.\n   */\n  handleHotUpdate?: ObjectHook<\n    (\n      this: MinimalPluginContextWithoutEnvironment,\n      ctx: HmrContext,\n    ) => Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>\n  >\n\n  /**\n   * This hook is not supported by Rolldown yet. But the type is declared for compatibility.\n   *\n   * @deprecated This hook is **not** deprecated. It is marked as deprecated just to make it clear that this hook is currently a no-op.\n   */\n  shouldTransformCachedModule?: ObjectHook<\n    (\n      this: PluginContext,\n      options: {\n        code: string\n        id: string\n        meta: CustomPluginOptions\n        moduleSideEffects: boolean | 'no-treeshake'\n      },\n    ) => boolean | null | void\n  >\n}\n\nexport type HookHandler<T> = T extends ObjectHook<infer H> ? H : T\n\nexport type PluginWithRequiredHook<K extends keyof Plugin> = Plugin & {\n  [P in K]: NonNullable<Plugin[P]>\n}\n\ntype Thenable<T> = T | Promise<T>\n\nexport type FalsyPlugin = false | null | undefined\n\nexport type PluginOption = Thenable<\n  | Plugin\n  | { name: string } // for rollup plugin compatibility\n  | FalsyPlugin\n  | PluginOption[]\n>\n\nexport async function resolveEnvironmentPlugins(\n  environment: PartialEnvironment,\n): Promise<Plugin[]> {\n  const environmentPlugins: Plugin[] = []\n  for (const plugin of environment.getTopLevelConfig().plugins) {\n    if (plugin.applyToEnvironment) {\n      const applied = await plugin.applyToEnvironment(environment)\n      if (!applied) {\n        continue\n      }\n      if (applied !== true) {\n        environmentPlugins.push(\n          ...((await asyncFlatten(arraify(applied))).filter(\n            Boolean,\n          ) as Plugin[]),\n        )\n        continue\n      }\n    }\n    environmentPlugins.push(plugin)\n  }\n  return environmentPlugins\n}\n\n/**\n * @experimental\n */\nexport function perEnvironmentPlugin(\n  name: string,\n  applyToEnvironment: (\n    environment: PartialEnvironment,\n  ) => boolean | Promise<boolean> | PluginOption,\n): Plugin {\n  return {\n    name,\n    applyToEnvironment,\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/asset.ts",
    "content": "import path from 'node:path'\nimport fsp from 'node:fs/promises'\nimport { Buffer } from 'node:buffer'\nimport { pathToFileURL } from 'node:url'\nimport * as mrmime from 'mrmime'\nimport type {\n  NormalizedOutputOptions,\n  PluginContext,\n  RenderedChunk,\n} from 'rolldown'\nimport MagicString from 'magic-string'\nimport colors from 'picocolors'\nimport picomatch from 'picomatch'\nimport { makeIdFiltersToMatchWithQuery } from 'rolldown/filter'\nimport {\n  createToImportMetaURLBasedRelativeRuntime,\n  toOutputFilePathInJS,\n} from '../build'\nimport type { Plugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport { checkPublicFile } from '../publicDir'\nimport {\n  encodeURIPath,\n  getHash,\n  injectQuery,\n  joinUrlSegments,\n  normalizePath,\n  rawRE,\n  removeLeadingSlash,\n  removeUrlQuery,\n  urlRE,\n} from '../utils'\nimport {\n  DEFAULT_ASSETS_INLINE_LIMIT,\n  DEFAULT_ASSETS_RE,\n  FS_PREFIX,\n} from '../constants'\nimport {\n  cleanUrl,\n  splitFileAndPostfix,\n  withTrailingSlash,\n} from '../../shared/utils'\nimport type { Environment } from '../environment'\nimport type { PartialEnvironment } from '../baseEnvironment'\n\n// referenceId is base64url but replaces - with $\nexport const assetUrlRE: RegExp = /__VITE_ASSET__([\\w$]+)__(?:\\$_(.*?)__)?/g\n\nconst jsSourceMapRE = /\\.[cm]?js\\.map$/\n\nexport const noInlineRE: RegExp = /[?&]no-inline\\b/\nexport const inlineRE: RegExp = /[?&]inline\\b/\n\nconst assetCache = new WeakMap<Environment, Map<string, string>>()\n\n/** a set of referenceId for entry CSS assets for each environment */\nexport const cssEntriesMap: WeakMap<\n  Environment,\n  Map<string, string>\n> = new WeakMap()\n\n// add own dictionary entry by directly assigning mrmime\nexport function registerCustomMime(): void {\n  // https://github.com/lukeed/mrmime/issues/3\n  // instead of `image/vnd.microsoft.icon` which is registered on IANA Media Types DB\n  // image/x-icon should be used instead for better compatibility (https://github.com/h5bp/html5-boilerplate/issues/219)\n  mrmime.mimes['ico'] = 'image/x-icon'\n  // https://mimesniff.spec.whatwg.org/#matching-an-image-type-pattern\n  mrmime.mimes['cur'] = 'image/x-icon'\n  // https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#flac\n  mrmime.mimes['flac'] = 'audio/flac'\n  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types\n  mrmime.mimes['eot'] = 'application/vnd.ms-fontobject'\n}\n\nexport function renderAssetUrlInJS(\n  pluginContext: PluginContext,\n  chunk: RenderedChunk,\n  opts: NormalizedOutputOptions,\n  code: string,\n): MagicString | undefined {\n  const { environment } = pluginContext\n  const toRelativeRuntime = createToImportMetaURLBasedRelativeRuntime(\n    opts.format,\n    environment.config.isWorker,\n  )\n\n  let match: RegExpExecArray | null\n  let s: MagicString | undefined\n\n  // Urls added with JS using e.g.\n  // imgElement.src = \"__VITE_ASSET__5aA0Ddc0__\" are using quotes\n\n  // Urls added in CSS that is imported in JS end up like\n  // var inlined = \".inlined{color:green;background:url(__VITE_ASSET__5aA0Ddc0__)}\\n\";\n\n  // In both cases, the wrapping should already be fine\n\n  assetUrlRE.lastIndex = 0\n  while ((match = assetUrlRE.exec(code))) {\n    s ||= new MagicString(code)\n    const [full, referenceId, postfix = ''] = match\n    const file = pluginContext.getFileName(referenceId)\n    chunk.viteMetadata!.importedAssets.add(cleanUrl(file))\n    const filename = file + postfix\n    const replacement = toOutputFilePathInJS(\n      environment,\n      filename,\n      'asset',\n      chunk.fileName,\n      'js',\n      toRelativeRuntime,\n    )\n    const replacementString =\n      typeof replacement === 'string'\n        ? JSON.stringify(encodeURIPath(replacement)).slice(1, -1)\n        : `\"+${replacement.runtime}+\"`\n    s.update(match.index, match.index + full.length, replacementString)\n  }\n\n  // Replace __VITE_PUBLIC_ASSET__5aA0Ddc0__ with absolute paths\n\n  const publicAssetUrlMap = publicAssetUrlCache.get(\n    environment.getTopLevelConfig(),\n  )!\n  publicAssetUrlRE.lastIndex = 0\n  while ((match = publicAssetUrlRE.exec(code))) {\n    s ||= new MagicString(code)\n    const [full, hash] = match\n    const publicUrl = publicAssetUrlMap.get(hash)!.slice(1)\n    const replacement = toOutputFilePathInJS(\n      environment,\n      publicUrl,\n      'public',\n      chunk.fileName,\n      'js',\n      toRelativeRuntime,\n    )\n    const replacementString =\n      typeof replacement === 'string'\n        ? JSON.stringify(encodeURIPath(replacement)).slice(1, -1)\n        : `\"+${replacement.runtime}+\"`\n    s.update(match.index, match.index + full.length, replacementString)\n  }\n\n  return s\n}\n\n/**\n * Also supports loading plain strings with import text from './foo.txt?raw'\n */\nexport function assetPlugin(config: ResolvedConfig): Plugin {\n  registerCustomMime()\n\n  return {\n    name: 'vite:asset',\n\n    perEnvironmentStartEndDuringDev: true,\n\n    buildStart() {\n      assetCache.set(this.environment, new Map())\n      cssEntriesMap.set(this.environment, new Map())\n    },\n\n    resolveId: {\n      filter: {\n        id: [\n          urlRE,\n          DEFAULT_ASSETS_RE,\n          ...makeIdFiltersToMatchWithQuery(config.rawAssetsInclude).map((v) =>\n            typeof v === 'string' ? picomatch.makeRe(v, { dot: true }) : v,\n          ),\n        ],\n      },\n      handler(id) {\n        if (!config.assetsInclude(cleanUrl(id)) && !urlRE.test(id)) {\n          return\n        }\n        // imports to absolute urls pointing to files in /public\n        // will fail to resolve in the main resolver. handle them here.\n        const publicFile = checkPublicFile(id, config)\n        if (publicFile) {\n          return id\n        }\n      },\n    },\n\n    load: {\n      filter: {\n        id: {\n          include: [\n            rawRE,\n            urlRE,\n            DEFAULT_ASSETS_RE,\n            ...makeIdFiltersToMatchWithQuery(config.rawAssetsInclude),\n          ],\n          // Rollup convention, this id should be handled by the\n          // plugin that marked it with \\0\n          exclude: /^\\0/,\n        },\n      },\n      async handler(id) {\n        // raw requests, read from disk\n        if (rawRE.test(id)) {\n          const file = checkPublicFile(id, config) || cleanUrl(id)\n          this.addWatchFile(file)\n          // raw query, read file and return as string\n          return {\n            code: `export default ${JSON.stringify(\n              await fsp.readFile(file, 'utf-8'),\n            )}`,\n            moduleType: 'js', // NOTE: needs to be set to avoid double `export default` in `?raw&.txt`s\n          }\n        }\n\n        if (!urlRE.test(id) && !config.assetsInclude(cleanUrl(id))) {\n          return\n        }\n\n        id = removeUrlQuery(id)\n        let url = await fileToUrl(this, id)\n\n        // Inherit HMR timestamp if this asset was invalidated\n        if (!url.startsWith('data:') && this.environment.mode === 'dev') {\n          const mod = this.environment.moduleGraph.getModuleById(id)\n          if (mod && mod.lastHMRTimestamp > 0) {\n            url = injectQuery(url, `t=${mod.lastHMRTimestamp}`)\n          }\n        }\n\n        return {\n          code: `export default ${JSON.stringify(encodeURIPath(url))}`,\n          // Force rollup to keep this module from being shared between other entry points if it's an entrypoint.\n          // If the resulting chunk is empty, it will be removed in generateBundle.\n          moduleSideEffects:\n            config.command === 'build' && this.getModuleInfo(id)?.isEntry\n              ? 'no-treeshake'\n              : false,\n          meta: config.command === 'build' ? { 'vite:asset': true } : undefined,\n          moduleType: 'js', // NOTE: needs to be set to avoid double `export default` in `.txt`s\n        }\n      },\n    },\n\n    ...(config.command === 'build'\n      ? {\n          renderChunk(code, chunk, opts) {\n            const s = renderAssetUrlInJS(this, chunk, opts, code)\n\n            if (s) {\n              return {\n                code: s.toString(),\n                map: this.environment.config.build.sourcemap\n                  ? s.generateMap({ hires: 'boundary' })\n                  : null,\n              }\n            } else {\n              return null\n            }\n          },\n        }\n      : {}),\n\n    generateBundle(_, bundle) {\n      // Remove empty entry point file\n      let importedFiles: Set<string> | undefined\n      for (const file in bundle) {\n        const chunk = bundle[file]\n        if (\n          chunk.type === 'chunk' &&\n          chunk.isEntry &&\n          chunk.moduleIds.length === 1 &&\n          config.assetsInclude(chunk.moduleIds[0]) &&\n          this.getModuleInfo(chunk.moduleIds[0])?.meta['vite:asset']\n        ) {\n          if (!importedFiles) {\n            importedFiles = new Set()\n            for (const file in bundle) {\n              const chunk = bundle[file]\n              if (chunk.type === 'chunk') {\n                for (const importedFile of chunk.imports) {\n                  importedFiles.add(importedFile)\n                }\n                for (const importedFile of chunk.dynamicImports) {\n                  importedFiles.add(importedFile)\n                }\n              }\n            }\n          }\n          if (!importedFiles.has(file)) {\n            delete bundle[file]\n          }\n        }\n      }\n\n      // do not emit assets for SSR build\n      if (\n        config.command === 'build' &&\n        !this.environment.config.build.emitAssets\n      ) {\n        for (const file in bundle) {\n          if (\n            bundle[file].type === 'asset' &&\n            !file.endsWith('ssr-manifest.json') &&\n            !jsSourceMapRE.test(file)\n          ) {\n            delete bundle[file]\n          }\n        }\n      }\n    },\n\n    watchChange(id) {\n      assetCache.get(this.environment)?.delete(normalizePath(id))\n    },\n  }\n}\n\nexport async function fileToUrl(\n  pluginContext: PluginContext,\n  id: string,\n  asFileUrl = false,\n): Promise<string> {\n  const { environment } = pluginContext\n  if (!environment.config.isBundled) {\n    return fileToDevUrl(environment, id, asFileUrl)\n  } else {\n    return fileToBuiltUrl(pluginContext, id)\n  }\n}\n\nexport async function fileToDevUrl(\n  environment: Environment,\n  id: string,\n  asFileUrl = false,\n): Promise<string> {\n  const config = environment.getTopLevelConfig()\n  const publicFile = checkPublicFile(id, config)\n\n  // If has inline query, unconditionally inline the asset\n  if (inlineRE.test(id)) {\n    const file = publicFile || cleanUrl(id)\n    const content = await fsp.readFile(file)\n    return assetToDataURL(environment, file, content)\n  }\n\n  // If is svg and it's inlined in build, also inline it in dev to match\n  // the behaviour in build due to quote handling differences.\n  const cleanedId = cleanUrl(id)\n  if (cleanedId.endsWith('.svg')) {\n    const file = publicFile || cleanedId\n    const content = await fsp.readFile(file)\n    if (shouldInline(environment, file, id, content, undefined, undefined)) {\n      return assetToDataURL(environment, file, content)\n    }\n  }\n\n  if (asFileUrl) {\n    return pathToFileURL(cleanedId).href\n  }\n\n  let rtn: string\n  if (publicFile) {\n    // in public dir during dev, keep the url as-is\n    rtn = id\n  } else if (id.startsWith(withTrailingSlash(config.root))) {\n    // in project root, infer short public path\n    rtn = '/' + path.posix.relative(config.root, id)\n  } else {\n    // outside of project root, use absolute fs path\n    // (this is special handled by the serve static middleware\n    rtn = path.posix.join(FS_PREFIX, id)\n  }\n  const base = joinUrlSegments(config.server.origin ?? '', config.decodedBase)\n  return joinUrlSegments(base, removeLeadingSlash(rtn))\n}\n\nexport function getPublicAssetFilename(\n  hash: string,\n  config: ResolvedConfig,\n): string | undefined {\n  return publicAssetUrlCache.get(config)?.get(hash)\n}\n\n// inner map: hash -> url\nexport const publicAssetUrlCache: WeakMap<\n  ResolvedConfig,\n  Map<string, string>\n> = new WeakMap()\n\nexport const publicAssetUrlRE: RegExp = /__VITE_PUBLIC_ASSET__([a-z\\d]{8})__/g\n\nexport function publicFileToBuiltUrl(\n  url: string,\n  config: ResolvedConfig,\n): string {\n  if (config.command !== 'build') {\n    // We don't need relative base or renderBuiltUrl support during dev\n    return joinUrlSegments(config.decodedBase, url)\n  }\n  const hash = getHash(url)\n  let cache = publicAssetUrlCache.get(config)\n  if (!cache) {\n    cache = new Map<string, string>()\n    publicAssetUrlCache.set(config, cache)\n  }\n  if (!cache.get(hash)) {\n    cache.set(hash, url)\n  }\n  return `__VITE_PUBLIC_ASSET__${hash}__`\n}\n\nconst GIT_LFS_PREFIX = Buffer.from('version https://git-lfs.github.com')\nfunction isGitLfsPlaceholder(content: Buffer): boolean {\n  if (content.length < GIT_LFS_PREFIX.length) return false\n  // Check whether the content begins with the characteristic string of Git LFS placeholders\n  return GIT_LFS_PREFIX.compare(content, 0, GIT_LFS_PREFIX.length) === 0\n}\n\n/**\n * Register an asset to be emitted as part of the bundle (if necessary)\n * and returns the resolved public URL\n */\nasync function fileToBuiltUrl(\n  pluginContext: PluginContext,\n  id: string,\n  skipPublicCheck = false,\n  forceInline?: boolean,\n): Promise<string> {\n  const environment = pluginContext.environment\n  const topLevelConfig = environment.getTopLevelConfig()\n  if (!skipPublicCheck) {\n    const publicFile = checkPublicFile(id, topLevelConfig)\n    if (publicFile) {\n      if (inlineRE.test(id)) {\n        // If inline via query, re-assign the id so it can be read by the fs and inlined\n        id = publicFile\n      } else {\n        return publicFileToBuiltUrl(id, topLevelConfig)\n      }\n    }\n  }\n\n  const cache = assetCache.get(environment)!\n  const cached = cache.get(id)\n  if (cached) {\n    return cached\n  }\n\n  let { file, postfix } = splitFileAndPostfix(id)\n  const content = await fsp.readFile(file)\n\n  let url: string\n  if (\n    shouldInline(environment, file, id, content, pluginContext, forceInline)\n  ) {\n    url = assetToDataURL(environment, file, content)\n  } else {\n    // emit as asset\n    const originalFileName = normalizePath(\n      path.relative(environment.config.root, file),\n    )\n    const referenceId = pluginContext.emitFile({\n      type: 'asset',\n      // Ignore directory structure for asset file names\n      name: path.basename(file),\n      originalFileName,\n      source: content,\n    })\n\n    if (environment.config.command === 'build' && noInlineRE.test(postfix)) {\n      postfix = postfix.replace(noInlineRE, '').replace(/^&/, '?')\n    }\n\n    if (\n      environment.config.command === 'serve' &&\n      environment.config.experimental.bundledDev\n    ) {\n      const outputFilename = pluginContext.getFileName(referenceId)\n      url = toOutputFilePathInJSForBundledDev(environment, outputFilename)\n    } else {\n      url = `__VITE_ASSET__${referenceId}__${postfix ? `$_${postfix}__` : ``}`\n    }\n  }\n\n  cache.set(id, url)\n  return url\n}\n\nexport function toOutputFilePathInJSForBundledDev(\n  environment: PartialEnvironment,\n  filename: string,\n): string {\n  const outputUrl = toOutputFilePathInJS(\n    environment,\n    filename,\n    'asset',\n    // in bundled dev, the chunks are always emitted to `assets` directory\n    'assets/dummy.js',\n    'js',\n    // relative base is not supported in bundled dev\n    () => {\n      throw new Error('unreachable')\n    },\n  )\n  // renderBuiltUrl is not supported in bundled dev\n  if (typeof outputUrl === 'object') throw new Error('unreachable')\n  return outputUrl\n}\n\nexport async function urlToBuiltUrl(\n  pluginContext: PluginContext,\n  url: string,\n  importer: string,\n  forceInline?: boolean,\n): Promise<string> {\n  const topLevelConfig = pluginContext.environment.getTopLevelConfig()\n  if (checkPublicFile(url, topLevelConfig)) {\n    return publicFileToBuiltUrl(url, topLevelConfig)\n  }\n  const file = normalizePath(\n    url[0] === '/'\n      ? path.join(topLevelConfig.root, url)\n      : path.join(path.dirname(importer), url),\n  )\n  return fileToBuiltUrl(\n    pluginContext,\n    file,\n    // skip public check since we just did it above\n    true,\n    forceInline,\n  )\n}\n\nfunction shouldInline(\n  environment: Environment,\n  file: string,\n  id: string,\n  content: Buffer,\n  /** Should be passed only in build */\n  buildPluginContext: PluginContext | undefined,\n  forceInline: boolean | undefined,\n): boolean {\n  if (noInlineRE.test(id)) return false\n  if (inlineRE.test(id)) return true\n  // Do build only checks if passed the plugin context during build\n  if (buildPluginContext) {\n    if (environment.config.build.lib) return true\n    if (buildPluginContext.getModuleInfo(id)?.isEntry) return false\n  }\n  if (forceInline !== undefined) return forceInline\n  if (file.endsWith('.html')) return false\n  // Don't inline SVG with fragments, as they are meant to be reused\n  if (file.endsWith('.svg') && id.includes('#')) return false\n  let limit: number\n  const { assetsInlineLimit } = environment.config.build\n  if (typeof assetsInlineLimit === 'function') {\n    const userShouldInline = assetsInlineLimit(file, content)\n    if (userShouldInline != null) return userShouldInline\n    limit = DEFAULT_ASSETS_INLINE_LIMIT\n  } else {\n    limit = Number(assetsInlineLimit)\n  }\n  return content.length < limit && !isGitLfsPlaceholder(content)\n}\n\nfunction assetToDataURL(\n  environment: Environment,\n  file: string,\n  content: Buffer,\n) {\n  if (environment.config.build.lib && isGitLfsPlaceholder(content)) {\n    environment.logger.warn(\n      colors.yellow(`Inlined file ${file} was not downloaded via Git LFS`),\n    )\n  }\n\n  if (file.endsWith('.svg')) {\n    return svgToDataURL(content)\n  } else {\n    const mimeType = mrmime.lookup(file) ?? 'application/octet-stream'\n    // base64 inlined as a string\n    return `data:${mimeType};base64,${content.toString('base64')}`\n  }\n}\n\nconst nestedQuotesRE = /\"[^\"']*'[^\"]*\"|'[^'\"]*\"[^']*'/\n\n// Inspired by https://github.com/iconify/iconify/blob/main/packages/utils/src/svg/url.ts\nfunction svgToDataURL(content: Buffer): string {\n  const stringContent = content.toString()\n  // If the SVG contains some text or HTML, any transformation is unsafe, and given that double quotes would then\n  // need to be escaped, the gain to use a data URI would be ridiculous if not negative\n  if (\n    stringContent.includes('<text') ||\n    stringContent.includes('<foreignObject') ||\n    nestedQuotesRE.test(stringContent)\n  ) {\n    return `data:image/svg+xml;base64,${content.toString('base64')}`\n  } else {\n    return (\n      'data:image/svg+xml,' +\n      stringContent\n        .trim()\n        .replaceAll(/>\\s+</g, '><')\n        .replaceAll('\"', \"'\")\n        .replaceAll('%', '%25')\n        .replaceAll('#', '%23')\n        .replaceAll('<', '%3c')\n        .replaceAll('>', '%3e')\n        // Spaces are not valid in srcset it has some use cases\n        // it can make the uncompressed URI slightly higher than base64, but will compress way better\n        // https://github.com/vitejs/vite/pull/14643#issuecomment-1766288673\n        .replaceAll(/\\s+/g, '%20')\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/assetImportMetaUrl.ts",
    "content": "import path from 'node:path'\nimport MagicString from 'magic-string'\nimport { stripLiteral } from 'strip-literal'\nimport { exactRegex } from 'rolldown/filter'\nimport type { Plugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport {\n  injectQuery,\n  isDataUrl,\n  isParentDirectory,\n  transformStableResult,\n  tryStatSync,\n} from '../utils'\nimport { CLIENT_ENTRY } from '../constants'\nimport { slash } from '../../shared/utils'\nimport { createBackCompatIdResolver } from '../idResolver'\nimport type { ResolveIdFn } from '../idResolver'\nimport { fileToUrl } from './asset'\nimport { preloadHelperId } from './importAnalysisBuild'\nimport type { InternalResolveOptions } from './resolve'\nimport { tryFsResolve } from './resolve'\nimport { hasViteIgnoreRE } from './importAnalysis'\n\n/**\n * Convert `new URL('./foo.png', import.meta.url)` to its resolved built URL\n *\n * Supports template string with dynamic segments:\n * ```\n * new URL(`./dir/${name}.png`, import.meta.url)\n * // transformed to\n * import.meta.glob('./dir/**.png', { eager: true, import: 'default' })[`./dir/${name}.png`]\n * ```\n */\nexport const assetImportMetaUrlRE: RegExp =\n  /\\bnew\\s+URL\\s*\\(\\s*('[^']+'|\"[^\"]+\"|`[^`]+`)\\s*,\\s*import\\.meta\\.url\\s*(?:,\\s*)?\\)/dg\n\nexport function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {\n  const { publicDir } = config\n  let assetResolver: ResolveIdFn\n\n  const fsResolveOptions: InternalResolveOptions = {\n    ...config.resolve,\n    root: config.root,\n    isProduction: config.isProduction,\n    isBuild: config.command === 'build',\n    packageCache: config.packageCache,\n    asSrc: true,\n  }\n\n  return {\n    name: 'vite:asset-import-meta-url',\n\n    applyToEnvironment(environment) {\n      return environment.config.consumer === 'client'\n    },\n\n    transform: {\n      filter: {\n        id: {\n          exclude: [exactRegex(preloadHelperId), exactRegex(CLIENT_ENTRY)],\n        },\n        code: assetImportMetaUrlRE,\n      },\n      async handler(code, id) {\n        let s: MagicString | undefined\n        const re = new RegExp(assetImportMetaUrlRE)\n        const cleanString = stripLiteral(code)\n\n        let match: RegExpExecArray | null\n        while ((match = re.exec(cleanString))) {\n          const [[startIndex, endIndex], [urlStart, urlEnd]] = match.indices!\n          if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue\n\n          const rawUrl = code.slice(urlStart, urlEnd)\n\n          if (!s) s = new MagicString(code)\n\n          // potential dynamic template string\n          if (rawUrl[0] === '`' && rawUrl.includes('${')) {\n            const queryDelimiterIndex = getQueryDelimiterIndex(rawUrl)\n            const hasQueryDelimiter = queryDelimiterIndex !== -1\n            const pureUrl = hasQueryDelimiter\n              ? rawUrl.slice(0, queryDelimiterIndex) + '`'\n              : rawUrl\n            const queryString = hasQueryDelimiter\n              ? rawUrl.slice(queryDelimiterIndex, -1)\n              : ''\n            const ast = this.parse(pureUrl)\n            const templateLiteral = (ast as any).body[0].expression\n            if (templateLiteral.expressions.length) {\n              const pattern = buildGlobPattern(templateLiteral)\n              if (pattern[0] === '*') {\n                // don't transform for patterns like this\n                // because users won't intend to do that in most cases\n                continue\n              }\n\n              const globOptions = {\n                eager: true,\n                import: 'default',\n                // A hack to allow 'as' & 'query' exist at the same time\n                query: injectQuery(queryString, 'url'),\n              }\n              s.update(\n                startIndex,\n                endIndex,\n                `new URL((import.meta.glob(${JSON.stringify(\n                  pattern,\n                )}, ${JSON.stringify(\n                  globOptions,\n                )}))[${pureUrl}], import.meta.url)`,\n              )\n              continue\n            }\n          }\n\n          const url = rawUrl.slice(1, -1)\n          if (isDataUrl(url)) {\n            continue\n          }\n          let file: string | undefined\n          if (url[0] === '.') {\n            file = slash(path.resolve(path.dirname(id), url))\n            file = tryFsResolve(file, fsResolveOptions) ?? file\n          } else {\n            assetResolver ??= createBackCompatIdResolver(config, {\n              extensions: [],\n              mainFields: [],\n              tryIndex: false,\n              preferRelative: true,\n            })\n            file = await assetResolver(this.environment, url, id)\n            file ??=\n              url[0] === '/'\n                ? slash(path.join(publicDir, url))\n                : slash(path.resolve(path.dirname(id), url))\n          }\n\n          // Get final asset URL. If the file does not exist,\n          // we fall back to the initial URL and let it resolve in runtime\n          let builtUrl: string | undefined\n          if (file) {\n            try {\n              if (publicDir && isParentDirectory(publicDir, file)) {\n                const publicPath = '/' + path.posix.relative(publicDir, file)\n                builtUrl = await fileToUrl(this, publicPath)\n              } else {\n                builtUrl = await fileToUrl(this, file)\n                // during dev, builtUrl may point to a directory or a non-existing file\n                if (tryStatSync(file)?.isFile()) {\n                  this.addWatchFile(file)\n                }\n              }\n            } catch {\n              // do nothing, we'll log a warning after this\n            }\n          }\n          if (!builtUrl) {\n            const rawExp = code.slice(startIndex, endIndex)\n            config.logger.warnOnce(\n              `\\n${rawExp} doesn't exist at build time, it will remain unchanged to be resolved at runtime. ` +\n                `If this is intended, you can use the /* @vite-ignore */ comment to suppress this warning.`,\n            )\n            builtUrl = url\n          }\n          s.update(\n            startIndex,\n            endIndex,\n            // NOTE: add `'' +` to opt-out rolldown's transform: https://github.com/rolldown/rolldown/issues/2745\n            `new URL(${JSON.stringify(builtUrl)}, '' + import.meta.url)`,\n          )\n        }\n        if (s) {\n          return transformStableResult(s, id, config)\n        }\n      },\n    },\n  }\n}\n\nfunction buildGlobPattern(ast: any) {\n  let pattern = ''\n  let lastIsGlob = false\n  for (let i = 0; i < ast.quasis.length; i++) {\n    const str = ast.quasis[i].value.raw\n    if (str) {\n      pattern += str\n      lastIsGlob = false\n    }\n\n    if (ast.expressions[i] && !lastIsGlob) {\n      pattern += '*'\n      lastIsGlob = true\n    }\n  }\n  return pattern\n}\n\nfunction getQueryDelimiterIndex(rawUrl: string): number {\n  let bracketsStack = 0\n  for (let i = 0; i < rawUrl.length; i++) {\n    if (rawUrl[i] === '{') {\n      bracketsStack++\n    } else if (rawUrl[i] === '}') {\n      bracketsStack--\n    } else if (rawUrl[i] === '?' && bracketsStack === 0) {\n      return i\n    }\n  }\n  return -1\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/clientInjections.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport type { Plugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport { CLIENT_ENTRY, ENV_ENTRY } from '../constants'\nimport { isObject, normalizePath, resolveHostname } from '../utils'\nimport { cleanUrl } from '../../shared/utils'\nimport { perEnvironmentState } from '../environment'\nimport { replaceDefine, serializeDefine } from './define'\n\n// ids in transform are normalized to unix style\nconst normalizedClientEntry = normalizePath(CLIENT_ENTRY)\nconst normalizedEnvEntry = normalizePath(ENV_ENTRY)\n\n/**\n * some values used by the client needs to be dynamically injected by the server\n * @server-only\n */\nexport function clientInjectionsPlugin(config: ResolvedConfig): Plugin {\n  let injectConfigValues: (code: string) => string\n\n  const getDefineReplacer = perEnvironmentState((environment) => {\n    const userDefine: Record<string, any> = {}\n    for (const key in environment.config.define) {\n      // import.meta.env.* is handled in `importAnalysis` plugin\n      if (!key.startsWith('import.meta.env.')) {\n        userDefine[key] = environment.config.define[key]\n      }\n    }\n    const serializedDefines = serializeDefine(userDefine)\n    const definesReplacement = () => serializedDefines\n    return (code: string) => code.replace(`__DEFINES__`, definesReplacement)\n  })\n\n  return {\n    name: 'vite:client-inject',\n    async buildStart() {\n      injectConfigValues = await createClientConfigValueReplacer(config)\n    },\n    async transform(code, id) {\n      const ssr = this.environment.config.consumer === 'server'\n      const cleanId = cleanUrl(id)\n      if (cleanId === normalizedClientEntry || cleanId === normalizedEnvEntry) {\n        const defineReplacer = getDefineReplacer(this)\n        return defineReplacer(injectConfigValues(code))\n      } else if (!ssr && code.includes('process.env.NODE_ENV')) {\n        // replace process.env.NODE_ENV instead of defining a global\n        // for it to avoid shimming a `process` object during dev,\n        // avoiding inconsistencies between dev and build\n        const nodeEnv =\n          this.environment.config.define?.['process.env.NODE_ENV'] ||\n          JSON.stringify(process.env.NODE_ENV || config.mode)\n        return await replaceDefine(this.environment, code, id, {\n          'process.env.NODE_ENV': nodeEnv,\n          'global.process.env.NODE_ENV': nodeEnv,\n          'globalThis.process.env.NODE_ENV': nodeEnv,\n        })\n      }\n    },\n  }\n}\n\nfunction escapeReplacement(value: string | number | boolean | null) {\n  const jsonValue = JSON.stringify(value)\n  return () => jsonValue\n}\n\nasync function createClientConfigValueReplacer(\n  config: ResolvedConfig,\n): Promise<(code: string) => string> {\n  const resolvedServerHostname = (await resolveHostname(config.server.host))\n    .name\n  const resolvedServerPort = config.server.port!\n  const devBase = config.base\n\n  const serverHost = `${resolvedServerHostname}:${resolvedServerPort}${devBase}`\n\n  let hmrConfig = config.server.hmr\n  hmrConfig = isObject(hmrConfig) ? hmrConfig : undefined\n  const host = hmrConfig?.host || null\n  const protocol = hmrConfig?.protocol || null\n  const timeout = hmrConfig?.timeout || 30000\n  const overlay = hmrConfig?.overlay !== false\n  const isHmrServerSpecified = !!hmrConfig?.server\n  const hmrConfigName = path.basename(config.configFile || 'vite.config.js')\n\n  // hmr.clientPort -> hmr.port\n  // -> (24678 if middleware mode and HMR server is not specified) -> new URL(import.meta.url).port\n  let port = hmrConfig?.clientPort || hmrConfig?.port || null\n  if (config.server.middlewareMode && !isHmrServerSpecified) {\n    port ||= 24678\n  }\n\n  let directTarget = hmrConfig?.host || resolvedServerHostname\n  directTarget += `:${hmrConfig?.port || resolvedServerPort}`\n  directTarget += devBase\n\n  let hmrBase = devBase\n  if (hmrConfig?.path) {\n    hmrBase = path.posix.join(hmrBase, hmrConfig.path)\n  }\n\n  const modeReplacement = escapeReplacement(config.mode)\n  const baseReplacement = escapeReplacement(devBase)\n  const serverHostReplacement = escapeReplacement(serverHost)\n  const hmrProtocolReplacement = escapeReplacement(protocol)\n  const hmrHostnameReplacement = escapeReplacement(host)\n  const hmrPortReplacement = escapeReplacement(port)\n  const hmrDirectTargetReplacement = escapeReplacement(directTarget)\n  const hmrBaseReplacement = escapeReplacement(hmrBase)\n  const hmrTimeoutReplacement = escapeReplacement(timeout)\n  const hmrEnableOverlayReplacement = escapeReplacement(overlay)\n  const hmrConfigNameReplacement = escapeReplacement(hmrConfigName)\n  const wsTokenReplacement = escapeReplacement(config.webSocketToken)\n  const serverForwardConsoleReplacement = escapeReplacement(\n    config.server.forwardConsole as any,\n  )\n  const bundleDevReplacement = escapeReplacement(\n    config.experimental.bundledDev || false,\n  )\n\n  return (code) =>\n    code\n      .replace(`__MODE__`, modeReplacement)\n      .replace(/__BASE__/g, baseReplacement)\n      .replace(`__SERVER_HOST__`, serverHostReplacement)\n      .replace(`__HMR_PROTOCOL__`, hmrProtocolReplacement)\n      .replace(`__HMR_HOSTNAME__`, hmrHostnameReplacement)\n      .replace(`__HMR_PORT__`, hmrPortReplacement)\n      .replace(`__HMR_DIRECT_TARGET__`, hmrDirectTargetReplacement)\n      .replace(`__HMR_BASE__`, hmrBaseReplacement)\n      .replace(`__HMR_TIMEOUT__`, hmrTimeoutReplacement)\n      .replace(`__HMR_ENABLE_OVERLAY__`, hmrEnableOverlayReplacement)\n      .replace(`__HMR_CONFIG_NAME__`, hmrConfigNameReplacement)\n      .replace(`__WS_TOKEN__`, wsTokenReplacement)\n      .replace(`__SERVER_FORWARD_CONSOLE__`, serverForwardConsoleReplacement)\n      .replaceAll(`__BUNDLED_DEV__`, bundleDevReplacement)\n}\n\nexport async function getHmrImplementation(\n  config: ResolvedConfig,\n): Promise<string> {\n  const content = fs.readFileSync(normalizedClientEntry, 'utf-8')\n  const replacer = await createClientConfigValueReplacer(config)\n  return (\n    replacer(content)\n      // the rolldown runtime cannot import a module\n      .replace(/import\\s*['\"]@vite\\/env['\"]/, '')\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/css.ts",
    "content": "import fs from 'node:fs'\nimport fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport postcssrc from 'postcss-load-config'\nimport type {\n  ExistingRawSourceMap,\n  InternalModuleFormat,\n  MinimalPluginContext,\n  OutputAsset,\n  OutputChunk,\n  RenderedChunk,\n  RenderedModule,\n  RollupError,\n  SourceMapInput,\n} from 'rolldown'\nimport { dataToEsm } from '@rollup/pluginutils'\nimport colors from 'picocolors'\nimport MagicString from 'magic-string'\nimport type * as PostCSS from 'postcss'\nimport type Sass from 'sass'\nimport type Stylus from 'stylus'\nimport type Less from 'less'\nimport type { RawSourceMap } from '@jridgewell/remapping'\nimport { WorkerWithFallback } from 'artichokie'\nimport { globSync } from 'tinyglobby'\nimport type {\n  TransformAttributeResult as LightningCssTransformAttributeResult,\n  TransformResult as LightningCssTransformResult,\n} from 'lightningcss'\nimport type { LightningCSSOptions } from '#types/internal/lightningcssOptions'\nimport type {\n  LessPreprocessorBaseOptions,\n  SassModernPreprocessBaseOptions,\n  StylusPreprocessorBaseOptions,\n} from '#types/internal/cssPreprocessorOptions'\nimport type { EsbuildTransformOptions } from '#types/internal/esbuildOptions'\nimport type { CustomPluginOptionsVite } from '#types/metadata'\nimport { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap'\nimport type { EnvironmentModuleNode } from '../server/moduleGraph'\nimport {\n  createToImportMetaURLBasedRelativeRuntime,\n  resolveUserExternal,\n  toOutputFilePathInCss,\n  toOutputFilePathInJS,\n} from '../build'\nimport type { LibraryOptions } from '../build'\nimport {\n  CLIENT_PUBLIC_PATH,\n  CSS_LANGS_RE,\n  DEV_PROD_CONDITION,\n  ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET,\n  SPECIAL_QUERY_RE,\n} from '../constants'\nimport type { ResolvedConfig } from '../config'\nimport type { Plugin } from '../plugin'\nimport { checkPublicFile } from '../publicDir'\nimport {\n  _dirname,\n  arraify,\n  asyncReplace,\n  combineSourcemaps,\n  createSerialPromiseQueue,\n  emptyCssComments,\n  encodeURIPath,\n  escapeRegex,\n  generateCodeFrame,\n  getHash,\n  getPackageManagerCommand,\n  getPkgName,\n  injectQuery,\n  isCSSRequest,\n  isDataUrl,\n  isExternalUrl,\n  isObject,\n  joinUrlSegments,\n  mergeWithDefaults,\n  normalizePath,\n  processSrcSet,\n  removeDirectQuery,\n  removeUrlQuery,\n  stripBomTag,\n  urlRE,\n} from '../utils'\nimport type { Logger } from '../logger'\nimport { cleanUrl, isWindows, slash } from '../../shared/utils'\nimport { NULL_BYTE_PLACEHOLDER } from '../../shared/constants'\nimport { createBackCompatIdResolver } from '../idResolver'\nimport type { ResolveIdFn } from '../idResolver'\nimport { PartialEnvironment } from '../baseEnvironment'\nimport type { TransformPluginContext } from '../server/pluginContainer'\nimport { searchForWorkspaceRoot } from '../server/searchRoot'\nimport { type DevEnvironment } from '..'\nimport type { PackageCache } from '../packages'\nimport { findNearestMainPackageData } from '../packages'\nimport { nodeResolveWithVite } from '../nodeResolve'\nimport { addToHTMLProxyTransformResult } from './html'\nimport {\n  assetUrlRE,\n  cssEntriesMap,\n  fileToUrl,\n  publicAssetUrlCache,\n  publicAssetUrlRE,\n  publicFileToBuiltUrl,\n  renderAssetUrlInJS,\n} from './asset'\nimport type { ESBuildOptions } from './esbuild'\nimport { getChunkOriginalFileName } from './manifest'\nimport { IIFE_BEGIN_RE, UMD_BEGIN_RE } from './oxc'\n\nconst decoder = new TextDecoder()\n// const debug = createDebugger('vite:css')\n\nexport interface CSSOptions {\n  /**\n   * Using lightningcss is an experimental option to handle CSS modules,\n   * assets and imports via Lightning CSS. It requires to install it as a\n   * peer dependency.\n   *\n   * @default 'postcss'\n   * @experimental\n   */\n  transformer?: 'postcss' | 'lightningcss'\n  /**\n   * https://github.com/css-modules/postcss-modules\n   */\n  modules?: CSSModulesOptions | false\n  /**\n   * Options for preprocessors.\n   *\n   * In addition to options specific to each processors, Vite supports `additionalData` option.\n   * The `additionalData` option can be used to inject extra code for each style content.\n   */\n  preprocessorOptions?: {\n    scss?: SassPreprocessorOptions\n    sass?: SassPreprocessorOptions\n    less?: LessPreprocessorOptions\n    styl?: StylusPreprocessorOptions\n    stylus?: StylusPreprocessorOptions\n  }\n\n  /**\n   * If this option is set, preprocessors will run in workers when possible.\n   * `true` means the number of CPUs minus 1.\n   *\n   * @default true\n   */\n  preprocessorMaxWorkers?: number | true\n  postcss?:\n    | string\n    | (PostCSS.ProcessOptions & {\n        plugins?: PostCSS.AcceptedPlugin[]\n      })\n  /**\n   * Enables css sourcemaps during dev\n   * @default false\n   * @experimental\n   */\n  devSourcemap?: boolean\n\n  /**\n   * @experimental\n   */\n  lightningcss?: LightningCSSOptions\n}\n\nexport interface CSSModulesOptions {\n  getJSON?: (\n    cssFileName: string,\n    json: Record<string, string>,\n    outputFileName: string,\n  ) => void\n  scopeBehaviour?: 'global' | 'local'\n  globalModulePaths?: RegExp[]\n  exportGlobals?: boolean\n  generateScopedName?:\n    | string\n    | ((name: string, filename: string, css: string) => string)\n  hashPrefix?: string\n  /**\n   * default: undefined\n   */\n  localsConvention?:\n    | 'camelCase'\n    | 'camelCaseOnly'\n    | 'dashes'\n    | 'dashesOnly'\n    | ((\n        originalClassName: string,\n        generatedClassName: string,\n        inputFile: string,\n      ) => string)\n}\n\nconst _cssConfigDefaults = Object.freeze({\n  /** @experimental */\n  transformer: 'postcss',\n  // modules\n  // preprocessorOptions\n  preprocessorMaxWorkers: true,\n  // postcss\n  /** @experimental */\n  devSourcemap: false,\n  // lightningcss\n} satisfies CSSOptions)\nexport const cssConfigDefaults: Readonly<Partial<CSSOptions>> =\n  _cssConfigDefaults\n\nexport type ResolvedCSSOptions = Omit<CSSOptions, 'lightningcss'> &\n  Required<Pick<CSSOptions, 'transformer' | 'devSourcemap'>> & {\n    lightningcss?: LightningCSSOptions\n  }\n\nexport function resolveCSSOptions(\n  options: CSSOptions | undefined,\n): ResolvedCSSOptions {\n  const resolved = mergeWithDefaults(_cssConfigDefaults, options ?? {})\n  if (resolved.transformer === 'lightningcss') {\n    resolved.lightningcss ??= {}\n    resolved.lightningcss.targets ??= convertTargets(\n      ESBUILD_BASELINE_WIDELY_AVAILABLE_TARGET,\n    )\n  }\n  return resolved\n}\n\nconst cssModuleRE = new RegExp(`\\\\.module${CSS_LANGS_RE.source}`)\nconst directRequestRE = /[?&]direct\\b/\nconst htmlProxyRE = /[?&]html-proxy\\b/\nconst htmlProxyIndexRE = /&index=(\\d+)/\nconst commonjsProxyRE = /[?&]commonjs-proxy/\nconst inlineRE = /[?&]inline\\b/\nconst inlineCSSRE = /[?&]inline-css\\b/\nconst styleAttrRE = /[?&]style-attr\\b/\nconst functionCallRE = /^[A-Z_][.\\w-]*\\(/i\nconst transformOnlyRE = /[?&]transform-only\\b/\nconst nonEscapedDoubleQuoteRe = /(?<!\\\\)\"/g\n\nconst defaultCssBundleName = 'style.css'\n\nconst enum PreprocessLang {\n  less = 'less',\n  sass = 'sass',\n  scss = 'scss',\n  styl = 'styl',\n  stylus = 'stylus',\n}\n// eslint-disable-next-line @typescript-eslint/no-unused-vars -- bug in typescript-eslint\nconst enum PureCssLang {\n  css = 'css',\n}\nconst enum PostCssDialectLang {\n  sss = 'sugarss',\n}\ntype CssLang =\n  | keyof typeof PureCssLang\n  | keyof typeof PreprocessLang\n  | keyof typeof PostCssDialectLang\n\nexport const isModuleCSSRequest = (request: string): boolean =>\n  cssModuleRE.test(request)\n\nexport const isDirectCSSRequest = (request: string): boolean =>\n  CSS_LANGS_RE.test(request) && directRequestRE.test(request)\n\nexport const isDirectRequest = (request: string): boolean =>\n  directRequestRE.test(request)\n\nconst cssModulesCache = new WeakMap<\n  ResolvedConfig,\n  Map<string, Record<string, string>>\n>()\n\nexport const removedPureCssFilesCache: WeakMap<\n  ResolvedConfig,\n  Map<string, RenderedChunk>\n> = new WeakMap()\n\n// Used only if the config doesn't code-split CSS (builds a single CSS file)\nexport const cssBundleNameCache: WeakMap<ResolvedConfig, string> = new WeakMap()\n\nconst postcssConfigCache = new WeakMap<\n  ResolvedConfig,\n  PostCSSConfigResult | null | Promise<PostCSSConfigResult | null>\n>()\n\nfunction encodePublicUrlsInCSS(config: ResolvedConfig) {\n  return config.command === 'build'\n}\n\nconst cssUrlAssetRE = /__VITE_CSS_URL__([\\da-f]+)__/g\n\n/**\n * Plugin applied before user plugins\n */\nexport function cssPlugin(config: ResolvedConfig): Plugin {\n  const isBuild = config.command === 'build'\n  let moduleCache: Map<string, Record<string, string>>\n\n  const idResolver = createBackCompatIdResolver(config, {\n    preferRelative: true,\n    tryIndex: false,\n    extensions: [],\n  })\n\n  let preprocessorWorkerController: PreprocessorWorkerController | undefined\n\n  // warm up cache for resolved postcss config\n  if (config.css.transformer !== 'lightningcss') {\n    resolvePostcssConfig(config).catch(() => {\n      /* will be handled later */\n    })\n  }\n\n  return {\n    name: 'vite:css',\n\n    buildStart() {\n      // Ensure a new cache for every build (i.e. rebuilding in watch mode)\n      moduleCache = new Map<string, Record<string, string>>()\n      cssModulesCache.set(config, moduleCache)\n\n      removedPureCssFilesCache.set(config, new Map<string, RenderedChunk>())\n\n      preprocessorWorkerController = createPreprocessorWorkerController(\n        normalizeMaxWorkers(config.css.preprocessorMaxWorkers),\n      )\n      preprocessorWorkerControllerCache.set(\n        config,\n        preprocessorWorkerController,\n      )\n    },\n\n    buildEnd() {\n      preprocessorWorkerController?.close()\n    },\n\n    load: {\n      filter: {\n        id: CSS_LANGS_RE,\n      },\n      async handler(id) {\n        if (urlRE.test(id)) {\n          if (isModuleCSSRequest(id)) {\n            throw new Error(\n              `?url is not supported with CSS modules. (tried to import ${JSON.stringify(\n                id,\n              )})`,\n            )\n          }\n\n          // *.css?url\n          // in dev, it's handled by assets plugin.\n          if (isBuild) {\n            id = injectQuery(removeUrlQuery(id), 'transform-only')\n            return (\n              `import ${JSON.stringify(id)};` +\n              `export default \"__VITE_CSS_URL__${Buffer.from(id).toString(\n                'hex',\n              )}__\"`\n            )\n          }\n        }\n      },\n    },\n    transform: {\n      filter: {\n        id: {\n          include: CSS_LANGS_RE,\n          exclude: [commonjsProxyRE, SPECIAL_QUERY_RE],\n        },\n      },\n      async handler(raw, id) {\n        const { environment } = this\n        const resolveUrl = (url: string, importer?: string) =>\n          idResolver(environment, url, importer)\n\n        const urlResolver: CssUrlResolver = async (url, importer) => {\n          const decodedUrl = decodeURI(url)\n          if (checkPublicFile(decodedUrl, config)) {\n            if (encodePublicUrlsInCSS(config)) {\n              return [publicFileToBuiltUrl(decodedUrl, config), undefined]\n            } else {\n              const base = joinUrlSegments(\n                config.server.origin ?? '',\n                config.base,\n              )\n              return [joinUrlSegments(base, decodedUrl), undefined]\n            }\n          }\n          const [id, fragment] = decodedUrl.split('#')\n          let resolved = await resolveUrl(id, importer)\n          if (resolved) {\n            if (fragment) resolved += '#' + fragment\n            let url = await fileToUrl(this, resolved)\n            // Inherit HMR timestamp if this asset was invalidated\n            if (!url.startsWith('data:') && this.environment.mode === 'dev') {\n              const mod = [\n                ...(this.environment.moduleGraph.getModulesByFile(resolved) ??\n                  []),\n              ].find((mod) => mod.type === 'asset')\n              if (mod?.lastHMRTimestamp) {\n                url = injectQuery(url, `t=${mod.lastHMRTimestamp}`)\n              }\n            }\n            return [url, cleanUrl(resolved)]\n          }\n          if (config.command === 'build') {\n            const isExternal = config.build.rollupOptions.external\n              ? resolveUserExternal(\n                  config.build.rollupOptions.external,\n                  decodedUrl, // use URL as id since id could not be resolved\n                  id,\n                  false,\n                )\n              : false\n\n            if (!isExternal) {\n              // #9800 If we cannot resolve the css url, leave a warning.\n              config.logger.warnOnce(\n                `\\n${decodedUrl} referenced in ${id} didn't resolve at build time, it will remain unchanged to be resolved at runtime`,\n              )\n            }\n          }\n          return [url, undefined]\n        }\n\n        const {\n          code: css,\n          modules,\n          deps,\n          map,\n        } = await compileCSS(\n          environment,\n          id,\n          raw,\n          preprocessorWorkerController!,\n          urlResolver,\n        )\n        if (modules) {\n          moduleCache.set(id, modules)\n        }\n\n        if (deps) {\n          for (const file of deps) {\n            this.addWatchFile(file)\n          }\n        }\n\n        return {\n          code: css,\n          map,\n        }\n      },\n    },\n  }\n}\n\n/**\n * Plugin applied after user plugins\n */\nexport function cssPostPlugin(config: ResolvedConfig): Plugin {\n  // styles initialization in buildStart causes a styling loss in watch\n  const styles = new Map<string, string>()\n  // queue to emit css serially to guarantee the files are emitted in a deterministic order\n  let codeSplitEmitQueue = createSerialPromiseQueue<string>()\n  const urlEmitQueue = createSerialPromiseQueue<unknown>()\n  let pureCssChunks: Set<RenderedChunk>\n\n  // when there are multiple rollup outputs and extracting CSS, only emit once,\n  // since output formats have no effect on the generated CSS.\n  let hasEmitted = false\n  let chunkCSSMap: Map<string, string>\n\n  const rollupOptionsOutput = config.build.rollupOptions.output\n  const assetFileNames = (\n    Array.isArray(rollupOptionsOutput)\n      ? rollupOptionsOutput[0]\n      : rollupOptionsOutput\n  )?.assetFileNames\n  const getCssAssetDirname = (\n    cssAssetName: string,\n    originalFileName?: string,\n  ) => {\n    const cssAssetNameDir = path.dirname(cssAssetName)\n    if (!assetFileNames) {\n      return path.join(config.build.assetsDir, cssAssetNameDir)\n    } else if (typeof assetFileNames === 'string') {\n      return path.join(path.dirname(assetFileNames), cssAssetNameDir)\n    } else {\n      return path.dirname(\n        assetFileNames({\n          type: 'asset',\n          names: [cssAssetName],\n          originalFileNames: originalFileName ? [originalFileName] : [],\n          source: '/* vite internal call, ignore */',\n        }),\n      )\n    }\n  }\n\n  function getCssBundleName() {\n    const cached = cssBundleNameCache.get(config)\n    if (cached) return cached\n\n    const cssBundleName = config.build.lib\n      ? resolveLibCssFilename(\n          config.build.lib,\n          config.root,\n          config.packageCache,\n        )\n      : defaultCssBundleName\n    cssBundleNameCache.set(config, cssBundleName)\n    return cssBundleName\n  }\n\n  return {\n    name: 'vite:css-post',\n\n    renderStart() {\n      // Ensure new caches for every build (i.e. rebuilding in watch mode)\n      pureCssChunks = new Set<RenderedChunk>()\n      hasEmitted = false\n      chunkCSSMap = new Map()\n      codeSplitEmitQueue = createSerialPromiseQueue()\n    },\n\n    transform: {\n      filter: {\n        id: {\n          include: CSS_LANGS_RE,\n          exclude: [commonjsProxyRE, SPECIAL_QUERY_RE],\n        },\n      },\n      async handler(css, id) {\n        css = stripBomTag(css)\n\n        // cache css compile result to map\n        // and then use the cache replace inline-style-flag\n        // when `generateBundle` in vite:build-html plugin and devHtmlHook\n        const inlineCSS = inlineCSSRE.test(id)\n        const isHTMLProxy = htmlProxyRE.test(id)\n        if (inlineCSS && isHTMLProxy) {\n          if (styleAttrRE.test(id)) {\n            css = css.replace(/\"/g, '&quot;')\n          }\n          const index = htmlProxyIndexRE.exec(id)?.[1]\n          if (index == null) {\n            throw new Error(`HTML proxy index in \"${id}\" not found`)\n          }\n          addToHTMLProxyTransformResult(\n            `${getHash(cleanUrl(id))}_${Number.parseInt(index)}`,\n            css,\n          )\n          return `export default ''`\n        }\n\n        const inlined = inlineRE.test(id)\n        const modules = cssModulesCache.get(config)!.get(id)\n\n        // #6984, #7552\n        // `foo.module.css` => modulesCode\n        // `foo.module.css?inline` => cssContent\n        const modulesCode =\n          modules &&\n          !inlined &&\n          dataToEsm(modules, { namedExports: true, preferConst: true })\n\n        if (config.command === 'serve') {\n          const getContentWithSourcemap = async (content: string) => {\n            if (config.css.devSourcemap) {\n              const sourcemap = this.getCombinedSourcemap()\n              if (sourcemap.mappings) {\n                await injectSourcesContent(\n                  sourcemap,\n                  cleanUrl(id),\n                  config.logger,\n                )\n              }\n              return getCodeWithSourcemap('css', content, sourcemap)\n            }\n            return content\n          }\n\n          if (isDirectCSSRequest(id)) {\n            return null\n          }\n          if (inlined) {\n            return `export default ${JSON.stringify(css)}`\n          }\n          if (this.environment.config.consumer === 'server') {\n            return modulesCode || 'export {}'\n          }\n\n          const cssContent = await getContentWithSourcemap(css)\n          const code = [\n            config.isBundled\n              ? `const { updateStyle: __vite__updateStyle, removeStyle: __vite__removeStyle } = import.meta.hot._internal`\n              : `import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from ${JSON.stringify(\n                  path.posix.join(config.base, CLIENT_PUBLIC_PATH),\n                )}`,\n            `const __vite__id = ${JSON.stringify(id)}`,\n            `const __vite__css = ${JSON.stringify(cssContent)}`,\n            `__vite__updateStyle(__vite__id, __vite__css)`,\n            // css modules exports change on edit so it can't self accept\n            `${modulesCode || 'import.meta.hot.accept()'}`,\n            `import.meta.hot.prune(() => __vite__removeStyle(__vite__id))`,\n          ].join('\\n')\n          return { code, map: { mappings: '' }, moduleType: 'js' }\n        }\n\n        // build CSS handling ----------------------------------------------------\n\n        // record css\n        if (!inlined) {\n          styles.set(id, css)\n        }\n\n        let code: string\n        if (modulesCode) {\n          code = modulesCode\n        } else if (inlined) {\n          let content = css\n          if (config.build.cssMinify) {\n            content = await minifyCSS(content, config, true)\n          }\n          code = `export default ${JSON.stringify(content)}`\n        } else {\n          // empty module when it's not a CSS module nor `?inline`\n          code = ''\n        }\n\n        return {\n          code,\n          map: { mappings: '' },\n          // avoid the css module from being tree-shaken so that we can retrieve\n          // it in renderChunk()\n          moduleSideEffects: modulesCode || inlined ? false : 'no-treeshake',\n          moduleType: 'js',\n        }\n      },\n    },\n\n    ...(config.command === 'build'\n      ? {\n          async renderChunk(code, chunk, opts, meta) {\n            let chunkCSS: string | undefined\n            const renderedModules = new Proxy(\n              {} as Record<string, RenderedModule | undefined>,\n              {\n                get(_target, p) {\n                  for (const name in meta.chunks) {\n                    const modules = meta.chunks[name].modules\n                    const module = modules[p as string]\n                    if (module) {\n                      return module\n                    }\n                  }\n                },\n              },\n            )\n            // the chunk is empty if it's a dynamic entry chunk that only contains a CSS import\n            const isJsChunkEmpty = code === '' && !chunk.isEntry\n            let isPureCssChunk = chunk.exports.length === 0\n            const ids = Object.keys(chunk.modules)\n            for (const id of ids) {\n              if (styles.has(id)) {\n                // ?transform-only is used for ?url and shouldn't be included in normal CSS chunks\n                if (transformOnlyRE.test(id)) {\n                  continue\n                }\n\n                // If this CSS is scoped to its importers exports, check if those importers exports\n                // are rendered in the chunks. If they are not, we can skip bundling this CSS.\n                const cssScopeTo =\n                  this.getModuleInfo(id)?.meta?.vite?.cssScopeTo\n                if (\n                  cssScopeTo &&\n                  !isCssScopeToRendered(cssScopeTo, renderedModules)\n                ) {\n                  continue\n                }\n\n                // a css module contains JS, so it makes this not a pure css chunk\n                if (cssModuleRE.test(id)) {\n                  isPureCssChunk = false\n                }\n\n                chunkCSS = (chunkCSS || '') + styles.get(id)\n              } else if (!isJsChunkEmpty) {\n                // if the module does not have a style, then it's not a pure css chunk.\n                // this is true because in the `transform` hook above, only modules\n                // that are css gets added to the `styles` map.\n                isPureCssChunk = false\n              }\n            }\n\n            const publicAssetUrlMap = publicAssetUrlCache.get(config)!\n\n            // resolve asset URL placeholders to their built file URLs\n            const resolveAssetUrlsInCss = (\n              chunkCSS: string,\n              cssAssetName: string,\n              originalFileName?: string,\n            ) => {\n              const encodedPublicUrls = encodePublicUrlsInCSS(config)\n\n              const relative = config.base === './' || config.base === ''\n              const cssAssetDirname =\n                encodedPublicUrls || relative\n                  ? slash(getCssAssetDirname(cssAssetName, originalFileName))\n                  : undefined\n\n              const toRelative = (filename: string) => {\n                // relative base + extracted CSS\n                const relativePath = normalizePath(\n                  path.relative(cssAssetDirname!, filename),\n                )\n                return relativePath[0] === '.'\n                  ? relativePath\n                  : './' + relativePath\n              }\n\n              // replace asset url references with resolved url.\n              chunkCSS = chunkCSS.replace(\n                assetUrlRE,\n                (_, fileHash, postfix = '') => {\n                  const filename = this.getFileName(fileHash) + postfix\n                  chunk.viteMetadata!.importedAssets.add(cleanUrl(filename))\n                  return encodeURIPath(\n                    toOutputFilePathInCss(\n                      filename,\n                      'asset',\n                      cssAssetName,\n                      'css',\n                      config,\n                      toRelative,\n                    ),\n                  )\n                },\n              )\n              // resolve public URL from CSS paths\n              if (encodedPublicUrls) {\n                const relativePathToPublicFromCSS = normalizePath(\n                  path.relative(cssAssetDirname!, ''),\n                )\n                chunkCSS = chunkCSS.replace(publicAssetUrlRE, (_, hash) => {\n                  const publicUrl = publicAssetUrlMap.get(hash)!.slice(1)\n                  return encodeURIPath(\n                    toOutputFilePathInCss(\n                      publicUrl,\n                      'public',\n                      cssAssetName,\n                      'css',\n                      config,\n                      () => `${relativePathToPublicFromCSS}/${publicUrl}`,\n                    ),\n                  )\n                })\n              }\n              return chunkCSS\n            }\n\n            function ensureFileExt(name: string, ext: string) {\n              return normalizePath(\n                path.format({ ...path.parse(name), base: undefined, ext }),\n              )\n            }\n\n            let s: MagicString | undefined\n            const urlEmitTasks: Array<{\n              cssAssetName: string\n              originalFileName: string\n              content: string\n              start: number\n              end: number\n            }> = []\n\n            if (code.includes('__VITE_CSS_URL__')) {\n              let match: RegExpExecArray | null\n              cssUrlAssetRE.lastIndex = 0\n              while ((match = cssUrlAssetRE.exec(code))) {\n                const [full, idHex] = match\n                const id = Buffer.from(idHex, 'hex').toString()\n                const originalFileName = cleanUrl(id)\n                const cssAssetName = ensureFileExt(\n                  path.basename(originalFileName),\n                  '.css',\n                )\n                if (!styles.has(id)) {\n                  throw new Error(\n                    `css content for ${JSON.stringify(id)} was not found`,\n                  )\n                }\n\n                let cssContent = styles.get(id)!\n\n                cssContent = resolveAssetUrlsInCss(\n                  cssContent,\n                  cssAssetName,\n                  originalFileName,\n                )\n\n                urlEmitTasks.push({\n                  cssAssetName,\n                  originalFileName,\n                  content: cssContent,\n                  start: match.index,\n                  end: match.index + full.length,\n                })\n              }\n            }\n\n            // should await even if this chunk does not include __VITE_CSS_URL__\n            // so that code after this line runs in the same order\n            await urlEmitQueue.run(async () =>\n              Promise.all(\n                urlEmitTasks.map(async (info) => {\n                  info.content = await finalizeCss(info.content, config)\n                }),\n              ),\n            )\n            if (urlEmitTasks.length > 0) {\n              const toRelativeRuntime =\n                createToImportMetaURLBasedRelativeRuntime(\n                  opts.format,\n                  config.isWorker,\n                )\n              s ||= new MagicString(code)\n\n              for (const {\n                cssAssetName,\n                originalFileName,\n                content,\n                start,\n                end,\n              } of urlEmitTasks) {\n                const referenceId = this.emitFile({\n                  type: 'asset',\n                  name: cssAssetName,\n                  originalFileName,\n                  source: content,\n                })\n\n                const filename = this.getFileName(referenceId)\n                chunk.viteMetadata!.importedAssets.add(cleanUrl(filename))\n                const replacement = toOutputFilePathInJS(\n                  this.environment,\n                  filename,\n                  'asset',\n                  chunk.fileName,\n                  'js',\n                  toRelativeRuntime,\n                )\n                const replacementString =\n                  typeof replacement === 'string'\n                    ? JSON.stringify(encodeURIPath(replacement)).slice(1, -1)\n                    : `\"+${replacement.runtime}+\"`\n                s.update(start, end, replacementString)\n              }\n            }\n\n            if (chunkCSS !== undefined) {\n              if (\n                isPureCssChunk &&\n                (opts.format === 'es' || opts.format === 'cjs')\n              ) {\n                // this is a shared CSS-only chunk that is empty.\n                pureCssChunks.add(chunk)\n              }\n\n              if (this.environment.config.build.cssCodeSplit) {\n                if (\n                  (opts.format === 'es' || opts.format === 'cjs') &&\n                  !chunk.fileName.includes('-legacy')\n                ) {\n                  const isEntry = chunk.isEntry && isPureCssChunk\n                  const cssFullAssetName = ensureFileExt(chunk.name, '.css')\n                  // if facadeModuleId doesn't exist or doesn't have a CSS extension,\n                  // that means a JS entry file imports a CSS file.\n                  // in this case, only use the filename for the CSS chunk name like JS chunks.\n                  const cssAssetName =\n                    chunk.isEntry &&\n                    (!chunk.facadeModuleId ||\n                      !isCSSRequest(chunk.facadeModuleId))\n                      ? path.basename(cssFullAssetName)\n                      : cssFullAssetName\n                  const originalFileName = getChunkOriginalFileName(\n                    chunk,\n                    config.root,\n                    this.environment.config.isOutputOptionsForLegacyChunks?.(\n                      opts,\n                    ) ?? false,\n                  )\n\n                  chunkCSS = resolveAssetUrlsInCss(\n                    chunkCSS,\n                    cssAssetName,\n                    originalFileName,\n                  )\n\n                  // wait for previous tasks as well\n                  chunkCSS = await codeSplitEmitQueue.run(async () => {\n                    return finalizeCss(chunkCSS!, config)\n                  })\n\n                  // emit corresponding css file\n                  const referenceId = this.emitFile({\n                    type: 'asset',\n                    name: cssAssetName,\n                    originalFileName,\n                    source: chunkCSS,\n                  })\n                  if (isEntry) {\n                    cssEntriesMap\n                      .get(this.environment)!\n                      .set(chunk.name, referenceId)\n                  }\n                  chunk.viteMetadata!.importedCss.add(\n                    this.getFileName(referenceId),\n                  )\n                } else if (this.environment.config.consumer === 'client') {\n                  // legacy build and inline css\n\n                  // Entry chunk CSS will be collected into `chunk.viteMetadata.importedCss`\n                  // and injected later by the `'vite:build-html'` plugin into the `index.html`\n                  // so it will be duplicated. (https://github.com/vitejs/vite/issues/2062#issuecomment-782388010)\n                  // But because entry chunk can be imported by dynamic import,\n                  // we shouldn't remove the inlined CSS. (#10285)\n\n                  chunkCSS = await finalizeCss(chunkCSS, config)\n                  let cssString = JSON.stringify(chunkCSS)\n                  cssString =\n                    renderAssetUrlInJS(\n                      this,\n                      chunk,\n                      opts,\n                      cssString,\n                    )?.toString() || cssString\n                  const style = `__vite_style__`\n                  const injectCode =\n                    `var ${style} = document.createElement('style');` +\n                    `${style}.textContent = ${cssString};` +\n                    `document.head.appendChild(${style});`\n\n                  s ||= new MagicString(code)\n                  injectInlinedCSS(s, this, code, opts.format, injectCode)\n                }\n              } else {\n                // resolve public URL from CSS paths, we need to use absolute paths\n                chunkCSS = resolveAssetUrlsInCss(\n                  chunkCSS,\n                  getCssBundleName(),\n                  defaultCssBundleName,\n                )\n                // finalizeCss is called for the aggregated chunk in generateBundle\n\n                chunkCSSMap.set(chunk.fileName, chunkCSS)\n              }\n            }\n\n            if (s) {\n              if (config.build.sourcemap) {\n                return {\n                  code: s.toString(),\n                  map: s.generateMap({ hires: 'boundary' }),\n                }\n              } else {\n                return { code: s.toString() }\n              }\n            }\n            return null\n          },\n\n          augmentChunkHash(chunk) {\n            if (chunk.viteMetadata?.importedCss.size) {\n              let hash = ''\n              for (const id of chunk.viteMetadata.importedCss) {\n                hash += id\n              }\n              return hash\n            }\n          },\n        }\n      : {}),\n\n    async generateBundle(opts, bundle) {\n      // to avoid emitting duplicate assets for modern build and legacy build\n      if (this.environment.config.isOutputOptionsForLegacyChunks?.(opts)) {\n        return\n      }\n\n      // vite:asset cleans up earlier assets of 'renderChunk',\n      // but with cssCodeSplit=false we may still emit CSS here.\n      // So is our responsibility to respect emitAssets\n      const canEmitAssets =\n        config.command !== 'build' || this.environment.config.build.emitAssets\n\n      // extract as single css bundle if no codesplit\n      if (\n        canEmitAssets &&\n        !this.environment.config.build.cssCodeSplit &&\n        !hasEmitted\n      ) {\n        let extractedCss = ''\n        const collected = new Set<OutputChunk>()\n        // will be populated in order they are used by entry points\n        const dynamicImports = new Set<string>()\n\n        function collect(chunk: OutputChunk | OutputAsset | undefined) {\n          if (!chunk || chunk.type !== 'chunk' || collected.has(chunk)) return\n          collected.add(chunk)\n\n          // First collect all styles from the synchronous imports (lowest priority)\n          chunk.imports.forEach((importName) => collect(bundle[importName]))\n          // Save dynamic imports in deterministic order to add the styles later (to have the highest priority)\n          chunk.dynamicImports.forEach((importName) =>\n            dynamicImports.add(importName),\n          )\n          // Then collect the styles of the current chunk (might overwrite some styles from previous imports)\n          extractedCss += chunkCSSMap.get(chunk.preliminaryFileName) ?? ''\n        }\n\n        // The bundle is guaranteed to be deterministic, if not then we have a bug in rollup.\n        // So we use it to ensure a deterministic order of styles\n        for (const chunk of Object.values(bundle)) {\n          if (chunk.type === 'chunk' && chunk.isEntry) {\n            collect(chunk)\n          }\n        }\n        // Now collect the dynamic chunks, this is done last to have the styles overwrite the previous ones\n        for (const chunkName of dynamicImports) {\n          collect(bundle[chunkName])\n        }\n\n        // Finally, if there's any extracted CSS, we emit the asset\n        if (extractedCss) {\n          hasEmitted = true\n          extractedCss = await finalizeCss(extractedCss, config)\n          this.emitFile({\n            name: getCssBundleName(),\n            type: 'asset',\n            source: extractedCss,\n            // this file is an implicit entry point, use defaultCssBundleName as the original file name\n            // this name is also used as a key in the manifest\n            originalFileName: defaultCssBundleName,\n          })\n        }\n      }\n\n      // remove empty css chunks and their imports\n      if (pureCssChunks.size) {\n        // map each pure css chunk (rendered chunk) to it's corresponding bundle\n        // chunk. we check that by `preliminaryFileName` as they have different\n        // `filename`s (rendered chunk has the !~{XXX}~ placeholder)\n        const prelimaryNameToChunkMap = Object.fromEntries(\n          Object.values(bundle)\n            .filter((chunk): chunk is OutputChunk => chunk.type === 'chunk')\n            .map((chunk) => [chunk.preliminaryFileName, chunk.fileName]),\n        )\n\n        // When running in watch mode the generateBundle is called once per output format\n        // in this case the `bundle` is not populated with the other output files\n        // but they are still in `pureCssChunks`.\n        // So we need to filter the names and only use those who are defined\n        const pureCssChunkNames = [...pureCssChunks]\n          .map((pureCssChunk) => prelimaryNameToChunkMap[pureCssChunk.fileName])\n          .filter(Boolean)\n\n        const replaceEmptyChunk = getEmptyChunkReplacer(\n          pureCssChunkNames,\n          opts.format,\n        )\n\n        for (const file in bundle) {\n          const chunk = bundle[file]\n          if (chunk.type === 'chunk') {\n            let chunkImportsPureCssChunk = false\n            // remove pure css chunk from other chunk's imports,\n            // and also register the emitted CSS files under the importer\n            // chunks instead.\n            chunk.imports = chunk.imports.filter((file) => {\n              if (pureCssChunkNames.includes(file)) {\n                const { importedCss, importedAssets } = (\n                  bundle[file] as OutputChunk\n                ).viteMetadata!\n                importedCss.forEach((file) =>\n                  chunk.viteMetadata!.importedCss.add(file),\n                )\n                importedAssets.forEach((file) =>\n                  chunk.viteMetadata!.importedAssets.add(file),\n                )\n                chunkImportsPureCssChunk = true\n                return false\n              }\n              return true\n            })\n            if (chunkImportsPureCssChunk) {\n              chunk.code = replaceEmptyChunk(chunk.code)\n            }\n          }\n        }\n\n        const removedPureCssFiles = removedPureCssFilesCache.get(config)!\n        pureCssChunkNames.forEach((fileName) => {\n          const emptyJsPlaceholder = bundle[fileName] as RenderedChunk\n          if (emptyJsPlaceholder.isEntry) {\n            const { importedAssets, importedCss } =\n              emptyJsPlaceholder.viteMetadata!\n            const cssReferenceId = cssEntriesMap\n              .get(this.environment)!\n              .get(emptyJsPlaceholder.name)!\n            const realCssEntryName = this.getFileName(cssReferenceId)\n            const realCssEntry = bundle[realCssEntryName]!\n            importedCss.delete(realCssEntryName)\n            if (importedAssets.size) {\n              realCssEntry.viteMetadata!.importedAssets = importedAssets\n            }\n            if (importedCss.size) {\n              realCssEntry.viteMetadata!.importedCss = importedCss\n            }\n          }\n\n          removedPureCssFiles.set(fileName, emptyJsPlaceholder)\n          delete bundle[fileName]\n          delete bundle[`${fileName}.map`]\n        })\n      }\n\n      const cssAssets = Object.values(bundle).filter(\n        (asset): asset is OutputAsset =>\n          asset.type === 'asset' && asset.fileName.endsWith('.css'),\n      )\n      for (const cssAsset of cssAssets) {\n        if (typeof cssAsset.source === 'string') {\n          cssAsset.source = cssAsset.source.replace(viteHashUpdateMarkerRE, '')\n        }\n      }\n    },\n  }\n}\n\nexport function injectInlinedCSS(\n  s: MagicString,\n  ctx: Pick<MinimalPluginContext, 'error'>,\n  code: string,\n  format: InternalModuleFormat,\n  injectCode: string,\n): void {\n  let injectionPoint: number\n  if (format === 'iife' || format === 'umd') {\n    const m = (format === 'iife' ? IIFE_BEGIN_RE : UMD_BEGIN_RE).exec(code)\n    if (!m) {\n      ctx.error('Injection point for inlined CSS not found')\n    }\n    injectionPoint = m.index + m[0].length\n  } else if (format === 'es') {\n    // legacy build\n    if (code.startsWith('#!')) {\n      let secondLinePos = code.indexOf('\\n')\n      if (secondLinePos === -1) {\n        secondLinePos = 0\n      }\n      injectionPoint = secondLinePos\n    } else {\n      injectionPoint = 0\n    }\n  } else {\n    ctx.error('Non supported format')\n  }\n  s.appendRight(injectionPoint, injectCode)\n}\n\nexport function cssAnalysisPlugin(config: ResolvedConfig): Plugin {\n  return {\n    name: 'vite:css-analysis',\n\n    transform: {\n      filter: {\n        id: {\n          include: CSS_LANGS_RE,\n          exclude: [commonjsProxyRE, SPECIAL_QUERY_RE],\n        },\n      },\n      async handler(_, id) {\n        const { moduleGraph } = this.environment as DevEnvironment\n        const thisModule = moduleGraph.getModuleById(id)\n\n        // Handle CSS @import dependency HMR and other added modules via this.addWatchFile.\n        // JS-related HMR is handled in the import-analysis plugin.\n        if (thisModule) {\n          // CSS modules cannot self-accept since it exports values\n          const isSelfAccepting =\n            !cssModulesCache.get(config)?.get(id) &&\n            !inlineRE.test(id) &&\n            !htmlProxyRE.test(id)\n          // attached by pluginContainer.addWatchFile\n          const pluginImports = (this as unknown as TransformPluginContext)\n            ._addedImports\n          if (pluginImports) {\n            // record deps in the module graph so edits to @import css can trigger\n            // main import to hot update\n            const depModules = new Set<string | EnvironmentModuleNode>()\n            for (const file of pluginImports) {\n              depModules.add(moduleGraph.createFileOnlyEntry(file))\n            }\n            moduleGraph.updateModuleInfo(\n              thisModule,\n              depModules,\n              null,\n              // The root CSS proxy module is self-accepting and should not\n              // have an explicit accept list\n              new Set(),\n              null,\n              isSelfAccepting,\n            )\n          } else {\n            thisModule.isSelfAccepting = isSelfAccepting\n          }\n        }\n      },\n    },\n  }\n}\n\nfunction isCssScopeToRendered(\n  cssScopeTo: Exclude<CustomPluginOptionsVite['cssScopeTo'], undefined>,\n  renderedModules: Record<string, RenderedModule | undefined>,\n) {\n  const [importerId, exp] = cssScopeTo\n  const importer = renderedModules[importerId]\n  return (\n    importer && (exp === undefined || importer.renderedExports.includes(exp))\n  )\n}\n\n/**\n * Create a replacer function that takes code and replaces given pure CSS chunk imports\n * @param pureCssChunkNames The chunks that only contain pure CSS and should be replaced\n * @param outputFormat The module output format to decide whether to replace `import` or `require`\n */\nexport function getEmptyChunkReplacer(\n  pureCssChunkNames: string[],\n  outputFormat: InternalModuleFormat,\n): (code: string) => string {\n  const emptyChunkFiles = pureCssChunkNames\n    .map((file) => escapeRegex(path.basename(file)))\n    .join('|')\n\n  // for cjs, require calls might be chained by minifier using the comma operator.\n  // in this case we have to keep one comma if a next require is chained\n  // or add a semicolon to terminate the chain.\n  const emptyChunkRE = new RegExp(\n    outputFormat === 'es'\n      ? `\\\\bimport\\\\s*[\"'][^\"']*(?:${emptyChunkFiles})[\"'];`\n      : `(\\\\b|,\\\\s*)require\\\\(\\\\s*[\"'\\`][^\"'\\`]*(?:${emptyChunkFiles})[\"'\\`]\\\\)(;|,)`,\n    'g',\n  )\n\n  return (code: string) =>\n    code.replace(\n      emptyChunkRE,\n      // remove css import while preserving source map location\n      (m, p1, p2) => {\n        if (outputFormat === 'es') {\n          return `/* empty css ${''.padEnd(m.length - 15)}*/`\n        }\n        if (p2 === ';') {\n          // if it ends with `;`, move it before and remove the leading `,`\n          return `${p2}/* empty css ${''.padEnd(m.length - 16)}*/`\n        }\n        // if it ends with `,`, remove it but keep the leading `,` if exists\n        return `${p1}/* empty css ${''.padEnd(m.length - 15 - p1.length)}*/`\n      },\n    )\n}\n\nconst fileURLWithWindowsDriveRE = /^file:\\/\\/\\/[a-zA-Z]:\\//\n\ninterface CSSAtImportResolvers {\n  css: ResolveIdFn\n  sass: ResolveIdFn\n  less: ResolveIdFn\n}\n\nfunction createCSSResolvers(config: ResolvedConfig): CSSAtImportResolvers {\n  let cssResolve: ResolveIdFn | undefined\n  let sassResolve: ResolveIdFn | undefined\n  let lessResolve: ResolveIdFn | undefined\n  return {\n    get css() {\n      return (cssResolve ??= createBackCompatIdResolver(config, {\n        extensions: ['.css'],\n        mainFields: ['style'],\n        conditions: ['style', DEV_PROD_CONDITION],\n        tryIndex: false,\n        preferRelative: true,\n      }))\n    },\n\n    get sass() {\n      if (!sassResolve) {\n        const resolver = createBackCompatIdResolver(config, {\n          extensions: ['.scss', '.sass', '.css'],\n          mainFields: ['sass', 'style'],\n          conditions: ['sass', 'style', DEV_PROD_CONDITION],\n          tryIndex: true,\n          tryPrefix: '_',\n          preferRelative: true,\n          skipMainField: true,\n        })\n        sassResolve = async (...args) => {\n          // the modern API calls `canonicalize` with resolved file URLs\n          // for relative URLs before raw specifiers\n          if (args[1].startsWith('file://')) {\n            args[1] = fileURLToPath(args[1], {\n              windows:\n                // file:///foo cannot be converted to path with windows mode\n                isWindows && !fileURLWithWindowsDriveRE.test(args[1])\n                  ? false\n                  : undefined,\n            })\n          }\n          return resolver(...args)\n        }\n      }\n      return sassResolve\n    },\n\n    get less() {\n      return (lessResolve ??= createBackCompatIdResolver(config, {\n        extensions: ['.less', '.css'],\n        mainFields: ['less', 'style'],\n        conditions: ['less', 'style', DEV_PROD_CONDITION],\n        tryIndex: false,\n        preferRelative: true,\n      }))\n    },\n  }\n}\n\nfunction getCssResolversKeys(\n  resolvers: CSSAtImportResolvers,\n): Array<keyof CSSAtImportResolvers> {\n  return Object.keys(resolvers) as unknown as Array<keyof CSSAtImportResolvers>\n}\n\nasync function compileCSSPreprocessors(\n  environment: PartialEnvironment,\n  id: string,\n  lang: PreprocessLang,\n  code: string,\n  workerController: PreprocessorWorkerController,\n): Promise<{\n  code: string\n  map?: ExistingRawSourceMap | { mappings: '' }\n  deps?: Set<string>\n}> {\n  const { config } = environment\n  const { preprocessorOptions, devSourcemap } = config.css\n  const atImportResolvers = getAtImportResolvers(\n    environment.getTopLevelConfig(),\n  )\n  const opts = {\n    ...((preprocessorOptions && preprocessorOptions[lang]) || {}),\n    // important: set this for relative import resolving\n    filename: cleanUrl(id),\n    enableSourcemap: devSourcemap ?? false,\n  }\n\n  const preProcessor = workerController[lang]\n  const preprocessResult = await preProcessor(\n    environment,\n    code,\n    config.root,\n    opts,\n    atImportResolvers,\n  )\n  if (preprocessResult.error) {\n    throw preprocessResult.error\n  }\n\n  let deps: Set<string> | undefined\n  if (preprocessResult.deps.length > 0) {\n    const normalizedFilename = normalizePath(opts.filename)\n    // sometimes sass registers the file itself as a dep\n    deps = new Set(\n      [...preprocessResult.deps].filter(\n        (dep) => normalizePath(dep) !== normalizedFilename,\n      ),\n    )\n  }\n\n  return {\n    code: preprocessResult.code,\n    map: combineSourcemapsIfExists(\n      opts.filename,\n      preprocessResult.map,\n      preprocessResult.additionalMap,\n    ),\n    deps,\n  }\n}\n\nconst configToAtImportResolvers = new WeakMap<\n  ResolvedConfig,\n  CSSAtImportResolvers\n>()\nfunction getAtImportResolvers(config: ResolvedConfig) {\n  let atImportResolvers = configToAtImportResolvers.get(config)\n  if (!atImportResolvers) {\n    atImportResolvers = createCSSResolvers(config)\n    configToAtImportResolvers.set(config, atImportResolvers)\n  }\n  return atImportResolvers\n}\n\nasync function compileCSS(\n  environment: PartialEnvironment,\n  id: string,\n  code: string,\n  workerController: PreprocessorWorkerController,\n  urlResolver?: CssUrlResolver,\n): Promise<{\n  code: string\n  map?: SourceMapInput\n  modules?: Record<string, string>\n  deps?: Set<string>\n}> {\n  const { config } = environment\n  const lang = CSS_LANGS_RE.exec(id)?.[1] as CssLang | undefined\n  const deps = new Set<string>()\n\n  // pre-processors: sass etc.\n  let preprocessorMap: ExistingRawSourceMap | { mappings: '' } | undefined\n  if (isPreProcessor(lang)) {\n    const preprocessorResult = await compileCSSPreprocessors(\n      environment,\n      id,\n      lang,\n      code,\n      workerController,\n    )\n    code = preprocessorResult.code\n    preprocessorMap = preprocessorResult.map\n    preprocessorResult.deps?.forEach((dep) => deps.add(dep))\n  } else if (lang === 'sss' && config.css.transformer === 'lightningcss') {\n    const sssResult = await transformSugarSS(environment, id, code)\n    code = sssResult.code\n    preprocessorMap = sssResult.map\n  }\n\n  const transformResult = await (config.css.transformer === 'lightningcss'\n    ? compileLightningCSS(\n        environment,\n        id,\n        code,\n        deps,\n        workerController,\n        urlResolver,\n      )\n    : compilePostCSS(\n        environment,\n        id,\n        code,\n        deps,\n        lang,\n        workerController,\n        urlResolver,\n      ))\n\n  if (!transformResult) {\n    return {\n      code,\n      map: config.css.devSourcemap ? preprocessorMap : { mappings: '' },\n      deps,\n    }\n  }\n\n  return {\n    ...transformResult,\n    map: config.css.devSourcemap\n      ? combineSourcemapsIfExists(\n          cleanUrl(id),\n          typeof transformResult.map === 'string'\n            ? JSON.parse(transformResult.map)\n            : transformResult.map,\n          preprocessorMap,\n        )\n      : { mappings: '' },\n    deps,\n  }\n}\n\nasync function compilePostCSS(\n  environment: PartialEnvironment,\n  id: string,\n  code: string,\n  deps: Set<string>,\n  lang: CssLang | undefined,\n  workerController: PreprocessorWorkerController,\n  urlResolver?: CssUrlResolver,\n): Promise<\n  | {\n      code: string\n      map?: Exclude<SourceMapInput, string>\n      modules?: Record<string, string>\n    }\n  | undefined\n> {\n  const { config } = environment\n  const { modules: modulesOptions, devSourcemap } = config.css\n  const isModule = modulesOptions !== false && cssModuleRE.test(id)\n  // although at serve time it can work without processing, we do need to\n  // crawl them in order to register watch dependencies.\n  const needInlineImport = code.includes('@import')\n  const hasUrl = cssUrlRE.test(code) || cssImageSetRE.test(code)\n  const postcssConfig = await resolvePostcssConfig(\n    environment.getTopLevelConfig(),\n  )\n\n  // postcss processing is not needed\n  if (\n    lang !== 'sss' &&\n    !postcssConfig &&\n    !isModule &&\n    !needInlineImport &&\n    !hasUrl\n  ) {\n    return\n  }\n\n  // postcss\n  const atImportResolvers = getAtImportResolvers(\n    environment.getTopLevelConfig(),\n  )\n  const postcssPlugins = postcssConfig?.plugins.slice() ?? []\n\n  if (needInlineImport) {\n    postcssPlugins.unshift(\n      (await importPostcssImport()).default({\n        async resolve(id, basedir) {\n          const publicFile = checkPublicFile(\n            id,\n            environment.getTopLevelConfig(),\n          )\n          if (publicFile) {\n            return publicFile\n          }\n\n          const resolved = await atImportResolvers.css(\n            environment,\n            id,\n            path.join(basedir, '*'),\n          )\n\n          if (resolved) {\n            return path.resolve(resolved)\n          }\n\n          // postcss-import falls back to `resolve` dep if this is unresolved,\n          // but we've shimmed to remove the `resolve` dep to cut on bundle size.\n          // warn here to provide a better error message.\n          if (!path.isAbsolute(id)) {\n            environment.logger.error(\n              colors.red(\n                `Unable to resolve \\`@import \"${id}\"\\` from ${basedir}`,\n              ),\n            )\n          }\n\n          return id\n        },\n        async load(id) {\n          const code = await fs.promises.readFile(id, 'utf-8')\n          const lang = CSS_LANGS_RE.exec(id)?.[1] as CssLang | undefined\n          if (isPreProcessor(lang)) {\n            const result = await compileCSSPreprocessors(\n              environment,\n              id,\n              lang,\n              code,\n              workerController,\n            )\n            result.deps?.forEach((dep) => deps.add(dep))\n            // TODO: support source map\n            return result.code\n          }\n          return code\n        },\n        nameLayer(index) {\n          return `vite--anon-layer-${getHash(id)}-${index}`\n        },\n      }),\n    )\n  }\n\n  if (\n    urlResolver &&\n    // when a postcss plugin is used (including the internal postcss plugins),\n    // we need to add this plugin regardless of whether\n    // this file contains url() or image-set(),\n    // because we don't know the content injected by those plugins\n    (postcssPlugins.length > 0 || isModule || hasUrl)\n  ) {\n    postcssPlugins.push(\n      UrlRewritePostcssPlugin({\n        resolver: urlResolver,\n        deps,\n        logger: environment.logger,\n      }),\n    )\n  }\n\n  let modules: Record<string, string> | undefined\n\n  if (isModule) {\n    postcssPlugins.unshift(\n      (await importPostcssModules()).default({\n        ...modulesOptions,\n        localsConvention: modulesOptions?.localsConvention,\n        getJSON(\n          cssFileName: string,\n          _modules: Record<string, string>,\n          outputFileName: string,\n        ) {\n          modules = _modules\n          if (modulesOptions && typeof modulesOptions.getJSON === 'function') {\n            modulesOptions.getJSON(cssFileName, _modules, outputFileName)\n          }\n        },\n        async resolve(id: string, importer: string) {\n          for (const key of getCssResolversKeys(atImportResolvers)) {\n            const resolved = await atImportResolvers[key](\n              environment,\n              id,\n              importer,\n            )\n            if (resolved) {\n              return path.resolve(resolved)\n            }\n          }\n\n          return id\n        },\n      }),\n    )\n  }\n\n  const postcssOptions = postcssConfig?.options ?? {}\n  const postcssParser =\n    lang === 'sss' ? await loadSss(config.root) : postcssOptions.parser\n\n  if (!postcssPlugins.length && !postcssParser) {\n    return\n  }\n\n  const result = await runPostCSS(\n    id,\n    code,\n    postcssPlugins,\n    { ...postcssOptions, parser: postcssParser },\n    deps,\n    environment.logger,\n    devSourcemap,\n  )\n  return { ...result, modules }\n}\n\nasync function transformSugarSS(\n  environment: PartialEnvironment,\n  id: string,\n  code: string,\n) {\n  const { config } = environment\n  const { devSourcemap } = config.css\n\n  const sssParser = await loadSss(config.root)\n  const result = await runPostCSS(\n    id,\n    code,\n    [],\n    { parser: sssParser },\n    undefined,\n    environment.logger,\n    devSourcemap,\n  )\n  return result\n}\n\nasync function runPostCSS(\n  id: string,\n  code: string,\n  plugins: PostCSS.AcceptedPlugin[],\n  options: PostCSS.ProcessOptions,\n  deps: Set<string> | undefined,\n  logger: Logger,\n  enableSourcemap: boolean,\n) {\n  let postcssResult: PostCSS.Result\n  try {\n    const source = removeDirectQuery(id)\n    const postcss = await importPostcss()\n\n    // postcss is an unbundled dep and should be lazy imported\n    postcssResult = await postcss.default(plugins).process(code, {\n      ...options,\n      to: source,\n      from: source,\n      ...(enableSourcemap\n        ? {\n            map: {\n              inline: false,\n              annotation: false,\n              // postcss may return virtual files\n              // we cannot obtain content of them, so this needs to be enabled\n              sourcesContent: true,\n              // when \"prev: preprocessorMap\", the result map may include duplicate filename in `postcssResult.map.sources`\n              // prev: preprocessorMap,\n            },\n          }\n        : {}),\n    })\n\n    // record CSS dependencies from @imports\n    for (const message of postcssResult.messages) {\n      if (message.type === 'dependency') {\n        deps?.add(normalizePath(message.file as string))\n      } else if (message.type === 'dir-dependency') {\n        // https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md#3-dependencies\n        const { dir, glob: globPattern = '**' } = message\n        const files = globSync(globPattern, {\n          absolute: true,\n          cwd: path.resolve(path.dirname(id), dir),\n          expandDirectories: false,\n          ignore: ['**/node_modules/**'],\n        })\n        for (let i = 0; i < files.length; i++) {\n          deps?.add(files[i])\n        }\n      } else if (message.type === 'warning') {\n        const warning = message as PostCSS.Warning\n        let msg = `[vite:css][postcss] ${warning.text}`\n        msg += `\\n${generateCodeFrame(\n          code,\n          {\n            line: warning.line,\n            column: warning.column - 1, // 1-based\n          },\n          warning.endLine !== undefined && warning.endColumn !== undefined\n            ? {\n                line: warning.endLine,\n                column: warning.endColumn - 1, // 1-based\n              }\n            : undefined,\n        )}`\n        logger.warn(colors.yellow(msg))\n      }\n    }\n  } catch (e) {\n    e.message = `[postcss] ${e.message}`\n    e.code = code\n    e.loc = {\n      file: e.file,\n      line: e.line,\n      column: e.column - 1, // 1-based\n    }\n    throw e\n  }\n\n  if (!enableSourcemap) {\n    return {\n      code: postcssResult.css,\n      map: { mappings: '' as const },\n    }\n  }\n\n  const rawPostcssMap = postcssResult.map.toJSON()\n  const postcssMap = await formatPostcssSourceMap(\n    // version property of rawPostcssMap is declared as string\n    // but actually it is a number\n    rawPostcssMap as Omit<RawSourceMap, 'version'> as ExistingRawSourceMap,\n    cleanUrl(id),\n  )\n\n  return {\n    code: postcssResult.css,\n    map: postcssMap,\n  }\n}\n\nfunction createCachedImport<T>(imp: () => Promise<T>): () => T | Promise<T> {\n  let cached: T | Promise<T>\n  return () => {\n    if (!cached) {\n      cached = imp().then((module) => {\n        cached = module\n        return module\n      })\n    }\n    return cached\n  }\n}\nconst importPostcssImport = createCachedImport(() => import('postcss-import'))\nconst importPostcssModules = createCachedImport(() => import('postcss-modules'))\nconst importPostcss = createCachedImport(() => import('postcss'))\n\nconst preprocessorWorkerControllerCache = new WeakMap<\n  ResolvedConfig,\n  PreprocessorWorkerController\n>()\nlet alwaysFakeWorkerWorkerControllerCache:\n  | PreprocessorWorkerController\n  | undefined\n\nexport interface PreprocessCSSResult {\n  code: string\n  map?: SourceMapInput\n  modules?: Record<string, string>\n  deps?: Set<string>\n}\n\n/**\n * @experimental\n */\nexport async function preprocessCSS(\n  code: string,\n  filename: string,\n  config: ResolvedConfig,\n): Promise<PreprocessCSSResult> {\n  let workerController = preprocessorWorkerControllerCache.get(config)\n\n  if (!workerController) {\n    // if workerController doesn't exist, create a workerController that always uses fake workers\n    // because fake workers doesn't require calling `.close` unlike real workers\n    alwaysFakeWorkerWorkerControllerCache ||=\n      createPreprocessorWorkerController(0)\n    workerController = alwaysFakeWorkerWorkerControllerCache\n  }\n\n  // `preprocessCSS` is hardcoded to use the client environment.\n  // Since CSS is usually only consumed by the client, and the server builds need to match\n  // the client asset chunk name to deduplicate the link reference, this may be fine in most\n  // cases. We should revisit in the future if there's a case to preprocess CSS based on a\n  // different environment instance.\n  const environment: PartialEnvironment = new PartialEnvironment(\n    'client',\n    config,\n  )\n\n  return await compileCSS(environment, filename, code, workerController)\n}\n\nexport async function formatPostcssSourceMap(\n  rawMap: ExistingRawSourceMap,\n  file: string,\n): Promise<ExistingRawSourceMap> {\n  const inputFileDir = path.dirname(file)\n\n  // Note: the real `Sourcemap#sources` maybe `null`, but rollup typing is not handle it.\n  const sources = rawMap.sources!.map((source) => {\n    const cleanSource = cleanUrl(decodeURIComponent(source!))\n\n    // postcss virtual files\n    if (cleanSource[0] === '<' && cleanSource.endsWith('>')) {\n      return `\\0${cleanSource}`\n    }\n\n    return normalizePath(path.resolve(inputFileDir, cleanSource))\n  })\n\n  return {\n    file,\n    mappings: rawMap.mappings,\n    names: rawMap.names,\n    sources,\n    sourcesContent: rawMap.sourcesContent,\n    version: rawMap.version,\n  }\n}\n\nfunction combineSourcemapsIfExists(\n  filename: string,\n  map1: ExistingRawSourceMap | { mappings: '' } | undefined,\n  map2: ExistingRawSourceMap | { mappings: '' } | undefined,\n): ExistingRawSourceMap | { mappings: '' } | undefined {\n  if (!map1 || !map2) {\n    return map1\n  }\n  if (map1.mappings === '' || map2.mappings === '') {\n    return { mappings: '' }\n  }\n  return combineSourcemaps(filename, [\n    // type of version property of ExistingRawSourceMap is number\n    // but it is always 3\n    map1 as RawSourceMap,\n    map2 as RawSourceMap,\n  ]) as ExistingRawSourceMap\n}\n\nconst viteHashUpdateMarker = '/*$vite$:1*/'\nconst viteHashUpdateMarkerRE = /\\/\\*\\$vite\\$:\\d+\\*\\//\n\nasync function finalizeCss(css: string, config: ResolvedConfig) {\n  // hoist external @imports and @charset to the top of the CSS chunk per spec (#1845 and #6333)\n  if (css.includes('@import') || css.includes('@charset')) {\n    css = await hoistAtRules(css)\n  }\n  if (config.build.cssMinify) {\n    css = await minifyCSS(css, config, false)\n  }\n  // inject an additional string to generate a different hash for https://github.com/vitejs/vite/issues/18038\n  //\n  // pre-5.4.3, we generated CSS link tags without crossorigin attribute and generated an hash without\n  // this string\n  // in 5.4.3, we added crossorigin attribute to the generated CSS link tags but that made chromium browsers\n  // to block the CSSs from loading due to chromium's weird behavior\n  // (https://www.hacksoft.io/blog/handle-images-cors-error-in-chrome, https://issues.chromium.org/issues/40381978)\n  // to avoid that happening, we inject an additional string so that a different hash is generated\n  // for the same CSS content\n  css += viteHashUpdateMarker\n  return css\n}\n\ninterface PostCSSConfigResult {\n  options: PostCSS.ProcessOptions\n  plugins: PostCSS.AcceptedPlugin[]\n}\n\nasync function resolvePostcssConfig(\n  config: ResolvedConfig,\n): Promise<PostCSSConfigResult | null> {\n  let result = postcssConfigCache.get(config)\n  if (result !== undefined) {\n    return await result\n  }\n\n  // inline postcss config via vite config\n  const inlineOptions = config.css.postcss\n  if (isObject(inlineOptions)) {\n    const options = { ...inlineOptions }\n\n    delete options.plugins\n    result = {\n      options,\n      plugins: inlineOptions.plugins || [],\n    }\n  } else {\n    const searchPath =\n      typeof inlineOptions === 'string' ? inlineOptions : config.root\n    const stopDir = searchForWorkspaceRoot(config.root)\n    result = postcssrc({}, searchPath, { stopDir }).catch((e) => {\n      if (!e.message.includes('No PostCSS Config found')) {\n        if (e instanceof Error) {\n          const { name, message, stack } = e\n          e.name = 'Failed to load PostCSS config'\n          e.message = `Failed to load PostCSS config (searchPath: ${searchPath}): [${name}] ${message}\\n${stack}`\n          e.stack = '' // add stack to message to retain stack\n          throw e\n        } else {\n          throw new Error(`Failed to load PostCSS config: ${e}`)\n        }\n      }\n      return null\n    })\n    // replace cached promise to result object when finished\n    result.then(\n      (resolved) => {\n        postcssConfigCache.set(config, resolved)\n      },\n      () => {\n        /* keep as rejected promise, will be handled later */\n      },\n    )\n  }\n\n  postcssConfigCache.set(config, result)\n  return result\n}\n\ntype CssUrlResolver = (\n  url: string,\n  importer?: string,\n) =>\n  | [url: string, id: string | undefined]\n  | Promise<[url: string, id: string | undefined]>\n/**\n * replace URL references\n *\n * When returning `false`, it keeps the content as-is\n */\ntype CssUrlReplacer = (\n  unquotedUrl: string,\n  rawUrl: string,\n) => string | false | Promise<string | false>\n// https://drafts.csswg.org/css-syntax-3/#identifier-code-point\nexport const cssUrlRE: RegExp =\n  /(?<!@import\\s+)(?<=^|[^\\w\\-\\u0080-\\uffff])url\\((\\s*('[^']+'|\"[^\"]+\")\\s*|(?:\\\\.|[^'\")\\\\])+)\\)/\nexport const cssDataUriRE: RegExp =\n  /(?<=^|[^\\w\\-\\u0080-\\uffff])data-uri\\((\\s*('[^']+'|\"[^\"]+\")\\s*|[^'\")]+)\\)/\nexport const importCssRE: RegExp =\n  /@import\\s+(?:url\\()?('[^']+\\.css'|\"[^\"]+\\.css\"|[^'\"\\s)]+\\.css)/\n// Assuming a function name won't be longer than 256 chars\n// eslint-disable-next-line regexp/no-unused-capturing-group -- doesn't detect asyncReplace usage\nconst cssImageSetRE = /(?<=image-set\\()((?:[\\w-]{1,256}\\([^)]*\\)|[^)])*)(?=\\))/\n\nconst UrlRewritePostcssPlugin: PostCSS.PluginCreator<{\n  resolver: CssUrlResolver\n  deps: Set<string>\n  logger: Logger\n}> = (opts) => {\n  if (!opts) {\n    throw new Error('base or replace is required')\n  }\n\n  return {\n    postcssPlugin: 'vite-url-rewrite',\n    Once(root) {\n      const promises: Promise<void>[] = []\n      root.walkDecls((declaration) => {\n        const importer = declaration.source?.input.file\n        if (!importer) {\n          opts.logger.warnOnce(\n            '\\nA PostCSS plugin did not pass the `from` option to `postcss.parse`. ' +\n              'This may cause imported assets to be incorrectly transformed. ' +\n              \"If you've recently added a PostCSS plugin that raised this warning, \" +\n              'please contact the package author to fix the issue.',\n          )\n        }\n        const isCssUrl = cssUrlRE.test(declaration.value)\n        const isCssImageSet = cssImageSetRE.test(declaration.value)\n        if (isCssUrl || isCssImageSet) {\n          const replacerForDeclaration = async (rawUrl: string) => {\n            const [newUrl, resolvedId] = await opts.resolver(rawUrl, importer)\n            if (resolvedId) {\n              opts.deps.add(resolvedId)\n            }\n            return newUrl\n          }\n          if (isCssUrl && isCssImageSet) {\n            promises.push(\n              rewriteCssUrls(declaration.value, replacerForDeclaration)\n                .then((url) => rewriteCssImageSet(url, replacerForDeclaration))\n                .then((url) => {\n                  declaration.value = url\n                }),\n            )\n          } else {\n            const rewriterToUse = isCssImageSet\n              ? rewriteCssImageSet\n              : rewriteCssUrls\n            promises.push(\n              rewriterToUse(declaration.value, replacerForDeclaration).then(\n                (url) => {\n                  declaration.value = url\n                },\n              ),\n            )\n          }\n        }\n      })\n      if (promises.length) {\n        return Promise.all(promises) as any\n      }\n    },\n  }\n}\nUrlRewritePostcssPlugin.postcss = true\n\nfunction rewriteCssUrls(\n  css: string,\n  replacer: CssUrlReplacer,\n): Promise<string> {\n  return asyncReplace(css, cssUrlRE, async (match) => {\n    const [matched, rawUrl] = match\n    return await doUrlReplace(rawUrl.trim(), matched, replacer)\n  })\n}\n\nfunction rewriteCssDataUris(\n  css: string,\n  replacer: CssUrlReplacer,\n): Promise<string> {\n  return asyncReplace(css, cssDataUriRE, async (match) => {\n    const [matched, rawUrl] = match\n    return await doUrlReplace(rawUrl.trim(), matched, replacer, 'data-uri')\n  })\n}\n\nfunction rewriteImportCss(\n  css: string,\n  replacer: CssUrlReplacer,\n): Promise<string> {\n  return asyncReplace(css, importCssRE, async (match) => {\n    const [matched, rawUrl] = match\n    return await doImportCSSReplace(rawUrl, matched, replacer)\n  })\n}\n\n// TODO: image and cross-fade could contain a \"url\" that needs to be processed\n// https://drafts.csswg.org/css-images-4/#image-notation\n// https://drafts.csswg.org/css-images-4/#cross-fade-function\nconst cssNotProcessedRE = /(?:gradient|element|cross-fade|image)\\(/\n\nasync function rewriteCssImageSet(\n  css: string,\n  replacer: CssUrlReplacer,\n): Promise<string> {\n  return await asyncReplace(css, cssImageSetRE, async (match) => {\n    const [, rawUrl] = match\n    const url = await processSrcSet(rawUrl, async ({ url }) => {\n      // the url maybe url(...)\n      if (cssUrlRE.test(url)) {\n        return await rewriteCssUrls(url, replacer)\n      }\n      if (!cssNotProcessedRE.test(url)) {\n        return await doUrlReplace(url, url, replacer)\n      }\n      return url\n    })\n    return url\n  })\n}\nfunction skipUrlReplacer(unquotedUrl: string) {\n  return (\n    isExternalUrl(unquotedUrl) ||\n    isDataUrl(unquotedUrl) ||\n    unquotedUrl[0] === '#' ||\n    functionCallRE.test(unquotedUrl) ||\n    // skip if it is already a placeholder\n    unquotedUrl.startsWith('__VITE_ASSET__') ||\n    unquotedUrl.startsWith('__VITE_PUBLIC_ASSET__')\n  )\n}\nasync function doUrlReplace(\n  rawUrl: string,\n  matched: string,\n  replacer: CssUrlReplacer,\n  funcName: string = 'url',\n) {\n  let wrap = ''\n  const first = rawUrl[0]\n  let unquotedUrl = rawUrl\n  if (first === `\"` || first === `'`) {\n    wrap = first\n    unquotedUrl = rawUrl.slice(1, -1)\n  }\n  if (skipUrlReplacer(unquotedUrl)) {\n    return matched\n  }\n  //  Remove escape sequences to get the actual file name before resolving.\n  unquotedUrl = unquotedUrl.replace(/\\\\(\\W)/g, '$1')\n\n  let newUrl = await replacer(unquotedUrl, rawUrl)\n  if (newUrl === false) {\n    return matched\n  }\n\n  // The new url might need wrapping even if the original did not have it, e.g.\n  // if a space was added during replacement or the URL contains \")\"\n  if (wrap === '' && (newUrl !== encodeURI(newUrl) || newUrl.includes(')'))) {\n    wrap = '\"'\n  }\n  // If wrapping in single quotes and newUrl also contains single quotes, switch to double quotes.\n  // Give preference to double quotes since SVG inlining converts double quotes to single quotes.\n  if (wrap === \"'\" && newUrl.includes(\"'\")) {\n    wrap = '\"'\n  }\n  // Escape double quotes if they exist (they also tend to be rarer than single quotes)\n  if (wrap === '\"' && newUrl.includes('\"')) {\n    newUrl = newUrl.replace(nonEscapedDoubleQuoteRe, '\\\\\"')\n  }\n  return `${funcName}(${wrap}${newUrl}${wrap})`\n}\n\nasync function doImportCSSReplace(\n  rawUrl: string,\n  matched: string,\n  replacer: CssUrlReplacer,\n) {\n  let wrap = ''\n  const first = rawUrl[0]\n  let unquotedUrl = rawUrl\n  if (first === `\"` || first === `'`) {\n    wrap = first\n    unquotedUrl = rawUrl.slice(1, -1)\n  }\n  if (skipUrlReplacer(unquotedUrl)) {\n    return matched\n  }\n\n  const newUrl = await replacer(unquotedUrl, rawUrl)\n  if (newUrl === false) {\n    return matched\n  }\n\n  const prefix = matched.includes('url(') ? 'url(' : ''\n  return `@import ${prefix}${wrap}${newUrl}${wrap}`\n}\n\nasync function minifyCSS(\n  css: string,\n  config: ResolvedConfig,\n  inlined: boolean,\n) {\n  // We want inlined CSS to not end with a linebreak, while ensuring that\n  // regular CSS assets do end with a linebreak.\n  // See https://github.com/vitejs/vite/pull/13893#issuecomment-1678628198\n\n  if (config.build.cssMinify === 'esbuild') {\n    const { transform, formatMessages } = await importEsbuild()\n    try {\n      const { code, warnings } = await transform(css, {\n        loader: 'css',\n        target: config.build.cssTarget || undefined,\n        ...resolveMinifyCssEsbuildOptions(config.esbuild || {}),\n      })\n      if (warnings.length) {\n        const msgs = await formatMessages(warnings, { kind: 'warning' })\n        config.logger.warn(\n          colors.yellow(`[esbuild css minify]\\n${msgs.join('\\n')}`),\n        )\n      }\n      // esbuild output does return a linebreak at the end\n      return inlined ? code.trimEnd() : code\n    } catch (e) {\n      if (e.errors) {\n        e.message = '[esbuild css minify] ' + e.message\n        const msgs = await formatMessages(e.errors, { kind: 'error' })\n        e.frame = '\\n' + msgs.join('\\n')\n        e.loc = e.errors[0].location\n      }\n      throw e\n    }\n  }\n\n  try {\n    const { code, warnings } = (await importLightningCSS()).transform({\n      ...config.css.lightningcss,\n      targets: convertTargets(config.build.cssTarget),\n      cssModules: undefined,\n      // TODO: Pass actual filename here, which can also be passed to esbuild's\n      // `sourcefile` option below to improve error messages\n      filename: defaultCssBundleName,\n      code: Buffer.from(css),\n      minify: true,\n    })\n\n    for (const warning of warnings) {\n      let msg = `[lightningcss minify] ${warning.message}`\n      msg += `\\n${generateCodeFrame(css, {\n        line: warning.loc.line,\n        column: warning.loc.column - 1, // 1-based\n      })}`\n      config.logger.warn(colors.yellow(msg))\n    }\n\n    // NodeJS res.code = Buffer\n    // Deno res.code = Uint8Array\n    // For correct decode compiled css need to use TextDecoder\n    // LightningCSS output does not return a linebreak at the end\n    return decoder.decode(code) + (inlined ? '' : '\\n')\n  } catch (e) {\n    e.message = `[lightningcss minify] ${e.message}`\n    const friendlyMessage = getLightningCssErrorMessageForIeSyntaxes(css)\n    if (friendlyMessage) {\n      e.message += friendlyMessage\n    }\n\n    if (e.loc) {\n      e.loc = {\n        line: e.loc.line,\n        column: e.loc.column - 1, // 1-based\n      }\n      e.frame = generateCodeFrame(css, e.loc)\n    }\n    throw e\n  }\n}\n\nfunction resolveMinifyCssEsbuildOptions(\n  options: ESBuildOptions,\n): EsbuildTransformOptions {\n  const base: EsbuildTransformOptions = {\n    charset: options.charset,\n    logLevel: options.logLevel,\n    logLimit: options.logLimit,\n    logOverride: options.logOverride,\n    legalComments: options.legalComments,\n  }\n\n  if (\n    options.minifyIdentifiers != null ||\n    options.minifySyntax != null ||\n    options.minifyWhitespace != null\n  ) {\n    return {\n      ...base,\n      minifyIdentifiers: options.minifyIdentifiers ?? true,\n      minifySyntax: options.minifySyntax ?? true,\n      minifyWhitespace: options.minifyWhitespace ?? true,\n    }\n  } else {\n    return { ...base, minify: true }\n  }\n}\n\nconst atImportRE =\n  /@import(?:\\s*(?:url\\([^)]*\\)|\"(?:[^\"]|(?<=\\\\)\")*\"|'(?:[^']|(?<=\\\\)')*').*?|[^;]*);/g\nconst atCharsetRE =\n  /@charset(?:\\s*(?:\"(?:[^\"]|(?<=\\\\)\")*\"|'(?:[^']|(?<=\\\\)')*').*?|[^;]*);/g\n\nexport async function hoistAtRules(css: string): Promise<string> {\n  const s = new MagicString(css)\n  const cleanCss = emptyCssComments(css)\n  let match: RegExpExecArray | null\n\n  // #1845\n  // CSS @import can only appear at top of the file. We need to hoist all @import\n  // to top when multiple files are concatenated.\n  // match until semicolon that's not in quotes\n  atImportRE.lastIndex = 0\n  while ((match = atImportRE.exec(cleanCss))) {\n    s.remove(match.index, match.index + match[0].length)\n    // Use `appendLeft` instead of `prepend` to preserve original @import order\n    s.appendLeft(0, match[0])\n  }\n\n  // #6333\n  // CSS @charset must be the top-first in the file, hoist the first to top\n  atCharsetRE.lastIndex = 0\n  let foundCharset = false\n  while ((match = atCharsetRE.exec(cleanCss))) {\n    s.remove(match.index, match.index + match[0].length)\n    if (!foundCharset) {\n      s.prepend(match[0])\n      foundCharset = true\n    }\n  }\n\n  return s.toString()\n}\n\n// Preprocessor support. This logic is largely replicated from @vue/compiler-sfc\n\ntype PreprocessorAdditionalDataResult =\n  | string\n  | { content: string; map?: ExistingRawSourceMap }\n\ntype PreprocessorAdditionalData =\n  | string\n  | ((\n      source: string,\n      filename: string,\n    ) =>\n      | PreprocessorAdditionalDataResult\n      | Promise<PreprocessorAdditionalDataResult>)\n\nexport type SassPreprocessorOptions = {\n  additionalData?: PreprocessorAdditionalData\n} & SassModernPreprocessBaseOptions\n\nexport type LessPreprocessorOptions = {\n  additionalData?: PreprocessorAdditionalData\n} & LessPreprocessorBaseOptions\n\nexport type StylusPreprocessorOptions = {\n  additionalData?: PreprocessorAdditionalData\n} & StylusPreprocessorBaseOptions\n\ntype StylePreprocessorInternalOptions = {\n  maxWorkers?: number | true\n  filename: string\n  enableSourcemap: boolean\n}\n\ntype SassStylePreprocessorInternalOptions = StylePreprocessorInternalOptions &\n  SassPreprocessorOptions\n\ntype LessStylePreprocessorInternalOptions = StylePreprocessorInternalOptions &\n  LessPreprocessorOptions\n\ntype StylusStylePreprocessorInternalOptions = StylePreprocessorInternalOptions &\n  StylusPreprocessorOptions\n\ntype StylePreprocessor<Options extends StylePreprocessorInternalOptions> = {\n  process: (\n    environment: PartialEnvironment,\n    source: string,\n    root: string,\n    options: Options,\n    resolvers: CSSAtImportResolvers,\n  ) => StylePreprocessorResults | Promise<StylePreprocessorResults>\n  close: () => void\n}\n\nexport interface StylePreprocessorResults {\n  code: string\n  map?: ExistingRawSourceMap | undefined\n  additionalMap?: ExistingRawSourceMap | undefined\n  error?: RollupError\n  deps: string[]\n}\n\nconst loadedPreprocessorPath: Partial<\n  Record<PreprocessLang | PostCssDialectLang | 'sass-embedded', string>\n> = {}\n\nfunction loadPreprocessorPath(\n  lang: PreprocessLang | PostCssDialectLang | 'sass-embedded',\n  root: string,\n): string {\n  const cached = loadedPreprocessorPath[lang]\n  if (cached) {\n    return cached\n  }\n\n  // Try resolve from project root first, then the current vite installation path\n  const resolved =\n    nodeResolveWithVite(lang, undefined, { root }) ??\n    nodeResolveWithVite(lang, _dirname, { root })\n  if (resolved) return (loadedPreprocessorPath[lang] = resolved)\n\n  // Error if we can't find the preprocessor\n  const installCommand = getPackageManagerCommand('install')\n  throw new Error(\n    `Preprocessor dependency \"${lang}\" not found. Did you install it? Try \\`${installCommand} -D ${lang}\\`.`,\n  )\n}\n\nfunction loadSassPackage(\n  root: string,\n  skipEmbedded = false,\n): {\n  name: 'sass' | 'sass-embedded'\n  path: string\n} {\n  // try sass-embedded before sass, unless skipEmbedded is true\n  if (!skipEmbedded) {\n    try {\n      const path = loadPreprocessorPath('sass-embedded', root)\n      return { name: 'sass-embedded', path }\n    } catch (e1) {\n      try {\n        const path = loadPreprocessorPath(PreprocessLang.sass, root)\n        return { name: 'sass', path }\n      } catch {\n        throw e1\n      }\n    }\n  }\n\n  // skip sass-embedded and try sass directly\n  const path = loadPreprocessorPath(PreprocessLang.sass, root)\n  return { name: 'sass', path }\n}\n\nlet cachedSss: PostCSS.Syntax | Promise<PostCSS.Syntax>\nasync function loadSss(root: string): Promise<PostCSS.Syntax> {\n  if (!cachedSss) {\n    cachedSss = (async () => {\n      const sssPath = loadPreprocessorPath(PostCssDialectLang.sss, root)\n      const resolved = (await import(pathToFileURL(sssPath).href)).default\n      return (cachedSss = resolved)\n    })()\n  }\n  return cachedSss\n}\n\ndeclare const window: unknown | undefined\ndeclare const location: { href: string } | undefined\n\n// in unix, scss might append `location.href` in environments that shim `location`\n// see https://github.com/sass/dart-sass/issues/710\nfunction cleanScssBugUrl(url: string) {\n  if (\n    // check bug via `window` and `location` global\n    typeof window !== 'undefined' &&\n    typeof location !== 'undefined' &&\n    typeof location.href === 'string'\n  ) {\n    const prefix = location.href.replace(/\\/$/, '')\n    return url.replace(prefix, '')\n  } else {\n    return url\n  }\n}\n\n// #region Sass\n// .scss/.sass processor\nconst makeScssWorker = (\n  environment: PartialEnvironment,\n  resolvers: CSSAtImportResolvers,\n  _maxWorkers: number | undefined,\n) => {\n  let compilerPromise: Promise<Sass.AsyncCompiler> | undefined\n\n  // we use the compiler api provided by sass\n  // instead of creating a worker pool on our own\n  type WorkerType = InstanceType<\n    typeof WorkerWithFallback<\n      [\n        sassPath: string,\n        data: string,\n        // additionalData can a function that is not cloneable but it won't be used\n        options: SassStylePreprocessorInternalOptions & {\n          additionalData: undefined\n        },\n      ],\n      ScssWorkerResult\n    >\n  >\n\n  const worker: WorkerType = {\n    async run(sassPath, data, options) {\n      const sass: typeof Sass = await import(sassPath)\n      compilerPromise ??= sass.initAsyncCompiler()\n      const compiler = await compilerPromise\n\n      const sassOptions = { ...options } as Sass.StringOptions<'async'>\n      sassOptions.url = pathToFileURL(options.filename)\n      sassOptions.sourceMap = options.enableSourcemap\n\n      const skipRebaseUrls = (unquotedUrl: string, rawUrl: string) => {\n        const isQuoted = rawUrl[0] === '\"' || rawUrl[0] === \"'\"\n        // matches `url($foo)`\n        if (!isQuoted && unquotedUrl[0] === '$') {\n          return true\n        }\n        // matches `url(#{foo})` and `url('#{foo}')`\n        return unquotedUrl.startsWith('#{')\n      }\n\n      const internalImporter: Sass.Importer<'async'> = {\n        async canonicalize(url, context) {\n          const importer = context.containingUrl\n            ? fileURLToPath(context.containingUrl)\n            : options.filename\n          const resolved = await resolvers.sass(\n            environment,\n            url,\n            cleanScssBugUrl(importer),\n          )\n          if (\n            resolved &&\n            (resolved.endsWith('.css') ||\n              resolved.endsWith('.scss') ||\n              resolved.endsWith('.sass'))\n          ) {\n            return pathToFileURL(resolved)\n          }\n          return null\n        },\n        async load(canonicalUrl) {\n          const ext = path.extname(canonicalUrl.pathname)\n          let syntax: Sass.Syntax = 'scss'\n          if (ext === '.sass') {\n            syntax = 'indented'\n          } else if (ext === '.css') {\n            syntax = 'css'\n          }\n          const result = await rebaseUrls(\n            environment,\n            fileURLToPath(canonicalUrl),\n            options.filename,\n            resolvers.sass,\n            skipRebaseUrls,\n          )\n          const contents =\n            result.contents ?? (await fsp.readFile(result.file, 'utf-8'))\n          return { contents, syntax, sourceMapUrl: canonicalUrl }\n        },\n      }\n      sassOptions.importers = [\n        ...(sassOptions.importers ?? []),\n        internalImporter,\n      ]\n      sassOptions.importer ??= internalImporter\n\n      const result = await compiler.compileStringAsync(data, sassOptions)\n      return {\n        css: result.css,\n        map: result.sourceMap ? JSON.stringify(result.sourceMap) : undefined,\n        stats: {\n          includedFiles: result.loadedUrls\n            .filter((url) => url.protocol === 'file:')\n            .map((url) => fileURLToPath(url)),\n        },\n      } satisfies ScssWorkerResult\n    },\n    async stop() {\n      const compiler = await compilerPromise\n      await compiler?.dispose()\n      compilerPromise = undefined\n    },\n  }\n\n  return worker\n}\n\ntype ScssWorkerResult = {\n  css: string\n  map?: string | undefined\n  stats: { includedFiles: string[] }\n}\n\nconst scssProcessor = (\n  maxWorkers: number | undefined,\n): StylePreprocessor<SassStylePreprocessorInternalOptions> => {\n  let worker: ReturnType<typeof makeScssWorker> | undefined\n  let failedSassEmbedded: boolean | undefined\n\n  return {\n    close() {\n      worker?.stop()\n    },\n    async process(environment, source, root, options, resolvers) {\n      let sassPackage = loadSassPackage(root, failedSassEmbedded ?? false)\n      if (failedSassEmbedded === undefined) {\n        failedSassEmbedded = false\n        try {\n          await import(sassPackage.path)\n        } catch (e) {\n          if (/sass-embedded-[a-z0-9]+-[a-z0-9]+/i.test(e.message)) {\n            failedSassEmbedded = true\n            sassPackage = loadSassPackage(root, failedSassEmbedded)\n          }\n        }\n      }\n\n      worker ??= makeScssWorker(environment, resolvers, maxWorkers)\n\n      const { content: data, map: additionalMap } = await getSource(\n        source,\n        options.filename,\n        options.additionalData,\n        options.enableSourcemap,\n      )\n\n      const optionsWithoutAdditionalData = {\n        ...options,\n        additionalData: undefined,\n      }\n      try {\n        const result = await worker.run(\n          pathToFileURL(sassPackage.path).href,\n          data,\n          optionsWithoutAdditionalData,\n        )\n        const deps = result.stats.includedFiles.map((f) => cleanScssBugUrl(f))\n        const map: ExistingRawSourceMap | undefined = result.map\n          ? JSON.parse(result.map.toString())\n          : undefined\n\n        if (map) {\n          // Note: the real `Sourcemap#sources` maybe `null`, but rollup typing is not handle it.\n          map.sources = map.sources!.map((url) =>\n            url!.startsWith('file://')\n              ? normalizePath(fileURLToPath(url!))\n              : url,\n          )\n        }\n\n        return {\n          code: result.css.toString(),\n          map,\n          additionalMap,\n          deps,\n        }\n      } catch (e) {\n        // normalize SASS error\n        e.message = `[sass] ${e.message}`\n        e.id = e.file\n        e.frame = e.formatted\n        // modern api lacks `line` and `column` property. extract from `e.span`.\n        // NOTE: the values are 0-based so +1 is required.\n        if (e.span?.start) {\n          e.line = e.span.start.line + 1\n          e.column = e.span.start.column + 1\n          // it also lacks `e.formatted`, so we shim with the message here since\n          // sass error messages have the frame already in them and we don't want\n          // to re-generate a new frame (same as legacy api)\n          e.frame = e.message\n        }\n        return { code: '', error: e, deps: [] }\n      }\n    },\n  }\n}\n// #endregion\n\n/**\n * relative url() inside \\@imported sass and less files must be rebased to use\n * root file as base.\n */\nasync function rebaseUrls(\n  environment: PartialEnvironment,\n  file: string,\n  rootFile: string,\n  resolver: ResolveIdFn,\n  ignoreUrl?: (unquotedUrl: string, rawUrl: string) => boolean,\n): Promise<{ file: string; contents?: string }> {\n  file = path.resolve(file) // ensure os-specific flashes\n  // in the same dir, no need to rebase\n  const fileDir = path.dirname(file)\n  const rootDir = path.dirname(rootFile)\n  if (fileDir === rootDir) {\n    return { file }\n  }\n\n  const content = await fsp.readFile(file, 'utf-8')\n  // no url()\n  const hasUrls = cssUrlRE.test(content)\n  // data-uri() calls\n  const hasDataUris = cssDataUriRE.test(content)\n  // no @import xxx.css\n  const hasImportCss = importCssRE.test(content)\n\n  if (!hasUrls && !hasDataUris && !hasImportCss) {\n    return { file }\n  }\n\n  let rebased\n  const rebaseFn = async (unquotedUrl: string, rawUrl: string) => {\n    if (ignoreUrl?.(unquotedUrl, rawUrl)) return false\n    if (unquotedUrl[0] === '/') return unquotedUrl\n    const absolute =\n      (await resolver(environment, unquotedUrl, file)) ||\n      path.resolve(fileDir, unquotedUrl)\n    const relative = path.relative(rootDir, absolute)\n    return normalizePath(relative)\n  }\n\n  // fix css imports in less such as `@import \"foo.css\"`\n  if (hasImportCss) {\n    rebased = await rewriteImportCss(content, rebaseFn)\n  }\n\n  if (hasUrls) {\n    rebased = await rewriteCssUrls(rebased || content, rebaseFn)\n  }\n\n  if (hasDataUris) {\n    rebased = await rewriteCssDataUris(rebased || content, rebaseFn)\n  }\n\n  return {\n    file,\n    contents: rebased,\n  }\n}\n\n// #region Less\n// .less\nconst makeLessWorker = (\n  environment: PartialEnvironment,\n  resolvers: CSSAtImportResolvers,\n  maxWorkers: number | undefined,\n) => {\n  const skipRebaseUrls = (unquotedUrl: string, _rawUrl: string) => {\n    // matches both\n    // - interpolation: `url('@{foo}')`\n    // - variable: `url(@foo)`\n    return unquotedUrl[0] === '@'\n  }\n\n  const viteLessResolve = async (\n    filename: string,\n    dir: string,\n    rootFile: string,\n    mime: string | undefined,\n  ) => {\n    const resolved = await resolvers.less(\n      environment,\n      filename,\n      path.join(dir, '*'),\n    )\n    if (!resolved) return undefined\n\n    // don't rebase URLs in JavaScript plugins\n    if (mime === 'application/javascript') {\n      const file = path.resolve(resolved) // ensure os-specific flashes\n      return { resolved: file }\n    }\n\n    const result = await rebaseUrls(\n      environment,\n      resolved,\n      rootFile,\n      resolvers.less,\n      skipRebaseUrls,\n    )\n    return {\n      resolved,\n      contents: 'contents' in result ? result.contents : undefined,\n    }\n  }\n\n  const worker = new WorkerWithFallback(\n    async () => {\n      const [fsp, path] = await Promise.all([\n        import('node:fs/promises'),\n        import('node:path'),\n      ])\n\n      let ViteLessManager: any\n      const createViteLessPlugin = (\n        less: typeof Less,\n        rootFile: string,\n      ): Less.Plugin => {\n        const { FileManager } = less\n        ViteLessManager ??= class ViteManager extends FileManager {\n          rootFile\n          constructor(rootFile: string) {\n            super()\n            this.rootFile = rootFile\n          }\n          override supports(filename: string) {\n            return !/^(?:https?:)?\\/\\//.test(filename)\n          }\n          override supportsSync() {\n            return false\n          }\n          override async loadFile(\n            filename: string,\n            dir: string,\n            opts: any,\n            env: any,\n          ): Promise<Less.FileLoadResult> {\n            const result = await viteLessResolve(\n              filename,\n              dir,\n              this.rootFile,\n              opts.mime,\n            )\n            if (result) {\n              return {\n                filename: path.resolve(result.resolved),\n                contents:\n                  result.contents ??\n                  (await fsp.readFile(result.resolved, 'utf-8')),\n              }\n            } else {\n              return super.loadFile(filename, dir, opts, env)\n            }\n          }\n        }\n\n        return {\n          install(_, pluginManager) {\n            pluginManager.addFileManager(new ViteLessManager(rootFile))\n          },\n          minVersion: [3, 0, 0],\n        }\n      }\n\n      return async (\n        lessPath: string,\n        content: string,\n        // additionalData can a function that is not cloneable but it won't be used\n        options: LessStylePreprocessorInternalOptions & {\n          additionalData: undefined\n        },\n      ) => {\n        const nodeLess: typeof Less = (await import(lessPath)).default\n        const viteResolverPlugin = createViteLessPlugin(\n          nodeLess,\n          options.filename,\n        )\n        const result = await nodeLess.render(content, {\n          // support @import from node dependencies by default\n          paths: ['node_modules'],\n          ...options,\n          plugins: [viteResolverPlugin, ...(options.plugins || [])],\n          ...(options.enableSourcemap\n            ? {\n                sourceMap: {\n                  outputSourceFiles: true,\n                  // does not exist in types, but exists\n                  disableSourcemapAnnotation: true,\n                  sourceMapFileInline: false,\n                } as Less.SourceMapOption,\n              }\n            : {}),\n        })\n        return result\n      }\n    },\n    {\n      parentFunctions: { viteLessResolve },\n      shouldUseFake(_lessPath, _content, options) {\n        // plugins are a function and is not serializable\n        // in that case, fallback to running in main thread\n        return !!options.plugins && options.plugins.length > 0\n      },\n      max: maxWorkers,\n    },\n  )\n  return worker\n}\n\nconst lessProcessor = (\n  maxWorkers: number | undefined,\n): StylePreprocessor<LessStylePreprocessorInternalOptions> => {\n  let worker: ReturnType<typeof makeLessWorker> | undefined\n\n  return {\n    close() {\n      worker?.stop()\n    },\n    async process(environment, source, root, options, resolvers) {\n      const lessPath = loadPreprocessorPath(PreprocessLang.less, root)\n      worker ??= makeLessWorker(environment, resolvers, maxWorkers)\n\n      const { content, map: additionalMap } = await getSource(\n        source,\n        options.filename,\n        options.additionalData,\n        options.enableSourcemap,\n      )\n\n      let result: Less.RenderOutput | undefined\n      const optionsWithoutAdditionalData = {\n        ...options,\n        additionalData: undefined,\n      }\n      try {\n        result = await worker.run(\n          pathToFileURL(lessPath).href,\n          content,\n          optionsWithoutAdditionalData,\n        )\n      } catch (e) {\n        const error = e as Less.RenderError\n        // normalize error info\n        const normalizedError: RollupError = new Error(\n          `[less] ${error.message || error.type}`,\n        ) as RollupError\n        normalizedError.loc = {\n          file: error.filename || options.filename,\n          line: error.line,\n          column: error.column,\n        }\n        return { code: '', error: normalizedError, deps: [] }\n      }\n\n      const map: ExistingRawSourceMap | undefined =\n        result.map && JSON.parse(result.map)\n      if (map) {\n        delete map.sourcesContent\n      }\n\n      return {\n        code: result.css.toString(),\n        map,\n        additionalMap,\n        deps: result.imports,\n      }\n    },\n  }\n}\n// #endregion\n\n// #region Stylus\n// .styl\nconst makeStylWorker = (maxWorkers: number | undefined) => {\n  const worker = new WorkerWithFallback(\n    () => {\n      return async (\n        stylusPath: string,\n        content: string,\n        root: string,\n        // additionalData can a function that is not cloneable but it won't be used\n        options: StylusStylePreprocessorInternalOptions & {\n          additionalData: undefined\n        },\n      ) => {\n        const stylus: typeof Stylus = (await import(stylusPath)).default\n\n        const ref = stylus(content, {\n          // support @import from node dependencies by default\n          paths: ['node_modules'],\n          ...options,\n        })\n        if (options.define) {\n          for (const key in options.define) {\n            ref.define(key, options.define[key])\n          }\n        }\n        if (options.enableSourcemap) {\n          ref.set('sourcemap', {\n            comment: false,\n            inline: false,\n            basePath: root,\n          })\n        }\n\n        return {\n          code: ref.render(),\n          // @ts-expect-error sourcemap exists\n          map: ref.sourcemap as ExistingRawSourceMap | undefined,\n          deps: ref.deps(),\n        }\n      }\n    },\n    {\n      shouldUseFake(_stylusPath, _content, _root, options) {\n        // define can include functions and those are not serializable\n        // Evaluator is always a function\n        // in those cases, fallback to running in main thread\n        return !!(\n          (options.define &&\n            Object.values(options.define).some(\n              (d) => typeof d === 'function',\n            )) ||\n          options.Evaluator\n        )\n      },\n      max: maxWorkers,\n    },\n  )\n  return worker\n}\n\nconst stylProcessor = (\n  maxWorkers: number | undefined,\n): StylePreprocessor<StylusStylePreprocessorInternalOptions> => {\n  let worker: ReturnType<typeof makeStylWorker> | undefined\n\n  return {\n    close() {\n      worker?.stop()\n    },\n    async process(_environment, source, root, options, _resolvers) {\n      const stylusPath = loadPreprocessorPath(PreprocessLang.stylus, root)\n      worker ??= makeStylWorker(maxWorkers)\n\n      // Get source with preprocessor options.additionalData. Make sure a new line separator\n      // is added to avoid any render error, as added stylus content may not have semi-colon separators\n      const { content, map: additionalMap } = await getSource(\n        source,\n        options.filename,\n        options.additionalData,\n        options.enableSourcemap,\n        '\\n',\n      )\n      // Get preprocessor options.imports dependencies as stylus\n      // does not return them with its builtin `.deps()` method\n      const importsDeps = (options.imports ?? []).map((dep: string) =>\n        path.resolve(dep),\n      )\n      const optionsWithoutAdditionalData = {\n        ...options,\n        additionalData: undefined,\n      }\n      try {\n        const { code, map, deps } = await worker.run(\n          pathToFileURL(stylusPath).href,\n          content,\n          root,\n          optionsWithoutAdditionalData,\n        )\n        return {\n          code,\n          map: formatStylusSourceMap(map, root),\n          additionalMap,\n          // Concat imports deps with computed deps\n          deps: [...deps, ...importsDeps],\n        }\n      } catch (e) {\n        const wrapped = new Error(`[stylus] ${e.message}`)\n        wrapped.name = e.name\n        wrapped.stack = e.stack\n        return { code: '', error: wrapped, deps: [] }\n      }\n    },\n  }\n}\n\nfunction formatStylusSourceMap(\n  mapBefore: ExistingRawSourceMap | undefined,\n  root: string,\n): ExistingRawSourceMap | undefined {\n  if (!mapBefore) return undefined\n  const map = { ...mapBefore }\n\n  const resolveFromRoot = (p: string | null) =>\n    normalizePath(path.resolve(root, p!))\n\n  if (map.file) {\n    map.file = resolveFromRoot(map.file)\n  }\n  // Note: the real `Sourcemap#sources` maybe `null`, but rollup typing is not handle it.\n  map.sources = map.sources!.map(resolveFromRoot)\n\n  return map\n}\n// #endregion\n\nasync function getSource(\n  source: string,\n  filename: string,\n  additionalData: PreprocessorAdditionalData | undefined,\n  enableSourcemap: boolean,\n  sep: string = '',\n): Promise<{ content: string; map?: ExistingRawSourceMap }> {\n  if (!additionalData) return { content: source }\n\n  if (typeof additionalData === 'function') {\n    const newContent = await additionalData(source, filename)\n    if (typeof newContent === 'string') {\n      return { content: newContent }\n    }\n    return newContent\n  }\n\n  if (!enableSourcemap) {\n    return { content: additionalData + sep + source }\n  }\n\n  const ms = new MagicString(source)\n  ms.appendLeft(0, sep)\n  ms.appendLeft(0, additionalData)\n\n  const map = ms.generateMap({ hires: 'boundary' })\n  map.file = filename\n  map.sources = [filename]\n\n  return {\n    content: ms.toString(),\n    map,\n  }\n}\n\nconst createPreprocessorWorkerController = (maxWorkers: number | undefined) => {\n  const scss = scssProcessor(maxWorkers)\n  const less = lessProcessor(maxWorkers)\n  const styl = stylProcessor(maxWorkers)\n\n  const sassProcess: StylePreprocessor<SassStylePreprocessorInternalOptions>['process'] =\n    (environment, source, root, options, resolvers) => {\n      const opts: SassStylePreprocessorInternalOptions = { ...options }\n      opts.syntax = 'indented'\n      return scss.process(environment, source, root, opts, resolvers)\n    }\n\n  const close = () => {\n    less.close()\n    scss.close()\n    styl.close()\n  }\n\n  return {\n    [PreprocessLang.less]: less.process,\n    [PreprocessLang.scss]: scss.process,\n    [PreprocessLang.sass]: sassProcess,\n    [PreprocessLang.styl]: styl.process,\n    [PreprocessLang.stylus]: styl.process,\n    close,\n  } as const satisfies Record<PreprocessLang | 'close', unknown>\n}\n\nconst normalizeMaxWorkers = (maxWorker: number | true | undefined) => {\n  if (maxWorker === undefined) return 0\n  if (maxWorker === true) return undefined\n  return maxWorker\n}\n\ntype PreprocessorWorkerController = ReturnType<\n  typeof createPreprocessorWorkerController\n>\n\nconst preprocessorSet = new Set([\n  PreprocessLang.less,\n  PreprocessLang.sass,\n  PreprocessLang.scss,\n  PreprocessLang.styl,\n  PreprocessLang.stylus,\n] as const)\n\nfunction isPreProcessor(lang: any): lang is PreprocessLang {\n  return lang && preprocessorSet.has(lang)\n}\n\nconst importEsbuild = createCachedImport(() => import('esbuild'))\n\nconst importLightningCSS = createCachedImport(() => import('lightningcss'))\nasync function compileLightningCSS(\n  environment: PartialEnvironment,\n  id: string,\n  src: string,\n  deps: Set<string>,\n  workerController: PreprocessorWorkerController,\n  urlResolver?: CssUrlResolver,\n): Promise<{\n  code: string\n  map?: string | undefined\n  modules?: Record<string, string>\n}> {\n  const { config } = environment\n  // replace null byte as lightningcss treats that as a string terminator\n  // https://github.com/parcel-bundler/lightningcss/issues/874\n  const filename = removeDirectQuery(id).replace('\\0', NULL_BYTE_PLACEHOLDER)\n\n  let res: LightningCssTransformAttributeResult | LightningCssTransformResult\n  try {\n    res = styleAttrRE.test(id)\n      ? (await importLightningCSS()).transformStyleAttribute({\n          filename,\n          code: Buffer.from(src),\n          targets: config.css.lightningcss?.targets,\n          minify: config.isProduction && !!config.build.cssMinify,\n          analyzeDependencies: true,\n        })\n      : await (\n          await importLightningCSS()\n        ).bundleAsync({\n          ...config.css.lightningcss,\n          filename,\n          // projectRoot is needed to get stable hash when using CSS modules\n          projectRoot: config.root,\n          resolver: {\n            async read(filePath) {\n              if (filePath === filename) {\n                return src\n              }\n\n              const code = fs.readFileSync(filePath, 'utf-8')\n              const lang = CSS_LANGS_RE.exec(filePath)?.[1] as\n                | CssLang\n                | undefined\n              if (isPreProcessor(lang)) {\n                const result = await compileCSSPreprocessors(\n                  environment,\n                  id,\n                  lang,\n                  code,\n                  workerController,\n                )\n                result.deps?.forEach((dep) => deps.add(dep))\n                // TODO: support source map\n                return result.code\n              } else if (lang === 'sss') {\n                const sssResult = await transformSugarSS(environment, id, code)\n                // TODO: support source map\n                return sssResult.code\n              }\n              return code\n            },\n            async resolve(id, from) {\n              const publicFile = checkPublicFile(\n                id,\n                environment.getTopLevelConfig(),\n              )\n              if (publicFile) {\n                return publicFile\n              }\n\n              // NOTE: with `transformer: 'postcss'`, CSS modules `composes` tried to resolve with\n              //       all resolvers, but in `transformer: 'lightningcss'`, only the one for the\n              //       current file type is used.\n              const atImportResolvers = getAtImportResolvers(\n                environment.getTopLevelConfig(),\n              )\n              const lang = CSS_LANGS_RE.exec(from)?.[1] as CssLang | undefined\n              let resolver: ResolveIdFn\n              switch (lang) {\n                case 'css':\n                case 'sss':\n                case 'styl':\n                case 'stylus':\n                case undefined:\n                  resolver = atImportResolvers.css\n                  break\n                case 'sass':\n                case 'scss':\n                  resolver = atImportResolvers.sass\n                  break\n                case 'less':\n                  resolver = atImportResolvers.less\n                  break\n                default:\n                  throw new Error(`Unknown lang: ${lang satisfies never}`)\n              }\n\n              const resolved = await resolver(environment, id, from)\n              if (resolved) {\n                deps.add(resolved)\n                return resolved\n              }\n              return id\n            },\n          },\n          minify: config.isProduction && !!config.build.cssMinify,\n          sourceMap:\n            config.command === 'build'\n              ? !!config.build.sourcemap\n              : config.css.devSourcemap,\n          analyzeDependencies: true,\n          cssModules: cssModuleRE.test(id)\n            ? (config.css.lightningcss?.cssModules ?? true)\n            : undefined,\n        })\n  } catch (e) {\n    e.message = `[lightningcss] ${e.message}`\n    if (e.loc) {\n      e.loc = {\n        file: e.fileName.replace(NULL_BYTE_PLACEHOLDER, '\\0'),\n        line: e.loc.line,\n        column: e.loc.column - 1, // 1-based\n      }\n      try {\n        const code = fs.readFileSync(e.fileName, 'utf-8')\n        const friendlyMessage = getLightningCssErrorMessageForIeSyntaxes(code)\n        if (friendlyMessage) {\n          e.message += friendlyMessage\n        }\n      } catch {}\n    }\n    throw e\n  }\n\n  for (const warning of res.warnings) {\n    let msg = `[vite:css][lightningcss] ${warning.message}`\n    msg += `\\n${generateCodeFrame(src, {\n      line: warning.loc.line,\n      column: warning.loc.column - 1, // 1-based\n    })}`\n    environment.logger.warn(colors.yellow(msg))\n  }\n\n  // NodeJS res.code = Buffer\n  // Deno res.code = Uint8Array\n  // For correct decode compiled css need to use TextDecoder\n  let css = decoder.decode(res.code)\n  for (const dep of res.dependencies!) {\n    switch (dep.type) {\n      case 'url': {\n        let replaceUrl: string\n        if (skipUrlReplacer(dep.url)) {\n          replaceUrl = dep.url\n        } else if (urlResolver) {\n          const [newUrl, resolvedId] = await urlResolver(\n            dep.url,\n            dep.loc.filePath.replace(NULL_BYTE_PLACEHOLDER, '\\0'),\n          )\n          if (resolvedId) {\n            deps.add(resolvedId)\n          }\n          replaceUrl = newUrl\n        } else {\n          replaceUrl = dep.url\n        }\n\n        css = css.replace(\n          dep.placeholder,\n          // lightningcss always generates `url(\"placeholder\")`\n          // (`url('placeholder')`, `url(placeholder)` is not generated)\n          // so escape double quotes\n          () => replaceUrl.replaceAll('\"', '\\\\\"'),\n        )\n        break\n      }\n      default:\n        throw new Error(`Unsupported dependency type: ${dep.type}`)\n    }\n  }\n\n  let modules: Record<string, string> | undefined\n  if ('exports' in res && res.exports) {\n    modules = {}\n    // https://github.com/parcel-bundler/lightningcss/issues/291\n    const sortedEntries = Object.entries(res.exports).sort((a, b) =>\n      a[0].localeCompare(b[0]),\n    )\n    for (const [key, value] of sortedEntries) {\n      modules[key] = value.name\n      // https://lightningcss.dev/css-modules.html#class-composition\n      for (const c of value.composes) {\n        modules[key] += ' ' + c.name\n      }\n    }\n  }\n\n  return {\n    code: css,\n    map: 'map' in res ? res.map?.toString() : undefined,\n    modules,\n  }\n}\n\n// friendly error for https://github.com/parcel-bundler/lightningcss/issues/39\nfunction getLightningCssErrorMessageForIeSyntaxes(\n  code: string,\n): string | undefined {\n  const commonIeMessage =\n    ', which was used in the past to support old Internet Explorer versions.' +\n    ' This is not a valid CSS syntax and will be ignored by modern browsers. ' +\n    '\\nWhile this is not supported by LightningCSS, you can set `css.lightningcss.errorRecovery: true` to strip these codes.'\n  if (/[\\s;{]\\*[a-zA-Z-][\\w-]+\\s*:/.test(code)) {\n    // https://stackoverflow.com/a/1667560\n    return (\n      '.\\nThis file contains star property hack (e.g. `*zoom`)' +\n      commonIeMessage\n    )\n  }\n  if (/min-width:\\s*0\\\\0/.test(code)) {\n    // https://stackoverflow.com/a/14585820\n    return (\n      '.\\nThis file contains @media zero hack (e.g. `@media (min-width: 0\\\\0)`)' +\n      commonIeMessage\n    )\n  }\n  return undefined\n}\n\n// Convert https://esbuild.github.io/api/#target\n// To https://github.com/parcel-bundler/lightningcss/blob/master/node/targets.d.ts\n\nconst map: Record<\n  string,\n  keyof NonNullable<LightningCSSOptions['targets']> | false | undefined\n> = {\n  chrome: 'chrome',\n  edge: 'edge',\n  firefox: 'firefox',\n  hermes: false,\n  ie: 'ie',\n  ios: 'ios_saf',\n  node: false,\n  opera: 'opera',\n  rhino: false,\n  safari: 'safari',\n}\n\nconst esMap: Record<number, string[]> = {\n  // https://caniuse.com/?search=es2015\n  2015: ['chrome49', 'edge13', 'safari10', 'ios10', 'firefox44', 'opera36'],\n  // https://caniuse.com/?search=es2016\n  2016: ['chrome50', 'edge13', 'safari10', 'ios10', 'firefox43', 'opera37'],\n  // https://caniuse.com/?search=es2017\n  2017: ['chrome58', 'edge15', 'safari11', 'ios11', 'firefox52', 'opera45'],\n  // https://caniuse.com/?search=es2018\n  2018: ['chrome63', 'edge79', 'safari12', 'ios12', 'firefox58', 'opera50'],\n  // https://caniuse.com/?search=es2019\n  2019: ['chrome73', 'edge79', 'safari12.1', 'ios12.1', 'firefox64', 'opera60'],\n  // https://caniuse.com/?search=es2020\n  2020: ['chrome80', 'edge80', 'safari14.1', 'ios14.5', 'firefox80', 'opera67'],\n  // https://caniuse.com/?search=es2021\n  2021: ['chrome85', 'edge85', 'safari14.1', 'ios14.5', 'firefox80', 'opera71'],\n  // https://caniuse.com/?search=es2022\n  2022: ['chrome94', 'edge94', 'safari16.4', 'ios16.4', 'firefox93', 'opera80'],\n  // https://caniuse.com/?search=es2023\n  2023: [\n    'chrome110',\n    'edge110',\n    'safari16.4',\n    'ios16.4',\n    'firefox146',\n    'opera96',\n  ],\n  // https://caniuse.com/sr-es15\n  2024: [\n    'chrome119',\n    'edge119',\n    'safari17.4',\n    'ios17.4',\n    'firefox145',\n    'opera105',\n  ],\n  // https://caniuse.com/?feats=mdn-javascript_builtins_set_union%2Cmdn-javascript_builtins_iterator_toarray%2Cmdn-javascript_statements_import_import_attributes_type_json%2Cmdn-javascript_regular_expressions_named_capturing_group_duplicate_named_capturing_groups%2Cmdn-javascript_regular_expressions_modifier%2Cmdn-javascript_builtins_promise_try%2Cmdn-javascript_builtins_float16array%2Cmdn-javascript_builtins_regexp_escape\n  2025: [\n    'chrome136',\n    'edge136',\n    'safari26.0',\n    'ios26.0',\n    'firefox138',\n    'opera121',\n  ],\n}\n\nconst esRE = /es(6|\\d{4})/\nconst versionRE = /\\d/\n\nconst convertTargetsCache = new Map<\n  string | string[],\n  LightningCSSOptions['targets']\n>()\nexport const convertTargets = (\n  esbuildTarget: string | string[] | false,\n): LightningCSSOptions['targets'] => {\n  if (!esbuildTarget) return {}\n  const cached = convertTargetsCache.get(esbuildTarget)\n  if (cached) return cached\n  const targets: LightningCSSOptions['targets'] = {}\n\n  const entriesWithoutES = arraify(esbuildTarget).flatMap((e) => {\n    const match = esRE.exec(e)\n    if (!match) return e\n    const year = match[1] === '6' ? 2015 : Number(match[1])\n    if (!esMap[year]) throw new Error(`Unsupported target \"${e}\"`)\n    return esMap[year]\n  })\n\n  for (const entry of entriesWithoutES) {\n    if (entry === 'esnext') continue\n    const index = entry.search(versionRE)\n    if (index >= 0) {\n      const browser = map[entry.slice(0, index)]\n      if (browser === false) continue // No mapping available\n      if (browser) {\n        const [major, minor = 0] = entry\n          .slice(index)\n          .split('.')\n          .map((v) => parseInt(v, 10))\n        if (!isNaN(major) && !isNaN(minor)) {\n          const version = (major << 16) | (minor << 8)\n          if (!targets[browser] || version < targets[browser]!) {\n            targets[browser] = version\n          }\n          continue\n        }\n      }\n    }\n    throw new Error(`Unsupported target \"${entry}\"`)\n  }\n\n  convertTargetsCache.set(esbuildTarget, targets)\n  return targets\n}\n\nexport function resolveLibCssFilename(\n  libOptions: LibraryOptions,\n  root: string,\n  packageCache?: PackageCache,\n): string {\n  if (typeof libOptions.cssFileName === 'string') {\n    return `${libOptions.cssFileName}.css`\n  } else if (typeof libOptions.fileName === 'string') {\n    return `${libOptions.fileName}.css`\n  }\n\n  const packageJson = findNearestMainPackageData(root, packageCache)?.data\n  const name = packageJson ? getPkgName(packageJson.name) : undefined\n\n  if (!name)\n    throw new Error(\n      'Name in package.json is required if option \"build.lib.cssFileName\" is not provided.',\n    )\n\n  return `${name}.css`\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/define.ts",
    "content": "import { transformSync } from 'rolldown/utils'\nimport type { ResolvedConfig } from '../config'\nimport type { Plugin } from '../plugin'\nimport { escapeRegex, isCSSRequest } from '../utils'\nimport type { Environment } from '../environment'\nimport { isHTMLRequest } from './html'\n\nconst nonJsRe = /\\.json(?:$|\\?)/\nconst isNonJsRequest = (request: string): boolean => nonJsRe.test(request)\nconst escapedDotRE = /(?<!\\\\)\\\\./g\n\nexport function definePlugin(config: ResolvedConfig): Plugin {\n  const isBundled = config.isBundled\n  const isBuild = config.command === 'build'\n  const isBuildLib = isBuild && config.build.lib\n\n  // ignore replace process.env in lib build\n  const processEnv: Record<string, string> = {}\n  if (!isBuildLib) {\n    const nodeEnv = process.env.NODE_ENV || config.mode\n    Object.assign(processEnv, {\n      'process.env': `{}`,\n      'global.process.env': `{}`,\n      'globalThis.process.env': `{}`,\n      'process.env.NODE_ENV': JSON.stringify(nodeEnv),\n      'global.process.env.NODE_ENV': JSON.stringify(nodeEnv),\n      'globalThis.process.env.NODE_ENV': JSON.stringify(nodeEnv),\n    })\n  }\n\n  // during dev, import.meta properties are handled by importAnalysis plugin.\n  const importMetaKeys: Record<string, string> = {}\n  const importMetaEnvKeys: Record<string, string> = {}\n  const importMetaFallbackKeys: Record<string, string> = {}\n  if (isBuild) {\n    importMetaKeys['import.meta.hot'] = `undefined`\n  }\n  if (isBundled) {\n    for (const key in config.env) {\n      const val = JSON.stringify(config.env[key])\n      importMetaKeys[`import.meta.env.${key}`] = val\n      importMetaEnvKeys[key] = val\n    }\n    // these will be set to a proper value in `generatePattern`\n    importMetaKeys['import.meta.env.SSR'] = `undefined`\n    importMetaFallbackKeys['import.meta.env'] = `undefined`\n  }\n\n  function generatePattern(environment: Environment) {\n    const keepProcessEnv = environment.config.keepProcessEnv\n\n    const userDefine: Record<string, string> = {}\n    const userDefineEnv: Record<string, any> = {}\n    for (const key in environment.config.define) {\n      userDefine[key] = handleDefineValue(environment.config.define[key])\n\n      // make sure `import.meta.env` object has user define properties\n      if (isBuild && key.startsWith('import.meta.env.')) {\n        userDefineEnv[key.slice(16)] = environment.config.define[key]\n      }\n    }\n\n    const define: Record<string, string> = {\n      ...(keepProcessEnv ? {} : processEnv),\n      ...importMetaKeys,\n      ...userDefine,\n      ...importMetaFallbackKeys,\n    }\n\n    // Additional define fixes based on `ssr` value\n    const ssr = environment.config.consumer === 'server'\n\n    if ('import.meta.env.SSR' in define) {\n      define['import.meta.env.SSR'] = ssr + ''\n    }\n\n    const importMetaEnvVal = serializeDefine({\n      ...importMetaEnvKeys,\n      SSR: ssr + '',\n      ...userDefineEnv,\n    })\n\n    // Create regex pattern as a fast check before running esbuild\n    const patternKeys = Object.keys(userDefine)\n    if (!keepProcessEnv && Object.keys(processEnv).length) {\n      patternKeys.push('process.env')\n    }\n    if (Object.keys(importMetaKeys).length) {\n      patternKeys.push('import.meta.env', 'import.meta.hot')\n    }\n    const pattern = patternKeys.length\n      ? new RegExp(\n          patternKeys\n            // replace `\\.` (ignore `\\\\.`) with `\\??\\.` to match with `?.` as well\n            .map((key) => escapeRegex(key).replaceAll(escapedDotRE, '\\\\??\\\\.'))\n            .join('|'),\n        )\n      : null\n\n    return [define, pattern, importMetaEnvVal] as const\n  }\n\n  const patternsCache = new WeakMap<\n    Environment,\n    readonly [Record<string, string>, RegExp | null, string]\n  >()\n  function getPattern(environment: Environment) {\n    let pattern = patternsCache.get(environment)\n    if (!pattern) {\n      pattern = generatePattern(environment)\n      patternsCache.set(environment, pattern)\n    }\n    return pattern\n  }\n\n  if (isBundled) {\n    return {\n      name: 'vite:define',\n      options(option) {\n        const [define, _pattern, importMetaEnvVal] = getPattern(\n          this.environment,\n        )\n        define['import.meta.env'] = importMetaEnvVal\n        define['import.meta.env.*'] = 'undefined'\n        option.transform ??= {}\n        option.transform.define = { ...option.transform.define, ...define }\n      },\n    }\n  }\n\n  return {\n    name: 'vite:define',\n\n    transform: {\n      async handler(code, id) {\n        if (this.environment.config.consumer === 'client') {\n          // for dev we inject actual global defines in the vite client to\n          // avoid the transform cost. see the `clientInjection` and\n          // `importAnalysis` plugin.\n          return\n        }\n\n        if (\n          // exclude html, css and static assets for performance\n          isHTMLRequest(id) ||\n          isCSSRequest(id) ||\n          isNonJsRequest(id) ||\n          config.assetsInclude(id)\n        ) {\n          return\n        }\n\n        const [define, pattern] = getPattern(this.environment)\n        if (!pattern) return\n\n        // Check if our code needs any replacements before running esbuild\n        pattern.lastIndex = 0\n        if (!pattern.test(code)) return\n\n        const result = await replaceDefine(this.environment, code, id, define)\n        return result\n      },\n    },\n  }\n}\n\nexport async function replaceDefine(\n  environment: Environment,\n  code: string,\n  id: string,\n  define: Record<string, string>,\n): Promise<{\n  code: string\n  map: ReturnType<typeof transformSync>['map'] | null\n}> {\n  const result = transformSync(id, code, {\n    lang: 'js',\n    sourceType: 'module',\n    define,\n    sourcemap:\n      environment.config.command === 'build'\n        ? !!environment.config.build.sourcemap\n        : true,\n    tsconfig: false,\n  })\n\n  if (result.errors.length > 0) {\n    throw new AggregateError(result.errors, 'oxc transform error')\n  }\n\n  return {\n    code: result.code,\n    map: result.map || null,\n  }\n}\n\n/**\n * Like `JSON.stringify` but keeps raw string values as a literal\n * in the generated code. For example: `\"window\"` would refer to\n * the global `window` object directly.\n */\nexport function serializeDefine(define: Record<string, any>): string {\n  let res = `{`\n  const keys = Object.keys(define).sort()\n  for (let i = 0; i < keys.length; i++) {\n    const key = keys[i]\n    const val = define[key]\n    res += `${JSON.stringify(key)}: ${handleDefineValue(val)}`\n    if (i !== keys.length - 1) {\n      res += `, `\n    }\n  }\n  return res + `}`\n}\n\nfunction handleDefineValue(value: any): string {\n  if (typeof value === 'undefined') return 'undefined'\n  if (typeof value === 'string') return value\n  return JSON.stringify(value)\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/dynamicImportVars.ts",
    "content": "import { posix } from 'node:path'\nimport MagicString from 'magic-string'\nimport { init, parse as parseImports } from 'es-module-lexer'\nimport type { ImportSpecifier } from 'es-module-lexer'\nimport { parseAst } from 'rolldown/parseAst'\nimport { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars'\nimport { viteDynamicImportVarsPlugin as nativeDynamicImportVarsPlugin } from 'rolldown/experimental'\nimport { exactRegex } from 'rolldown/filter'\nimport { type Plugin, perEnvironmentPlugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport { CLIENT_ENTRY } from '../constants'\nimport { createBackCompatIdResolver } from '../idResolver'\nimport {\n  createFilter,\n  normalizePath,\n  rawRE,\n  requestQueryMaybeEscapedSplitRE,\n  requestQuerySplitRE,\n  transformStableResult,\n  urlRE,\n} from '../utils'\nimport type { Environment } from '../environment'\nimport { perEnvironmentState } from '../environment'\nimport { hasViteIgnoreRE } from './importAnalysis'\nimport { workerOrSharedWorkerRE } from './worker'\n\nexport const dynamicImportHelperId = '\\0vite/dynamic-import-helper.js'\n\nconst relativePathRE = /^\\.{1,2}\\//\n// fast path to check if source contains a dynamic import. we check for a\n// trailing slash too as a dynamic import statement can have comments between\n// the `import` and the `(`.\nconst hasDynamicImportRE = /\\bimport\\s*[(/]/\n\ninterface DynamicImportRequest {\n  query?: string | Record<string, string>\n  import?: string\n}\n\ninterface DynamicImportPattern {\n  globParams: DynamicImportRequest | null\n  userPattern: string\n  rawPattern: string\n}\n\nconst dynamicImportHelper = (\n  glob: Record<string, any>,\n  path: string,\n  segs: number,\n) => {\n  const v = glob[path]\n  if (v) {\n    return typeof v === 'function' ? v() : Promise.resolve(v)\n  }\n  return new Promise((_, reject) => {\n    ;(typeof queueMicrotask === 'function' ? queueMicrotask : setTimeout)(\n      reject.bind(\n        null,\n        new Error(\n          'Unknown variable dynamic import: ' +\n            path +\n            (path.split('/').length !== segs\n              ? '. Note that variables only represent file names one level deep.'\n              : ''),\n        ),\n      ),\n    )\n  })\n}\n\nfunction parseDynamicImportPattern(\n  strings: string,\n): DynamicImportPattern | null {\n  const filename = strings.slice(1, -1)\n  const ast = (parseAst(strings).body[0] as any).expression\n\n  const userPatternQuery = dynamicImportToGlob(ast, filename)\n  if (!userPatternQuery) {\n    return null\n  }\n\n  const [userPattern] = userPatternQuery.split(\n    // ? is escaped on posix OS\n    requestQueryMaybeEscapedSplitRE,\n    2,\n  )\n  let [rawPattern, search] = filename.split(requestQuerySplitRE, 2)\n  let globParams: DynamicImportRequest | null = null\n  if (search) {\n    search = '?' + search\n    if (\n      workerOrSharedWorkerRE.test(search) ||\n      urlRE.test(search) ||\n      rawRE.test(search)\n    ) {\n      globParams = {\n        query: search,\n        import: '*',\n      }\n    } else {\n      globParams = {\n        query: search,\n      }\n    }\n  }\n\n  return {\n    globParams,\n    userPattern,\n    rawPattern,\n  }\n}\n\nexport async function transformDynamicImport(\n  importSource: string,\n  importer: string,\n  resolve: (\n    url: string,\n    importer?: string,\n  ) => Promise<string | undefined> | string | undefined,\n  root: string,\n): Promise<{\n  glob: string\n  pattern: string\n  rawPattern: string\n} | null> {\n  if (importSource[1] !== '.' && importSource[1] !== '/') {\n    const resolvedFileName = await resolve(importSource.slice(1, -1), importer)\n    if (!resolvedFileName) {\n      return null\n    }\n    const relativeFileName = normalizePath(\n      posix.relative(\n        posix.dirname(normalizePath(importer)),\n        normalizePath(resolvedFileName),\n      ),\n    )\n    importSource =\n      '`' + (relativeFileName[0] === '.' ? '' : './') + relativeFileName + '`'\n  }\n\n  const dynamicImportPattern = parseDynamicImportPattern(importSource)\n  if (!dynamicImportPattern) {\n    return null\n  }\n  const { globParams, rawPattern, userPattern } = dynamicImportPattern\n  const params = globParams ? `, ${JSON.stringify(globParams)}` : ''\n  const dir = importer ? posix.dirname(importer) : root\n  const normalized =\n    rawPattern[0] === '/'\n      ? posix.join(root, rawPattern.slice(1))\n      : posix.join(dir, rawPattern)\n\n  let newRawPattern = posix.relative(posix.dirname(importer), normalized)\n\n  if (!relativePathRE.test(newRawPattern)) {\n    newRawPattern = `./${newRawPattern}`\n  }\n\n  const exp = `(import.meta.glob(${JSON.stringify(userPattern)}${params}))`\n\n  return {\n    rawPattern: newRawPattern,\n    pattern: userPattern,\n    glob: exp,\n  }\n}\n\nexport function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin {\n  const resolve = createBackCompatIdResolver(config, {\n    preferRelative: true,\n    tryIndex: false,\n    extensions: [],\n  })\n\n  if (config.isBundled) {\n    return perEnvironmentPlugin('native:dynamic-import-vars', (environment) => {\n      const { include, exclude } =\n        environment.config.build.dynamicImportVarsOptions\n\n      return nativeDynamicImportVarsPlugin({\n        include,\n        exclude,\n        resolver(id, importer) {\n          return resolve(environment, id, importer)\n        },\n        sourcemap: !!environment.config.build.sourcemap,\n      })\n    })\n  }\n\n  const getFilter = perEnvironmentState((environment: Environment) => {\n    const { include, exclude } =\n      environment.config.build.dynamicImportVarsOptions\n    return createFilter(include, exclude)\n  })\n\n  return {\n    name: 'vite:dynamic-import-vars',\n\n    resolveId: {\n      filter: { id: exactRegex(dynamicImportHelperId) },\n      handler(id) {\n        return id\n      },\n    },\n\n    load: {\n      filter: { id: exactRegex(dynamicImportHelperId) },\n      handler(_id) {\n        return `export default ${dynamicImportHelper.toString()}`\n      },\n    },\n\n    transform: {\n      filter: {\n        id: { exclude: exactRegex(CLIENT_ENTRY) },\n        code: hasDynamicImportRE,\n      },\n      async handler(source, importer) {\n        const { environment } = this\n        if (!getFilter(this)(importer)) {\n          return\n        }\n\n        await init\n\n        let imports: readonly ImportSpecifier[] = []\n        try {\n          imports = parseImports(source)[0]\n        } catch {\n          // ignore as it might not be a JS file, the subsequent plugins will catch the error\n          return null\n        }\n\n        if (!imports.length) {\n          return null\n        }\n\n        let s: MagicString | undefined\n        let needDynamicImportHelper = false\n\n        for (let index = 0; index < imports.length; index++) {\n          const {\n            s: start,\n            e: end,\n            ss: expStart,\n            se: expEnd,\n            d: dynamicIndex,\n          } = imports[index]\n\n          if (dynamicIndex === -1 || source[start] !== '`') {\n            continue\n          }\n\n          if (hasViteIgnoreRE.test(source.slice(expStart, expEnd))) {\n            continue\n          }\n\n          s ||= new MagicString(source)\n          let result\n          try {\n            result = await transformDynamicImport(\n              source.slice(start, end),\n              importer,\n              (id, importer) => resolve(environment, id, importer),\n              config.root,\n            )\n          } catch (error) {\n            this.warn(error)\n          }\n\n          if (!result) {\n            continue\n          }\n\n          const { rawPattern, glob } = result\n\n          needDynamicImportHelper = true\n          s.overwrite(\n            expStart,\n            expEnd,\n            `__variableDynamicImportRuntimeHelper(${glob}, \\`${rawPattern}\\`, ${rawPattern.split('/').length})`,\n          )\n        }\n\n        if (s) {\n          if (needDynamicImportHelper) {\n            s.prepend(\n              `import __variableDynamicImportRuntimeHelper from \"${dynamicImportHelperId}\";`,\n            )\n          }\n          return transformStableResult(s, importer, config)\n        }\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/esbuild.ts",
    "content": "import path from 'node:path'\nimport colors from 'picocolors'\nimport type { RawSourceMap } from '@jridgewell/remapping'\nimport type { InternalModuleFormat, SourceMap } from 'rolldown'\nimport { resolveTsconfig } from 'rolldown/experimental'\nimport { TsconfigCache } from 'rolldown/utils'\nimport type {\n  EsbuildLoader,\n  EsbuildMessage,\n  EsbuildTransformOptions,\n  EsbuildTransformResult as RawEsbuildTransformResult,\n} from '#types/internal/esbuildOptions'\nimport type { FSWatcher } from '#dep-types/chokidar'\nimport {\n  combineSourcemaps,\n  createDebugger,\n  createFilter,\n  ensureWatchedFile,\n  generateCodeFrame,\n} from '../utils'\nimport type { ViteDevServer } from '../server'\nimport type { ResolvedConfig } from '../config'\nimport type { Plugin } from '../plugin'\nimport { cleanUrl } from '../../shared/utils'\n\nconst debug = createDebugger('vite:esbuild')\n\n// IIFE content looks like `var MyLib = function() {`.\n// Spaces are removed and parameters are mangled when minified\nconst IIFE_BEGIN_RE =\n  /(?:const|var)\\s+\\S+\\s*=\\s*\\(?function\\([^()]*\\)\\s*\\{\\s*\"use strict\";/\n\nconst validExtensionRE = /\\.\\w+$/\nconst jsxExtensionsRE = /\\.(?:j|t)sx\\b/\n\n// the final build should always support dynamic import and import.meta.\n// if they need to be polyfilled, plugin-legacy should be used.\n// plugin-legacy detects these two features when checking for modern code.\n// Browser support: https://caniuse.com/es6-module-dynamic-import,mdn-javascript_operators_import_meta#:~:text=Feature%20summary\nexport const defaultEsbuildSupported = {\n  'dynamic-import': true,\n  'import-meta': true,\n}\n\nexport interface ESBuildOptions extends EsbuildTransformOptions {\n  include?: string | RegExp | ReadonlyArray<string | RegExp>\n  exclude?: string | RegExp | ReadonlyArray<string | RegExp>\n  jsxInject?: string\n  /**\n   * This option is not respected. Use `build.minify` instead.\n   */\n  minify?: never\n}\n\nexport type ESBuildTransformResult = Omit<RawEsbuildTransformResult, 'map'> & {\n  map: SourceMap\n}\n\ntype TSConfigJSON = {\n  extends?: string\n  compilerOptions?: {\n    alwaysStrict?: boolean\n    experimentalDecorators?: boolean\n    importsNotUsedAsValues?: 'remove' | 'preserve' | 'error'\n    jsx?: 'preserve' | 'react' | 'react-jsx' | 'react-jsxdev'\n    jsxFactory?: string\n    jsxFragmentFactory?: string\n    jsxImportSource?: string\n    preserveValueImports?: boolean\n    target?: string\n    useDefineForClassFields?: boolean\n    emitDecoratorMetadata?: boolean\n    verbatimModuleSyntax?: boolean\n  }\n  [key: string]: any\n}\nexport type TSCompilerOptions = NonNullable<TSConfigJSON['compilerOptions']>\n\nlet esbuild: Promise<typeof import('esbuild')> | undefined\nconst importEsbuild = () => {\n  esbuild ||= import('esbuild')\n  return esbuild\n}\n\nlet warnedTransformWithEsbuild = false\nconst warnTransformWithEsbuildUsageOnce = () => {\n  if (warnedTransformWithEsbuild) return\n  warnedTransformWithEsbuild = true\n\n  // eslint-disable-next-line no-console -- logger cannot be used here\n  console.warn(\n    colors.yellow(\n      '`transformWithEsbuild` is deprecated and will be removed in the future. ' +\n        'Please migrate to `transformWithOxc`.',\n    ),\n  )\n}\n\nexport async function transformWithEsbuild(\n  code: string,\n  filename: string,\n  options?: EsbuildTransformOptions,\n  inMap?: object,\n  config?: ResolvedConfig,\n  watcher?: FSWatcher,\n  /** @internal */\n  ignoreEsbuildWarning = false,\n): Promise<ESBuildTransformResult> {\n  let loader = options?.loader\n\n  if (!loader) {\n    // if the id ends with a valid ext, use it (e.g. vue blocks)\n    // otherwise, cleanup the query before checking the ext\n    const ext = path\n      .extname(validExtensionRE.test(filename) ? filename : cleanUrl(filename))\n      .slice(1)\n\n    if (ext === 'cjs' || ext === 'mjs') {\n      loader = 'js'\n    } else if (ext === 'cts' || ext === 'mts') {\n      loader = 'ts'\n    } else {\n      loader = ext as EsbuildLoader\n    }\n  }\n\n  let tsconfigRaw = options?.tsconfigRaw\n\n  // if options provide tsconfigRaw in string, it takes highest precedence\n  if (typeof tsconfigRaw !== 'string') {\n    // these fields would affect the compilation result\n    // https://esbuild.github.io/content-types/#tsconfig-json\n    const meaningfulFields: Array<keyof TSCompilerOptions> = [\n      'alwaysStrict',\n      'experimentalDecorators',\n      'importsNotUsedAsValues',\n      'jsx',\n      'jsxFactory',\n      'jsxFragmentFactory',\n      'jsxImportSource',\n      'preserveValueImports',\n      'target',\n      'useDefineForClassFields',\n      'verbatimModuleSyntax',\n    ]\n    const compilerOptionsForFile: TSCompilerOptions = {}\n    if (loader === 'ts' || loader === 'tsx') {\n      const result = resolveTsconfig(\n        filename,\n        getTSConfigResolutionCache(config),\n      )\n      if (result) {\n        const { tsconfig: loadedTsconfig, tsconfigFilePaths } = result\n        // tsconfig could be out of root, make sure it is watched on dev\n        if (watcher && config) {\n          for (const tsconfigFile of tsconfigFilePaths) {\n            ensureWatchedFile(watcher, tsconfigFile, config.root)\n          }\n        }\n\n        const loadedCompilerOptions = loadedTsconfig.compilerOptions ?? {}\n\n        for (const field of meaningfulFields) {\n          if (field in loadedCompilerOptions) {\n            // @ts-expect-error TypeScript can't tell they are of the same type\n            compilerOptionsForFile[field] = loadedCompilerOptions[field]\n          }\n        }\n      }\n    }\n\n    const compilerOptions = {\n      ...compilerOptionsForFile,\n      ...tsconfigRaw?.compilerOptions,\n    }\n\n    // esbuild uses `useDefineForClassFields: true` when `tsconfig.compilerOptions.target` isn't declared\n    // but we want `useDefineForClassFields: false` when `tsconfig.compilerOptions.target` isn't declared\n    // to align with the TypeScript's behavior\n    if (\n      compilerOptions.useDefineForClassFields === undefined &&\n      compilerOptions.target === undefined\n    ) {\n      compilerOptions.useDefineForClassFields = false\n    }\n\n    // esbuild uses tsconfig fields when both the normal options and tsconfig was set\n    // but we want to prioritize the normal options\n    if (options) {\n      if (options.jsx) compilerOptions.jsx = undefined\n      if (options.jsxFactory) compilerOptions.jsxFactory = undefined\n      if (options.jsxFragment) compilerOptions.jsxFragmentFactory = undefined\n      if (options.jsxImportSource) compilerOptions.jsxImportSource = undefined\n    }\n\n    tsconfigRaw = {\n      ...tsconfigRaw,\n      compilerOptions,\n    }\n  }\n\n  const resolvedOptions: EsbuildTransformOptions = {\n    sourcemap: true,\n    // ensure source file name contains full query\n    sourcefile: filename,\n    ...options,\n    loader,\n    tsconfigRaw,\n  }\n\n  // Some projects in the ecosystem are calling this function with an ESBuildOptions\n  // object and esbuild throws an error for extra fields\n  // @ts-expect-error include exists in ESBuildOptions\n  delete resolvedOptions.include\n  // @ts-expect-error exclude exists in ESBuildOptions\n  delete resolvedOptions.exclude\n  // @ts-expect-error jsxInject exists in ESBuildOptions\n  delete resolvedOptions.jsxInject\n\n  let transform: typeof import('esbuild').transform\n  try {\n    transform = (await importEsbuild()).transform\n  } catch (e) {\n    throw new Error(\n      'Failed to load `transformWithEsbuild`. ' +\n        'It is deprecated and it now requires esbuild to be installed separately. ' +\n        'If you are a package author, please migrate to `transformWithOxc` instead.',\n      { cause: e },\n    )\n  }\n\n  if (!ignoreEsbuildWarning) {\n    warnTransformWithEsbuildUsageOnce()\n  }\n\n  try {\n    const result = await transform(code, resolvedOptions)\n    let map: SourceMap\n    if (inMap && resolvedOptions.sourcemap) {\n      const nextMap = JSON.parse(result.map)\n      nextMap.sourcesContent = []\n      map = combineSourcemaps(filename, [\n        nextMap as RawSourceMap,\n        inMap as RawSourceMap,\n      ]) as SourceMap\n    } else {\n      map =\n        resolvedOptions.sourcemap && resolvedOptions.sourcemap !== 'inline'\n          ? JSON.parse(result.map)\n          : { mappings: '' }\n    }\n    return {\n      ...result,\n      map,\n    }\n  } catch (e: any) {\n    debug?.(`esbuild error with options used: `, resolvedOptions)\n    // patch error information\n    if (e.errors) {\n      e.frame = ''\n      e.errors.forEach((m: EsbuildMessage) => {\n        if (\n          m.text === 'Experimental decorators are not currently enabled' ||\n          m.text ===\n            'Parameter decorators only work when experimental decorators are enabled'\n        ) {\n          m.text +=\n            '. Vite 5 now uses esbuild 0.18 and you need to enable them by adding \"experimentalDecorators\": true in your \"tsconfig.json\" file.'\n        }\n        e.frame += `\\n` + prettifyMessage(m, code)\n      })\n      e.loc = e.errors[0].location\n    }\n    throw e\n  }\n}\n\nexport function esbuildPlugin(config: ResolvedConfig): Plugin {\n  const options = config.esbuild as ESBuildOptions\n  const { jsxInject, include, exclude, ...esbuildTransformOptions } = options\n\n  const filter = createFilter(include || /\\.(m?ts|[jt]sx)$/, exclude || /\\.js$/)\n\n  // Remove optimization options for dev as we only need to transpile them,\n  // and for build as the final optimization is in `buildEsbuildPlugin`\n  const transformOptions: EsbuildTransformOptions = {\n    target: 'esnext',\n    ...esbuildTransformOptions,\n    minify: false,\n    minifyIdentifiers: false,\n    minifySyntax: false,\n    minifyWhitespace: false,\n    treeShaking: false,\n    // keepNames is not needed when minify is disabled.\n    // Also transforming multiple times with keepNames enabled breaks\n    // tree-shaking. (#9164)\n    keepNames: false,\n    supported: {\n      ...defaultEsbuildSupported,\n      ...esbuildTransformOptions.supported,\n    },\n  }\n\n  let server: ViteDevServer | undefined\n\n  return {\n    name: 'vite:esbuild',\n    configureServer(_server) {\n      server = _server\n    },\n    async transform(code, id) {\n      if (filter(id) || filter(cleanUrl(id))) {\n        const result = await transformWithEsbuild(\n          code,\n          id,\n          transformOptions,\n          undefined,\n          config,\n          server?.watcher,\n        )\n        if (result.warnings.length) {\n          result.warnings.forEach((m) => {\n            this.warn(prettifyMessage(m, code))\n          })\n        }\n        if (jsxInject && jsxExtensionsRE.test(id)) {\n          result.code = jsxInject + ';' + result.code\n        }\n        return {\n          code: result.code,\n          map: result.map,\n          moduleType: 'js',\n        }\n      }\n    },\n  }\n}\n\nconst rollupToEsbuildFormatMap: Record<\n  string,\n  EsbuildTransformOptions['format'] | undefined\n> = {\n  es: 'esm',\n  cjs: 'cjs',\n\n  // passing `var Lib = (() => {})()` to esbuild with format = \"iife\"\n  // will turn it to `(() => { var Lib = (() => {})() })()`,\n  // so we remove the format config to tell esbuild not doing this\n  //\n  // although esbuild doesn't change format, there is still possibility\n  // that `{ treeShaking: true }` removes a top-level no-side-effect variable\n  // like: `var Lib = 1`, which becomes `` after esbuild transforming,\n  // but thankfully rollup does not do this optimization now\n  iife: undefined,\n}\n\n// #7188, esbuild adds helpers out of the UMD and IIFE wrappers, and the\n// names are minified potentially causing collision with other globals.\n// We inject the helpers inside the wrappers.\n// e.g. turn:\n//    <esbuild helpers> (function(){ /*actual content/* })()\n// into:\n//    (function(){ <esbuild helpers> /*actual content/* })()\n// Not using regex because it's too hard to rule out performance issues like #8738 #8099 #10900 #14065\n// Instead, using plain string index manipulation (indexOf, slice) which is simple and performant\n// We don't need to create a MagicString here because both the helpers and\n// the headers don't modify the sourcemap\nexport const injectEsbuildHelpers = (\n  esbuildCode: string,\n  format: string,\n): string => {\n  const contentIndex =\n    format === 'iife'\n      ? Math.max(esbuildCode.search(IIFE_BEGIN_RE), 0)\n      : format === 'umd'\n        ? esbuildCode.indexOf(`(function(`) // same for minified or not\n        : 0\n\n  if (contentIndex > 0) {\n    const esbuildHelpers = esbuildCode.slice(0, contentIndex)\n    return esbuildCode\n      .slice(contentIndex)\n      .replace('\"use strict\";', (m: string) => m + esbuildHelpers)\n  }\n  return esbuildCode\n}\n\nexport const buildEsbuildPlugin = (): Plugin => {\n  return {\n    name: 'vite:esbuild-transpile',\n    applyToEnvironment(environment) {\n      return environment.config.esbuild !== false\n    },\n    async renderChunk(code, chunk, opts) {\n      // avoid on legacy chunks since it produces legacy-unsafe code\n      // e.g. rewriting object properties into shorthands\n      if (this.environment.config.isOutputOptionsForLegacyChunks?.(opts)) {\n        return null\n      }\n\n      const config = this.environment.config\n      const options = resolveEsbuildTranspileOptions(config, opts.format)\n\n      if (!options) {\n        return null\n      }\n\n      const res = await transformWithEsbuild(\n        code,\n        chunk.fileName,\n        options,\n        undefined,\n        config,\n        undefined,\n        true,\n      )\n\n      if (config.build.lib) {\n        res.code = injectEsbuildHelpers(res.code, opts.format)\n      }\n\n      return res\n    },\n  }\n}\n\nexport function resolveEsbuildTranspileOptions(\n  config: ResolvedConfig,\n  format: InternalModuleFormat,\n): EsbuildTransformOptions | null {\n  const target = config.build.target\n  const minify = config.build.minify === 'esbuild'\n\n  if ((!target || target === 'esnext') && !minify) {\n    return null\n  }\n\n  // Do not minify whitespace for ES lib output since that would remove\n  // pure annotations and break tree-shaking\n  // https://github.com/vuejs/core/issues/2860#issuecomment-926882793\n  const isEsLibBuild = config.build.lib && format === 'es'\n  const esbuildOptions = config.esbuild || {}\n\n  const options: EsbuildTransformOptions = {\n    ...esbuildOptions,\n    loader: 'js',\n    target: target || undefined,\n    format: rollupToEsbuildFormatMap[format],\n    supported: {\n      ...defaultEsbuildSupported,\n      ...esbuildOptions.supported,\n    },\n  }\n\n  // If no minify, disable all minify options\n  if (!minify) {\n    return {\n      ...options,\n      minify: false,\n      minifyIdentifiers: false,\n      minifySyntax: false,\n      minifyWhitespace: false,\n      treeShaking: false,\n    }\n  }\n\n  // If user enable fine-grain minify options, minify with their options instead\n  if (\n    options.minifyIdentifiers != null ||\n    options.minifySyntax != null ||\n    options.minifyWhitespace != null\n  ) {\n    if (isEsLibBuild) {\n      // Disable minify whitespace as it breaks tree-shaking\n      return {\n        ...options,\n        minify: false,\n        minifyIdentifiers: options.minifyIdentifiers ?? true,\n        minifySyntax: options.minifySyntax ?? true,\n        minifyWhitespace: false,\n        treeShaking: true,\n      }\n    } else {\n      return {\n        ...options,\n        minify: false,\n        minifyIdentifiers: options.minifyIdentifiers ?? true,\n        minifySyntax: options.minifySyntax ?? true,\n        minifyWhitespace: options.minifyWhitespace ?? true,\n        treeShaking: true,\n      }\n    }\n  }\n\n  // Else apply default minify options\n  if (isEsLibBuild) {\n    // Minify all except whitespace as it breaks tree-shaking\n    return {\n      ...options,\n      minify: false,\n      minifyIdentifiers: true,\n      minifySyntax: true,\n      minifyWhitespace: false,\n      treeShaking: true,\n    }\n  } else {\n    return {\n      ...options,\n      minify: true,\n      treeShaking: true,\n    }\n  }\n}\n\nfunction prettifyMessage(m: EsbuildMessage, code: string): string {\n  let res = colors.yellow(m.text)\n  if (m.location) {\n    res += `\\n` + generateCodeFrame(code, m.location)\n  }\n  return res + `\\n`\n}\n\nlet globalTSConfigResolutionCache: TsconfigCache | undefined\nconst tsconfigResolutionCacheMap = new WeakMap<ResolvedConfig, TsconfigCache>()\n\nexport function getTSConfigResolutionCache(\n  config?: ResolvedConfig,\n): TsconfigCache {\n  if (!config) {\n    return (globalTSConfigResolutionCache ??= new TsconfigCache())\n  }\n  let cache = tsconfigResolutionCacheMap.get(config)\n  if (!cache) {\n    cache = new TsconfigCache()\n    tsconfigResolutionCacheMap.set(config, cache)\n  }\n  return cache\n}\n\nexport async function reloadOnTsconfigChange(\n  server: ViteDevServer,\n  changedFile: string,\n): Promise<void> {\n  // any tsconfig.json that's added in the workspace could be closer to a code file than a previously cached one\n  // any json file in the tsconfig cache could have been used to compile ts\n  if (changedFile.endsWith('.json')) {\n    const cache = getTSConfigResolutionCache(server.config)\n    if (changedFile.endsWith('/tsconfig.json')) {\n      server.config.logger.info(\n        `changed tsconfig file detected: ${changedFile} - Clearing cache and forcing full-reload to ensure TypeScript is compiled with updated config values.`,\n        { clear: server.config.clearScreen, timestamp: true },\n      )\n\n      // TODO: more finegrained invalidation than the nuclear option below\n\n      // clear module graph to remove code compiled with outdated config\n      for (const environment of Object.values(server.environments)) {\n        environment.moduleGraph.invalidateAll()\n      }\n\n      // reset the cache so that recompile works with up2date configs\n      cache.clear()\n\n      // reload environments\n      for (const environment of Object.values(server.environments)) {\n        environment.hot.send({\n          type: 'full-reload',\n          path: '*',\n        })\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/esbuildBannerFooterCompatPlugin.ts",
    "content": "import MagicString from 'magic-string'\nimport type { Plugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport { createFilter } from '../utils'\nimport { cleanUrl } from '../../shared/utils'\n\n/**\n * This plugin supports `esbuild.banner` and `esbuild.footer` options.\n * esbuild supported these options and Vite exposed them.\n * But this should be done by plugin with transform hook.\n * This plugin makes these options work in rolldown-vite as a backward compat for now.\n */\nexport function esbuildBannerFooterCompatPlugin(\n  config: ResolvedConfig,\n): Plugin | undefined {\n  const options = config.esbuild\n  if (!options) return\n\n  const { include, exclude, banner, footer } = options\n  if (!banner && !footer) return\n\n  const filter = createFilter(include || /\\.(m?ts|[jt]sx)$/, exclude || /\\.js$/)\n\n  return {\n    name: 'vite:esbuild-banner-footer-compat',\n    transform(code, id) {\n      if (filter(id) || filter(cleanUrl(id))) {\n        const needsSourcemap =\n          this.environment.mode === 'dev' ||\n          (this.environment.mode === 'build' &&\n            this.environment.config.build.sourcemap)\n        if (!needsSourcemap) {\n          if (banner) {\n            code = `${banner}\\n${code}`\n          }\n          if (footer) {\n            code = `${code}\\n${footer}`\n          }\n          return code\n        }\n\n        let s: MagicString | undefined\n        const str = () => s || (s = new MagicString(code))\n\n        if (banner) {\n          str().prepend(`${banner}\\n`)\n        }\n        if (footer) {\n          str().append(`${footer}\\n`)\n        }\n\n        if (s) {\n          return {\n            code: s.toString(),\n            map: s.generateMap({ hires: 'boundary' }),\n          }\n        }\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/forwardConsole.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport { parseErrorStacktrace } from '@vitest/utils/source-map'\nimport c from 'picocolors'\nimport type { ForwardConsolePayload } from '#types/customEvent'\nimport type { DevEnvironment, Plugin } from '..'\nimport { normalizePath } from '..'\nimport { extractSourcemapFromFile } from '../server/sourcemap'\nimport { generateCodeFrame } from '../utils'\n\nexport function forwardConsolePlugin(pluginOpts: {\n  environments: string[]\n}): Plugin {\n  const sourceMapCache = new Map<string, any>()\n\n  return {\n    name: 'vite:forward-console',\n    apply: 'serve',\n    configureServer(server) {\n      for (const name of pluginOpts.environments) {\n        const environment = server.environments[name]\n        environment.hot.on('vite:forward-console', (payload) => {\n          if (\n            payload.type === 'error' ||\n            payload.type === 'unhandled-rejection'\n          ) {\n            const output = formatError(payload, environment, sourceMapCache)\n            environment.config.logger.error(output, {\n              timestamp: true,\n            })\n          } else {\n            const output =\n              c.dim(`[console.${payload.data.level}] `) + payload.data.message\n            if (payload.data.level === 'error') {\n              environment.config.logger.error(output, {\n                timestamp: true,\n              })\n            } else if (payload.data.level === 'warn') {\n              environment.config.logger.warn(output, {\n                timestamp: true,\n              })\n            } else {\n              environment.config.logger.info(output, {\n                timestamp: true,\n              })\n            }\n          }\n        })\n      }\n    },\n  }\n}\n\nfunction formatError(\n  payload: Extract<\n    ForwardConsolePayload,\n    { type: 'error' | 'unhandled-rejection' }\n  >,\n  environment: DevEnvironment,\n  sourceMapCache: Map<string, any>,\n) {\n  const error = payload.data\n  const stacks = parseErrorStacktrace(error, {\n    getUrlId(id) {\n      const moduleGraph = environment.moduleGraph\n      const mod = moduleGraph.getModuleById(id)\n      if (mod) {\n        return id\n      }\n      const resolvedPath = normalizePath(\n        path.resolve(environment.config.root, id.slice(1)),\n      )\n      const modUrl = moduleGraph.getModuleById(resolvedPath)\n      if (modUrl) {\n        return resolvedPath\n      }\n      // some browsers (looking at you, safari) don't report queries in stack traces\n      // the next best thing is to try the first id that this file resolves to\n      const files = moduleGraph.getModulesByFile(resolvedPath)\n      if (files && files.size) {\n        return files.values().next().value!.id!\n      }\n      return id\n    },\n    getSourceMap(id) {\n      if (sourceMapCache.has(id)) {\n        return sourceMapCache.get(id)\n      }\n\n      const result = environment.moduleGraph.getModuleById(id)?.transformResult\n      // handle non-inline source map such as pre-bundled deps in node_modules/.vite\n      if (result && !result.map) {\n        try {\n          const filePath = id.split('?')[0]\n          const extracted = extractSourcemapFromFile(result.code, filePath)\n          sourceMapCache.set(id, extracted?.map)\n          return extracted?.map\n        } catch {\n          sourceMapCache.set(id, null)\n          return null\n        }\n      }\n\n      sourceMapCache.set(id, result?.map)\n      return result?.map\n    },\n    // override it to empty since vitest uses this option to skip internal files by default.\n    // https://github.com/vitest-dev/vitest/blob/4783137cd8d766cf998bdf2d638890eaa51e08d9/packages/utils/src/source-map.ts#L17\n    ignoreStackEntries: [],\n  })\n\n  const nearest = stacks.find((stack) => {\n    const modules = environment.moduleGraph.getModulesByFile(stack.file)\n    return (\n      [...(modules || [])].some((m) => m.transformResult) &&\n      fs.existsSync(stack.file)\n    )\n  })\n\n  let output = ''\n  const title =\n    payload.type === 'unhandled-rejection'\n      ? '[Unhandled rejection]'\n      : '[Unhandled error]'\n  output += c.red(`${title} ${c.bold(error.name)}: ${error.message}\\n`)\n  for (const stack of stacks) {\n    const file = normalizePath(\n      path.relative(environment.config.root, stack.file),\n    )\n    output += ` > ${[stack.method, `${file}:${stack.line}:${stack.column}`]\n      .filter(Boolean)\n      .join(' ')}\\n`\n    if (stack === nearest) {\n      const code = fs.readFileSync(stack.file, 'utf-8')\n      output += generateCodeFrame(code, stack).replace(/^/gm, '    ')\n      output += '\\n'\n    }\n  }\n  return output\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/html.ts",
    "content": "import path from 'node:path'\nimport { URL } from 'node:url'\nimport type {\n  OutputAsset,\n  OutputBundle,\n  OutputChunk,\n  RollupError,\n  SourceMapInput,\n} from 'rolldown'\nimport MagicString from 'magic-string'\nimport colors from 'picocolors'\nimport type {\n  DefaultTreeAdapterMap,\n  ErrorCodes,\n  ParserError,\n  Token,\n} from 'parse5'\nimport { stripLiteral } from 'strip-literal'\nimport escapeHtml from 'escape-html'\nimport type { MinimalPluginContextWithoutEnvironment, Plugin } from '../plugin'\nimport type { ViteDevServer } from '../server'\nimport {\n  decodeURIIfPossible,\n  encodeURIPath,\n  generateCodeFrame,\n  getHash,\n  isCSSRequest,\n  isDataUrl,\n  isExternalUrl,\n  normalizePath,\n  partialEncodeURIPath,\n  processSrcSet,\n  removeLeadingSlash,\n  unique,\n} from '../utils'\nimport type { ResolvedConfig } from '../config'\nimport { checkPublicFile } from '../publicDir'\nimport { toOutputFilePathInHtml } from '../build'\nimport { resolveEnvPrefix } from '../env'\nimport { cleanUrl } from '../../shared/utils'\nimport { perEnvironmentState } from '../environment'\nimport { getNodeAssetAttributes } from '../assetSource'\nimport type { Logger } from '../logger'\nimport {\n  assetUrlRE,\n  getPublicAssetFilename,\n  publicAssetUrlRE,\n  urlToBuiltUrl,\n} from './asset'\nimport { cssBundleNameCache } from './css'\nimport { modulePreloadPolyfillId } from './modulePreloadPolyfill'\n\ninterface ScriptAssetsUrl {\n  start: number\n  end: number\n  url: string\n}\n\nconst htmlProxyRE =\n  /[?&]html-proxy=?(?:&inline-css)?(?:&style-attr)?&index=(\\d+)\\.(?:js|css)$/\nconst isHtmlProxyRE = /[?&]html-proxy\\b/\n\nconst inlineCSSRE = /__VITE_INLINE_CSS__([a-z\\d]{8}_\\d+)__/g\n// Do not allow preceding '.', but do allow preceding '...' for spread operations\nconst inlineImportRE =\n  /(?<!(?<!\\.\\.)\\.)\\bimport\\s*\\((\"(?:[^\"]|(?<=\\\\)\")*\"|'(?:[^']|(?<=\\\\)')*')\\)/dg\nconst htmlLangRE = /\\.(?:html|htm)$/\nconst spaceRe = /[\\t\\n\\f\\r ]/\n\nconst importMapRE =\n  /[ \\t]*<script[^>]*type\\s*=\\s*(?:\"importmap\"|'importmap'|importmap)[^>]*>.*?<\\/script>/is\nconst moduleScriptRE =\n  /[ \\t]*<script[^>]*type\\s*=\\s*(?:\"module\"|'module'|module)[^>]*>/i\nconst modulePreloadLinkRE =\n  /[ \\t]*<link[^>]*rel\\s*=\\s*(?:\"modulepreload\"|'modulepreload'|modulepreload)[\\s\\S]*?\\/>/i\nconst importMapAppendRE = new RegExp(\n  [moduleScriptRE, modulePreloadLinkRE].map((r) => r.source).join('|'),\n  'i',\n)\n\nexport const isHTMLProxy = (id: string): boolean => isHtmlProxyRE.test(id)\n\nexport const isHTMLRequest = (request: string): boolean =>\n  htmlLangRE.test(request)\n\n// HTML Proxy Caches are stored by config -> filePath -> index\nexport const htmlProxyMap: WeakMap<\n  ResolvedConfig,\n  Map<\n    string,\n    {\n      code: string\n      map?: SourceMapInput\n    }[]\n  >\n> = new WeakMap()\n\n// HTML Proxy Transform result are stored by config\n// `${hash(importer)}_${query.index}` -> transformed css code\n// PS: key like `hash(/vite/playground/assets/index.html)_1`)\nexport const htmlProxyResult: Map<string, string> = new Map()\n\nexport function htmlInlineProxyPlugin(config: ResolvedConfig): Plugin {\n  // Should do this when `constructor` rather than when `buildStart`,\n  // `buildStart` will be triggered multiple times then the cached result will be emptied.\n  // https://github.com/vitejs/vite/issues/6372\n  htmlProxyMap.set(config, new Map())\n  return {\n    name: 'vite:html-inline-proxy',\n\n    resolveId: {\n      filter: { id: isHtmlProxyRE },\n      handler(id) {\n        return id\n      },\n    },\n\n    load: {\n      filter: { id: isHtmlProxyRE },\n      handler(id) {\n        const proxyMatch = htmlProxyRE.exec(id)\n        if (proxyMatch) {\n          const index = Number(proxyMatch[1])\n          const file = cleanUrl(id)\n          const url = file.replace(normalizePath(config.root), '')\n          const result = htmlProxyMap.get(config)!.get(url)?.[index]\n          if (result) {\n            // set moduleSideEffects to keep the module even if `treeshake.moduleSideEffects=false` is set\n            return { ...result, moduleSideEffects: true }\n          } else {\n            throw new Error(`No matching HTML proxy module found from ${id}`)\n          }\n        }\n      },\n    },\n  }\n}\n\nexport function addToHTMLProxyCache(\n  config: ResolvedConfig,\n  filePath: string,\n  index: number,\n  result: { code: string; map?: SourceMapInput },\n): void {\n  if (!htmlProxyMap.get(config)) {\n    htmlProxyMap.set(config, new Map())\n  }\n  if (!htmlProxyMap.get(config)!.get(filePath)) {\n    htmlProxyMap.get(config)!.set(filePath, [])\n  }\n  htmlProxyMap.get(config)!.get(filePath)![index] = result\n}\n\nexport function addToHTMLProxyTransformResult(\n  hash: string,\n  code: string,\n): void {\n  htmlProxyResult.set(hash, code)\n}\n\n// Some `<link rel>` elements should not be inlined in build. Excluding:\n// - `shortcut`                     : only valid for IE <9, use `icon`\n// - `mask-icon`                    : deprecated since Safari 12 (for pinned tabs)\n// - `apple-touch-icon-precomposed` : only valid for iOS <7 (for avoiding gloss effect)\nconst noInlineLinkRels = new Set([\n  'icon',\n  'apple-touch-icon',\n  'apple-touch-startup-image',\n  'manifest',\n])\n\nexport const isAsyncScriptMap: WeakMap<\n  ResolvedConfig,\n  Map<string, boolean>\n> = new WeakMap()\n\nexport function nodeIsElement(\n  node: DefaultTreeAdapterMap['node'],\n): node is DefaultTreeAdapterMap['element'] {\n  return node.nodeName[0] !== '#'\n}\n\nfunction traverseNodes(\n  node: DefaultTreeAdapterMap['node'],\n  visitor: (node: DefaultTreeAdapterMap['node']) => void,\n) {\n  if (node.nodeName === 'template') {\n    node = (node as DefaultTreeAdapterMap['template']).content\n  }\n  visitor(node)\n  if (\n    nodeIsElement(node) ||\n    node.nodeName === '#document' ||\n    node.nodeName === '#document-fragment'\n  ) {\n    node.childNodes.forEach((childNode) => traverseNodes(childNode, visitor))\n  }\n}\n\ntype ParseWarnings = Partial<Record<ErrorCodes, string>>\n\nexport async function traverseHtml(\n  html: string,\n  filePath: string,\n  warn: Logger['warn'],\n  visitor: (node: DefaultTreeAdapterMap['node']) => void,\n): Promise<void> {\n  // lazy load compiler\n  const { parse } = await import('parse5')\n  const warnings: ParseWarnings = {}\n  const ast = parse(html, {\n    scriptingEnabled: false, // parse inside <noscript>\n    sourceCodeLocationInfo: true,\n    onParseError: (e: ParserError) => {\n      handleParseError(e, html, filePath, warnings)\n    },\n  })\n  traverseNodes(ast, visitor)\n\n  for (const message of Object.values(warnings)) {\n    warn(colors.yellow(`\\n${message}`))\n  }\n}\n\nexport function getScriptInfo(node: DefaultTreeAdapterMap['element']): {\n  src: Token.Attribute | undefined\n  srcSourceCodeLocation: Token.Location | undefined\n  isModule: boolean\n  isAsync: boolean\n  isIgnored: boolean\n} {\n  let src: Token.Attribute | undefined\n  let srcSourceCodeLocation: Token.Location | undefined\n  let isModule = false\n  let isAsync = false\n  let isIgnored = false\n  for (const p of node.attrs) {\n    if (p.prefix !== undefined) continue\n    if (p.name === 'src') {\n      if (!src) {\n        src = p\n        srcSourceCodeLocation = node.sourceCodeLocation?.attrs!['src']\n      }\n    } else if (p.name === 'type' && p.value === 'module') {\n      isModule = true\n    } else if (p.name === 'async') {\n      isAsync = true\n    } else if (p.name === 'vite-ignore') {\n      isIgnored = true\n    }\n  }\n  return { src, srcSourceCodeLocation, isModule, isAsync, isIgnored }\n}\n\nconst attrValueStartRE = /=\\s*(.)/\n\nexport function overwriteAttrValue(\n  s: MagicString,\n  sourceCodeLocation: Token.Location,\n  newValue: string,\n): MagicString {\n  const srcString = s.slice(\n    sourceCodeLocation.startOffset,\n    sourceCodeLocation.endOffset,\n  )\n  const valueStart = attrValueStartRE.exec(srcString)\n  if (!valueStart) {\n    // overwrite attr value can only be called for a well-defined value\n    throw new Error(\n      `[vite:html] internal error, failed to overwrite attribute value`,\n    )\n  }\n  const wrapOffset = valueStart[1] === '\"' || valueStart[1] === \"'\" ? 1 : 0\n  const valueOffset = valueStart.index! + valueStart[0].length - 1\n  s.update(\n    sourceCodeLocation.startOffset + valueOffset + wrapOffset,\n    sourceCodeLocation.endOffset - wrapOffset,\n    newValue,\n  )\n  return s\n}\n\nexport function removeViteIgnoreAttr(\n  s: MagicString,\n  sourceCodeLocation: Token.Location,\n): MagicString {\n  const loc = (sourceCodeLocation as Token.LocationWithAttributes).attrs?.[\n    'vite-ignore'\n  ]\n  if (loc) {\n    s.remove(loc.startOffset, loc.endOffset)\n  }\n  return s\n}\n\n/**\n * Format parse5 @type {ParserError} to @type {RollupError}\n */\nfunction formatParseError(parserError: ParserError, id: string, html: string) {\n  const formattedError = {\n    code: parserError.code,\n    message: `parse5 error code ${parserError.code}`,\n    frame: generateCodeFrame(\n      html,\n      parserError.startOffset,\n      parserError.endOffset,\n    ),\n    loc: {\n      file: id,\n      line: parserError.startLine,\n      column: parserError.startCol,\n    },\n  } satisfies RollupError\n  return formattedError\n}\n\nfunction handleParseError(\n  parserError: ParserError,\n  html: string,\n  filePath: string,\n  warnings: ParseWarnings,\n) {\n  switch (parserError.code) {\n    case 'missing-doctype':\n      // ignore missing DOCTYPE\n      return\n    case 'abandoned-head-element-child':\n      // Accept elements without closing tag in <head>\n      return\n    case 'duplicate-attribute':\n      // Accept duplicate attributes #5966\n      // The first attribute is used, browsers silently ignore duplicates\n      return\n    case 'non-void-html-element-start-tag-with-trailing-solidus':\n      // Allow self closing on non-void elements #10439\n      return\n    case 'unexpected-question-mark-instead-of-tag-name':\n      // Allow <?xml> declaration and <?> empty elements\n      // lit generates <?>: https://github.com/lit/lit/issues/2470\n      return\n  }\n  const parseError = formatParseError(parserError, filePath, html)\n  warnings[parseError.code] ??=\n    `Unable to parse HTML; ${parseError.message}\\n` +\n    ` at ${parseError.loc.file}:${parseError.loc.line}:${parseError.loc.column}\\n` +\n    parseError.frame\n}\n\n/**\n * Compiles index.html into an entry js module\n */\nexport function buildHtmlPlugin(config: ResolvedConfig): Plugin {\n  const [preHooks, normalHooks, postHooks] = resolveHtmlTransforms(\n    config.plugins,\n  )\n  preHooks.unshift(injectCspNonceMetaTagHook(config))\n  preHooks.unshift(preImportMapHook(config))\n  preHooks.push(htmlEnvHook(config))\n  postHooks.push(injectNonceAttributeTagHook(config))\n  postHooks.push(postImportMapHook())\n  const processedHtml = perEnvironmentState(() => new Map<string, string>())\n\n  const isExcludedUrl = (url: string) =>\n    url[0] === '#' || isExternalUrl(url) || isDataUrl(url)\n\n  // Same reason with `htmlInlineProxyPlugin`\n  isAsyncScriptMap.set(config, new Map())\n\n  return {\n    name: 'vite:build-html',\n\n    transform: {\n      filter: { id: /\\.html$/ },\n      async handler(html, id) {\n        id = normalizePath(id)\n        const relativeUrlPath = normalizePath(path.relative(config.root, id))\n        const publicPath = `/${relativeUrlPath}`\n        const publicBase = getBaseInHTML(relativeUrlPath, config)\n\n        const publicToRelative = (filename: string) => publicBase + filename\n        const toOutputPublicFilePath = (url: string) =>\n          toOutputFilePathInHtml(\n            url.slice(1),\n            'public',\n            relativeUrlPath,\n            'html',\n            config,\n            publicToRelative,\n          )\n        // Determines true start position for the node, either the < character\n        // position, or the newline at the end of the previous line's node.\n        const nodeStartWithLeadingWhitespace = (\n          node: DefaultTreeAdapterMap['node'],\n        ) => {\n          const startOffset = node.sourceCodeLocation!.startOffset\n          if (startOffset === 0) return 0\n\n          // Gets the offset for the start of the line including the\n          // newline trailing the previous node\n          const lineStartOffset =\n            startOffset - node.sourceCodeLocation!.startCol\n\n          // <previous-line-node></previous-line-node>\n          // <target-node></target-node>\n          //\n          // Here we want to target the newline at the end of the previous line\n          // as the start position for our target.\n          //\n          // <previous-node></previous-node>\n          // <doubled-up-node></doubled-up-node><target-node></target-node>\n          //\n          // However, if there is content between our target node start and the\n          // previous newline, we cannot strip it out without risking content deletion.\n          let isLineEmpty = false\n          try {\n            const line = s.slice(Math.max(0, lineStartOffset), startOffset)\n            isLineEmpty = !line.trim()\n          } catch {\n            // magic-string may throw if there's some content removed in the sliced string,\n            // which we ignore and assume the line is not empty\n          }\n\n          return isLineEmpty ? lineStartOffset : startOffset\n        }\n\n        // pre-transform\n        html = await applyHtmlTransforms(html, preHooks, this, {\n          path: publicPath,\n          filename: id,\n        })\n\n        let js = ''\n        const s = new MagicString(html)\n        const scriptUrls: ScriptAssetsUrl[] = []\n        const styleUrls: ScriptAssetsUrl[] = []\n        let inlineModuleIndex = -1\n\n        let everyScriptIsAsync = true\n        let someScriptsAreAsync = false\n        let someScriptsAreDefer = false\n\n        const assetUrlsPromises: Promise<void>[] = []\n\n        // for each encountered asset url, rewrite original html so that it\n        // references the post-build location, ignoring empty attributes and\n        // attributes that directly reference named output.\n        const namedOutput = Object.keys(config.build.rollupOptions.input || {})\n        const processAssetUrl = async (url: string, shouldInline?: boolean) => {\n          if (\n            url !== '' && // Empty attribute\n            !namedOutput.includes(url) && // Direct reference to named output\n            !namedOutput.includes(removeLeadingSlash(url)) // Allow for absolute references as named output can't be an absolute path\n          ) {\n            try {\n              return await urlToBuiltUrl(this, url, id, shouldInline)\n            } catch (e) {\n              if (e.code !== 'ENOENT') {\n                throw e\n              }\n            }\n          }\n          return url\n        }\n\n        const setModuleSideEffectPromises: Promise<void>[] = []\n        await traverseHtml(html, id, config.logger.warn, (node) => {\n          if (!nodeIsElement(node)) {\n            return\n          }\n\n          let shouldRemove = false\n\n          // script tags\n          if (node.nodeName === 'script') {\n            const { src, srcSourceCodeLocation, isModule, isAsync, isIgnored } =\n              getScriptInfo(node)\n\n            if (isIgnored) {\n              removeViteIgnoreAttr(s, node.sourceCodeLocation!)\n            } else {\n              const url = src && src.value\n              const isPublicFile = !!(url && checkPublicFile(url, config))\n              if (isPublicFile) {\n                // referencing public dir url, prefix with base\n                overwriteAttrValue(\n                  s,\n                  srcSourceCodeLocation!,\n                  partialEncodeURIPath(toOutputPublicFilePath(url)),\n                )\n              }\n\n              if (isModule) {\n                inlineModuleIndex++\n                if (url && !isExcludedUrl(url) && !isPublicFile) {\n                  setModuleSideEffectPromises.push(\n                    this.resolve(url, id).then((resolved) => {\n                      if (!resolved) {\n                        return Promise.reject(\n                          new Error(`Failed to resolve ${url} from ${id}`),\n                        )\n                      }\n                      // set moduleSideEffects to keep the module even if `treeshake.moduleSideEffects=false` is set\n                      const moduleInfo = this.getModuleInfo(resolved.id)\n                      if (moduleInfo) {\n                        moduleInfo.moduleSideEffects = true\n                      } else if (!resolved.external) {\n                        return this.load({\n                          ...resolved,\n                          moduleSideEffects: true,\n                        }).then(() => {})\n                      }\n                    }),\n                  )\n                  // <script type=\"module\" src=\"...\"/>\n                  // add it as an import\n                  js += `\\nimport ${JSON.stringify(url)}`\n                  shouldRemove = true\n                } else if (node.childNodes.length) {\n                  const scriptNode =\n                    node.childNodes.pop() as DefaultTreeAdapterMap['textNode']\n                  const contents = scriptNode.value\n                  // <script type=\"module\">...</script>\n                  const filePath = id.replace(normalizePath(config.root), '')\n                  addToHTMLProxyCache(config, filePath, inlineModuleIndex, {\n                    code: contents,\n                  })\n                  js += `\\nimport \"${id}?html-proxy&index=${inlineModuleIndex}.js\"`\n                  shouldRemove = true\n                }\n\n                everyScriptIsAsync &&= isAsync\n                someScriptsAreAsync ||= isAsync\n                someScriptsAreDefer ||= !isAsync\n              } else if (url && !isPublicFile) {\n                if (!isExcludedUrl(url)) {\n                  config.logger.warn(\n                    `<script src=\"${url}\"> in \"${publicPath}\" can't be bundled without type=\"module\" attribute`,\n                  )\n                }\n              } else if (node.childNodes.length) {\n                const scriptNode =\n                  node.childNodes.pop() as DefaultTreeAdapterMap['textNode']\n                scriptUrls.push(\n                  ...extractImportExpressionFromClassicScript(scriptNode),\n                )\n              }\n            }\n          }\n\n          // For asset references in index.html, also generate an import\n          // statement for each - this will be handled by the asset plugin\n          const assetAttributes = getNodeAssetAttributes(node)\n          for (const attr of assetAttributes) {\n            if (attr.type === 'remove') {\n              s.remove(attr.location.startOffset, attr.location.endOffset)\n              continue\n            } else if (attr.type === 'srcset') {\n              assetUrlsPromises.push(\n                (async () => {\n                  const processedEncodedUrl = await processSrcSet(\n                    attr.value,\n                    async ({ url }) => {\n                      const decodedUrl = decodeURIIfPossible(url)\n                      if (\n                        decodedUrl !== undefined &&\n                        !isExcludedUrl(decodedUrl)\n                      ) {\n                        const result = await processAssetUrl(url)\n                        return result !== decodedUrl\n                          ? encodeURIPath(result)\n                          : url\n                      }\n                      return url\n                    },\n                  )\n                  if (processedEncodedUrl !== attr.value) {\n                    overwriteAttrValue(s, attr.location, processedEncodedUrl)\n                  }\n                })(),\n              )\n            } else if (attr.type === 'src') {\n              const url = decodeURIIfPossible(attr.value)\n              if (url === undefined) {\n                // ignore it\n              } else if (checkPublicFile(url, config)) {\n                overwriteAttrValue(\n                  s,\n                  attr.location,\n                  partialEncodeURIPath(toOutputPublicFilePath(url)),\n                )\n              } else if (!isExcludedUrl(url)) {\n                if (\n                  node.nodeName === 'link' &&\n                  isCSSRequest(url) &&\n                  // should not be converted if following attributes are present (#6748)\n                  !('media' in attr.attributes || 'disabled' in attr.attributes)\n                ) {\n                  // CSS references, convert to import\n                  const importExpression = `\\nimport ${JSON.stringify(url)}`\n                  styleUrls.push({\n                    url,\n                    start: nodeStartWithLeadingWhitespace(node),\n                    end: node.sourceCodeLocation!.endOffset,\n                  })\n                  js += importExpression\n                } else {\n                  // If the node is a link, check if it can be inlined. If not, set `shouldInline`\n                  // to `false` to force no inline. If `undefined`, it leaves to the default heuristics.\n                  const isNoInlineLink =\n                    node.nodeName === 'link' &&\n                    attr.attributes.rel &&\n                    parseRelAttr(attr.attributes.rel).some((v) =>\n                      noInlineLinkRels.has(v),\n                    )\n                  const shouldInline = isNoInlineLink ? false : undefined\n                  assetUrlsPromises.push(\n                    (async () => {\n                      const processedUrl = await processAssetUrl(\n                        url,\n                        shouldInline,\n                      )\n                      if (processedUrl !== url) {\n                        overwriteAttrValue(\n                          s,\n                          attr.location,\n                          partialEncodeURIPath(processedUrl),\n                        )\n                      }\n                    })(),\n                  )\n                }\n              }\n            }\n          }\n\n          const inlineStyle = findNeedTransformStyleAttribute(node)\n          if (inlineStyle) {\n            inlineModuleIndex++\n            // replace `inline style` with __VITE_INLINE_CSS__**_**__\n            // and import css in js code\n            const code = inlineStyle.attr.value\n            const filePath = id.replace(normalizePath(config.root), '')\n            addToHTMLProxyCache(config, filePath, inlineModuleIndex, { code })\n            // will transform with css plugin and cache result with css-post plugin\n            js += `\\nimport \"${id}?html-proxy&inline-css&style-attr&index=${inlineModuleIndex}.css\"`\n            const hash = getHash(cleanUrl(id))\n            // will transform in `applyHtmlTransforms`\n            overwriteAttrValue(\n              s,\n              inlineStyle.location!,\n              `__VITE_INLINE_CSS__${hash}_${inlineModuleIndex}__`,\n            )\n          }\n\n          // <style>...</style>\n          if (node.nodeName === 'style' && node.childNodes.length) {\n            const styleNode =\n              node.childNodes.pop() as DefaultTreeAdapterMap['textNode']\n            const filePath = id.replace(normalizePath(config.root), '')\n            inlineModuleIndex++\n            addToHTMLProxyCache(config, filePath, inlineModuleIndex, {\n              code: styleNode.value,\n            })\n            js += `\\nimport \"${id}?html-proxy&inline-css&index=${inlineModuleIndex}.css\"`\n            const hash = getHash(cleanUrl(id))\n            // will transform in `applyHtmlTransforms`\n            s.update(\n              styleNode.sourceCodeLocation!.startOffset,\n              styleNode.sourceCodeLocation!.endOffset,\n              `__VITE_INLINE_CSS__${hash}_${inlineModuleIndex}__`,\n            )\n          }\n\n          if (shouldRemove) {\n            // remove the script tag from the html. we are going to inject new\n            // ones in the end.\n            s.remove(\n              nodeStartWithLeadingWhitespace(node),\n              node.sourceCodeLocation!.endOffset,\n            )\n          }\n        })\n\n        isAsyncScriptMap.get(config)!.set(id, everyScriptIsAsync)\n\n        if (someScriptsAreAsync && someScriptsAreDefer) {\n          config.logger.warn(\n            `\\nMixed async and defer script modules in ${id}, output script will fallback to defer. Every script, including inline ones, need to be marked as async for your output script to be async.`,\n          )\n        }\n\n        await Promise.all(assetUrlsPromises)\n\n        // emit <script>import(\"./aaa\")</script> asset\n        for (const { start, end, url } of scriptUrls) {\n          if (checkPublicFile(url, config)) {\n            s.update(\n              start,\n              end,\n              partialEncodeURIPath(toOutputPublicFilePath(url)),\n            )\n          } else if (!isExcludedUrl(url)) {\n            s.update(\n              start,\n              end,\n              partialEncodeURIPath(await urlToBuiltUrl(this, url, id)),\n            )\n          }\n        }\n\n        // ignore <link rel=\"stylesheet\"> if its url can't be resolved\n        const resolvedStyleUrls = await Promise.all(\n          styleUrls.map(async (styleUrl) => ({\n            ...styleUrl,\n            resolved: await this.resolve(styleUrl.url, id),\n          })),\n        )\n        for (const { start, end, url, resolved } of resolvedStyleUrls) {\n          if (resolved == null) {\n            config.logger.warnOnce(\n              `\\n${url} doesn't exist at build time, it will remain unchanged to be resolved at runtime`,\n            )\n            const importExpression = `\\nimport ${JSON.stringify(url)}`\n            js = js.replace(importExpression, '')\n          } else {\n            s.remove(start, end)\n          }\n        }\n\n        processedHtml(this).set(id, s.toString())\n\n        // inject module preload polyfill only when configured and needed\n        const { modulePreload } = this.environment.config.build\n        if (\n          modulePreload !== false &&\n          modulePreload.polyfill &&\n          (someScriptsAreAsync || someScriptsAreDefer)\n        ) {\n          js = `import \"${modulePreloadPolyfillId}\";\\n${js}`\n        }\n\n        await Promise.all(setModuleSideEffectPromises)\n\n        // Force rollup to keep this module from being shared between other entry points.\n        // If the resulting chunk is empty, it will be removed in generateBundle.\n        return { code: js, moduleSideEffects: 'no-treeshake' }\n      },\n    },\n\n    async generateBundle(options, bundle) {\n      const analyzedImportedCssFiles = new Map<OutputChunk, string[]>()\n      const inlineEntryChunk = new Set<string>()\n      const getImportedChunks = (\n        chunk: OutputChunk,\n        seen: Set<string> = new Set(),\n      ): (OutputChunk | string)[] => {\n        const chunks: (OutputChunk | string)[] = []\n        chunk.imports.forEach((file) => {\n          const importee = bundle[file]\n          if (importee) {\n            if (importee.type === 'chunk' && !seen.has(file)) {\n              seen.add(file)\n\n              // post-order traversal\n              chunks.push(...getImportedChunks(importee, seen))\n              chunks.push(importee)\n            }\n          } else {\n            // external imports\n            chunks.push(file)\n          }\n        })\n        return chunks\n      }\n\n      const toScriptTag = (\n        chunkOrUrl: OutputChunk | string,\n        toOutputPath: (filename: string) => string,\n        isAsync: boolean,\n      ): HtmlTagDescriptor => ({\n        tag: 'script',\n        attrs: {\n          ...(isAsync ? { async: true } : {}),\n          type: 'module',\n          // crossorigin must be set not only for serving assets in a different origin\n          // but also to make it possible to preload the script using `<link rel=\"preload\">`.\n          // `<script type=\"module\">` used to fetch the script with credential mode `omit`,\n          // however `crossorigin` attribute cannot specify that value.\n          // https://developer.chrome.com/blog/modulepreload/#ok-so-why-doesnt-link-relpreload-work-for-modules:~:text=For%20%3Cscript%3E,of%20other%20modules.\n          // Now `<script type=\"module\">` uses `same origin`: https://github.com/whatwg/html/pull/3656#:~:text=Module%20scripts%20are%20always%20fetched%20with%20credentials%20mode%20%22same%2Dorigin%22%20by%20default%20and%20can%20no%20longer%0Ause%20%22omit%22\n          crossorigin: true,\n          src:\n            typeof chunkOrUrl === 'string'\n              ? chunkOrUrl\n              : toOutputPath(chunkOrUrl.fileName),\n        },\n      })\n\n      const toPreloadTag = (\n        filename: string,\n        toOutputPath: (filename: string) => string,\n      ): HtmlTagDescriptor => ({\n        tag: 'link',\n        attrs: {\n          rel: 'modulepreload',\n          crossorigin: true,\n          href: toOutputPath(filename),\n        },\n      })\n\n      const toStyleSheetLinkTag = (\n        file: string,\n        toOutputPath: (filename: string) => string,\n      ): HtmlTagDescriptor => ({\n        tag: 'link',\n        attrs: {\n          rel: 'stylesheet',\n          crossorigin: true,\n          href: toOutputPath(file),\n        },\n      })\n\n      const getCssFilesForChunk = (\n        chunk: OutputChunk,\n        seenChunks: Set<string> = new Set(),\n        seenCss: Set<string> = new Set(),\n      ): string[] => {\n        if (seenChunks.has(chunk.fileName)) {\n          return []\n        }\n        seenChunks.add(chunk.fileName)\n\n        if (analyzedImportedCssFiles.has(chunk)) {\n          const files = analyzedImportedCssFiles.get(chunk)!\n          const additionals = files.filter((file) => !seenCss.has(file))\n          additionals.forEach((file) => seenCss.add(file))\n          return additionals\n        }\n\n        const files: string[] = []\n        chunk.imports.forEach((file) => {\n          const importee = bundle[file]\n          if (importee?.type === 'chunk') {\n            files.push(...getCssFilesForChunk(importee, seenChunks, seenCss))\n          }\n        })\n        analyzedImportedCssFiles.set(chunk, files)\n\n        chunk.viteMetadata!.importedCss.forEach((file) => {\n          if (!seenCss.has(file)) {\n            seenCss.add(file)\n            files.push(file)\n          }\n        })\n\n        return files\n      }\n\n      const getCssTagsForChunk = (\n        chunk: OutputChunk,\n        toOutputPath: (filename: string) => string,\n      ) =>\n        getCssFilesForChunk(chunk).map((file) =>\n          toStyleSheetLinkTag(file, toOutputPath),\n        )\n\n      for (const [normalizedId, html] of processedHtml(this)) {\n        const relativeUrlPath = normalizePath(\n          path.relative(config.root, normalizedId),\n        )\n        const assetsBase = getBaseInHTML(relativeUrlPath, config)\n        const toOutputFilePath = (\n          filename: string,\n          type: 'asset' | 'public',\n        ) => {\n          if (isExternalUrl(filename)) {\n            return filename\n          } else {\n            return toOutputFilePathInHtml(\n              filename,\n              type,\n              relativeUrlPath,\n              'html',\n              config,\n              (filename) => assetsBase + filename,\n            )\n          }\n        }\n\n        const toOutputAssetFilePath = (filename: string) =>\n          toOutputFilePath(filename, 'asset')\n\n        const toOutputPublicAssetFilePath = (filename: string) =>\n          toOutputFilePath(filename, 'public')\n\n        const isAsync = isAsyncScriptMap.get(config)!.get(normalizedId)!\n\n        let result = html\n\n        // find corresponding entry chunk\n        const chunk = Object.values(bundle).find(\n          (chunk) =>\n            chunk.type === 'chunk' &&\n            chunk.isEntry &&\n            chunk.facadeModuleId &&\n            normalizePath(chunk.facadeModuleId) === normalizedId,\n        ) as OutputChunk | undefined\n\n        let canInlineEntry = false\n\n        // inject chunk asset links\n        if (chunk) {\n          // an entry chunk can be inlined if\n          //  - it's an ES module (e.g. not generated by the legacy plugin)\n          //  - it contains no meaningful code other than import statements\n          if (options.format === 'es' && isEntirelyImport(chunk.code)) {\n            canInlineEntry = true\n          }\n\n          // when not inlined, inject <script> for entry and modulepreload its dependencies\n          // when inlined, discard entry chunk and inject <script> for everything in post-order\n          const imports = getImportedChunks(chunk)\n          let assetTags: HtmlTagDescriptor[]\n          if (canInlineEntry) {\n            assetTags = imports.map((chunk) =>\n              toScriptTag(chunk, toOutputAssetFilePath, isAsync),\n            )\n          } else {\n            const { modulePreload } = this.environment.config.build\n            assetTags = [toScriptTag(chunk, toOutputAssetFilePath, isAsync)]\n            if (modulePreload !== false) {\n              const resolveDependencies =\n                typeof modulePreload === 'object' &&\n                modulePreload.resolveDependencies\n              const importsFileNames = imports\n                .filter((chunkOrUrl) => typeof chunkOrUrl !== 'string')\n                .map((chunk) => chunk.fileName)\n              const resolvedDeps = resolveDependencies\n                ? resolveDependencies(chunk.fileName, importsFileNames, {\n                    hostId: relativeUrlPath,\n                    hostType: 'html',\n                  })\n                : importsFileNames\n              assetTags.push(\n                ...resolvedDeps.map((i) =>\n                  toPreloadTag(i, toOutputAssetFilePath),\n                ),\n              )\n            }\n          }\n          assetTags.push(...getCssTagsForChunk(chunk, toOutputAssetFilePath))\n\n          result = injectToHead(result, assetTags)\n        }\n\n        // inject css link when cssCodeSplit is false\n        if (!this.environment.config.build.cssCodeSplit) {\n          const cssBundleName = cssBundleNameCache.get(config)\n          const cssChunk =\n            cssBundleName &&\n            (Object.values(bundle).find(\n              (chunk) =>\n                chunk.type === 'asset' && chunk.names.includes(cssBundleName),\n            ) as OutputAsset | undefined)\n          if (cssChunk) {\n            result = injectToHead(result, [\n              {\n                tag: 'link',\n                attrs: {\n                  rel: 'stylesheet',\n                  crossorigin: true,\n                  href: toOutputAssetFilePath(cssChunk.fileName),\n                },\n              },\n            ])\n          }\n        }\n\n        // no use assets plugin because it will emit file\n        let match: RegExpExecArray | null\n        let s: MagicString | undefined\n        inlineCSSRE.lastIndex = 0\n        while ((match = inlineCSSRE.exec(result))) {\n          s ||= new MagicString(result)\n          const { 0: full, 1: scopedName } = match\n          const cssTransformedCode = htmlProxyResult.get(scopedName)!\n          s.update(match.index, match.index + full.length, cssTransformedCode)\n        }\n        if (s) {\n          result = s.toString()\n        }\n        result = await applyHtmlTransforms(\n          result,\n          [...normalHooks, ...postHooks],\n          this,\n          {\n            path: '/' + relativeUrlPath,\n            filename: normalizedId,\n            bundle,\n            chunk,\n          },\n        )\n        // resolve asset url references\n        result = result.replace(assetUrlRE, (_, fileHash, postfix = '') => {\n          const file = this.getFileName(fileHash)\n          if (chunk) {\n            chunk.viteMetadata!.importedAssets.add(cleanUrl(file))\n          }\n          return encodeURIPath(toOutputAssetFilePath(file)) + postfix\n        })\n\n        result = result.replace(publicAssetUrlRE, (_, fileHash) => {\n          const publicAssetPath = toOutputPublicAssetFilePath(\n            getPublicAssetFilename(fileHash, config)!,\n          )\n\n          return encodeURIPath(\n            URL.canParse(publicAssetPath)\n              ? publicAssetPath\n              : normalizePath(publicAssetPath),\n          )\n        })\n\n        if (chunk && canInlineEntry) {\n          inlineEntryChunk.add(chunk.fileName)\n        }\n\n        const shortEmitName = normalizePath(\n          path.relative(config.root, normalizedId),\n        )\n        this.emitFile({\n          type: 'asset',\n          originalFileName: normalizedId,\n          fileName: shortEmitName,\n          source: result,\n        })\n      }\n\n      for (const fileName of inlineEntryChunk) {\n        // all imports from entry have been inlined to html, prevent rollup from outputting it\n        delete bundle[fileName]\n      }\n    },\n  }\n}\n\nexport function parseRelAttr(attr: string): string[] {\n  return attr.split(spaceRe).map((v) => v.toLowerCase())\n}\n\n// <tag style=\"... url(...) or image-set(...) ...\"></tag>\n// extract inline styles as virtual css\nexport function findNeedTransformStyleAttribute(\n  node: DefaultTreeAdapterMap['element'],\n): { attr: Token.Attribute; location?: Token.Location } | undefined {\n  const attr = node.attrs.find(\n    (prop) =>\n      prop.prefix === undefined &&\n      prop.name === 'style' &&\n      // only url(...) or image-set(...) in css need to emit file\n      (prop.value.includes('url(') || prop.value.includes('image-set(')),\n  )\n  if (!attr) return undefined\n  const location = node.sourceCodeLocation?.attrs?.['style']\n  return { attr, location }\n}\n\nexport function extractImportExpressionFromClassicScript(\n  scriptTextNode: DefaultTreeAdapterMap['textNode'],\n): ScriptAssetsUrl[] {\n  const startOffset = scriptTextNode.sourceCodeLocation!.startOffset\n  const cleanCode = stripLiteral(scriptTextNode.value)\n\n  const scriptUrls: ScriptAssetsUrl[] = []\n  let match: RegExpExecArray | null\n  inlineImportRE.lastIndex = 0\n  while ((match = inlineImportRE.exec(cleanCode))) {\n    const [, [urlStart, urlEnd]] = match.indices!\n    const start = urlStart + 1\n    const end = urlEnd - 1\n    scriptUrls.push({\n      start: start + startOffset,\n      end: end + startOffset,\n      url: scriptTextNode.value.slice(start, end),\n    })\n  }\n  return scriptUrls\n}\n\nexport interface HtmlTagDescriptor {\n  tag: string\n  /**\n   * attribute values will be escaped automatically if needed\n   */\n  attrs?: Record<string, string | boolean | undefined>\n  children?: string | HtmlTagDescriptor[]\n  /**\n   * default: 'head-prepend'\n   */\n  injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'\n}\n\nexport type IndexHtmlTransformResult =\n  | string\n  | HtmlTagDescriptor[]\n  | {\n      html: string\n      tags: HtmlTagDescriptor[]\n    }\n\nexport interface IndexHtmlTransformContext {\n  /**\n   * public path when served\n   */\n  path: string\n  /**\n   * filename on disk\n   */\n  filename: string\n  server?: ViteDevServer\n  bundle?: OutputBundle\n  chunk?: OutputChunk\n  originalUrl?: string\n}\n\nexport type IndexHtmlTransformHook = (\n  this: MinimalPluginContextWithoutEnvironment,\n  html: string,\n  ctx: IndexHtmlTransformContext,\n) => IndexHtmlTransformResult | void | Promise<IndexHtmlTransformResult | void>\n\nexport type IndexHtmlTransform =\n  | IndexHtmlTransformHook\n  | {\n      order?: 'pre' | 'post' | null\n      handler: IndexHtmlTransformHook\n    }\n\nexport function preImportMapHook(\n  config: ResolvedConfig,\n): IndexHtmlTransformHook {\n  return (html, ctx) => {\n    const importMapIndex = html.search(importMapRE)\n    if (importMapIndex < 0) return\n\n    const importMapAppendIndex = html.search(importMapAppendRE)\n    if (importMapAppendIndex < 0) return\n\n    if (importMapAppendIndex < importMapIndex) {\n      const relativeHtml = normalizePath(\n        path.relative(config.root, ctx.filename),\n      )\n      config.logger.warnOnce(\n        colors.yellow(\n          colors.bold(\n            `(!) <script type=\"importmap\"> should come before <script type=\"module\"> and <link rel=\"modulepreload\"> in /${relativeHtml}`,\n          ),\n        ),\n      )\n    }\n  }\n}\n\n/**\n * Move importmap before the first module script and modulepreload link\n */\nexport function postImportMapHook(): IndexHtmlTransformHook {\n  return (html) => {\n    if (!importMapAppendRE.test(html)) return\n\n    let importMap: string | undefined\n    html = html.replace(importMapRE, (match) => {\n      importMap = match\n      return ''\n    })\n\n    if (importMap) {\n      html = html.replace(\n        importMapAppendRE,\n        (match) => `${importMap}\\n${match}`,\n      )\n    }\n\n    return html\n  }\n}\n\nexport function injectCspNonceMetaTagHook(\n  config: ResolvedConfig,\n): IndexHtmlTransformHook {\n  return () => {\n    if (!config.html?.cspNonce) return\n\n    return [\n      {\n        tag: 'meta',\n        injectTo: 'head',\n        // use nonce attribute so that it's hidden\n        // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#accessing_nonces_and_nonce_hiding\n        attrs: { property: 'csp-nonce', nonce: config.html.cspNonce },\n      },\n    ]\n  }\n}\n\n/**\n * Support `%ENV_NAME%` syntax in html files\n */\nexport function htmlEnvHook(config: ResolvedConfig): IndexHtmlTransformHook {\n  const pattern = /%(\\S+?)%/g\n  const envPrefix = resolveEnvPrefix({ envPrefix: config.envPrefix })\n  const env: Record<string, any> = { ...config.env }\n\n  // account for user env defines\n  for (const key in config.define) {\n    if (key.startsWith(`import.meta.env.`)) {\n      const val = config.define[key]\n      if (typeof val === 'string') {\n        try {\n          const parsed = JSON.parse(val)\n          env[key.slice(16)] = typeof parsed === 'string' ? parsed : val\n        } catch {\n          env[key.slice(16)] = val\n        }\n      } else {\n        env[key.slice(16)] = JSON.stringify(val)\n      }\n    }\n  }\n  return (html, ctx) => {\n    return html.replace(pattern, (text, key) => {\n      if (key in env) {\n        return env[key]\n      } else {\n        if (envPrefix.some((prefix) => key.startsWith(prefix))) {\n          const relativeHtml = normalizePath(\n            path.relative(config.root, ctx.filename),\n          )\n          config.logger.warn(\n            colors.yellow(\n              colors.bold(\n                `(!) ${text} is not defined in env variables found in /${relativeHtml}. ` +\n                  `Is the variable mistyped?`,\n              ),\n            ),\n          )\n        }\n\n        return text\n      }\n    })\n  }\n}\n\nexport function injectNonceAttributeTagHook(\n  config: ResolvedConfig,\n): IndexHtmlTransformHook {\n  const processRelType = new Set(['stylesheet', 'modulepreload', 'preload'])\n\n  return async (html, { filename }) => {\n    const nonce = config.html?.cspNonce\n    if (!nonce) return\n\n    const s = new MagicString(html)\n\n    await traverseHtml(html, filename, config.logger.warn, (node) => {\n      if (!nodeIsElement(node)) {\n        return\n      }\n\n      const { nodeName, attrs, sourceCodeLocation } = node\n\n      if (\n        nodeName === 'script' ||\n        nodeName === 'style' ||\n        (nodeName === 'link' &&\n          attrs.some(\n            (attr) =>\n              attr.name === 'rel' &&\n              parseRelAttr(attr.value).some((a) => processRelType.has(a)),\n          ))\n      ) {\n        // If we already have a nonce attribute, we don't need to add another one\n        if (attrs.some(({ name }) => name === 'nonce')) {\n          return\n        }\n\n        const startTagEndOffset = sourceCodeLocation!.startTag!.endOffset\n\n        // if the closing of the start tag includes a `/`, the offset should be 2 so the nonce\n        // is appended prior to the `/`\n        const appendOffset = html[startTagEndOffset - 2] === '/' ? 2 : 1\n\n        s.appendRight(startTagEndOffset - appendOffset, ` nonce=\"${nonce}\"`)\n      }\n    })\n\n    return s.toString()\n  }\n}\n\nexport function resolveHtmlTransforms(\n  plugins: readonly Plugin[],\n): [\n  IndexHtmlTransformHook[],\n  IndexHtmlTransformHook[],\n  IndexHtmlTransformHook[],\n] {\n  const preHooks: IndexHtmlTransformHook[] = []\n  const normalHooks: IndexHtmlTransformHook[] = []\n  const postHooks: IndexHtmlTransformHook[] = []\n\n  for (const plugin of plugins) {\n    const hook = plugin.transformIndexHtml\n    if (!hook) continue\n\n    if (typeof hook === 'function') {\n      normalHooks.push(hook)\n    } else {\n      const handler = hook.handler\n      if (hook.order === 'pre') {\n        preHooks.push(handler)\n      } else if (hook.order === 'post') {\n        postHooks.push(handler)\n      } else {\n        normalHooks.push(handler)\n      }\n    }\n  }\n\n  return [preHooks, normalHooks, postHooks]\n}\n\n// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head#see_also\nconst elementsAllowedInHead = new Set([\n  'title',\n  'base',\n  'link',\n  'style',\n  'meta',\n  'script',\n  'noscript',\n  'template',\n])\n\nfunction headTagInsertCheck(\n  tags: HtmlTagDescriptor[],\n  ctx: IndexHtmlTransformContext,\n) {\n  if (!tags.length) return\n  const { logger } = ctx.server?.config || {}\n  const disallowedTags = tags.filter(\n    (tagDescriptor) => !elementsAllowedInHead.has(tagDescriptor.tag),\n  )\n\n  if (disallowedTags.length) {\n    const dedupedTags = unique(\n      disallowedTags.map((tagDescriptor) => `<${tagDescriptor.tag}>`),\n    )\n    logger?.warn(\n      colors.yellow(\n        colors.bold(\n          `[${dedupedTags.join(',')}] can not be used inside the <head> Element, please check the 'injectTo' value`,\n        ),\n      ),\n    )\n  }\n}\n\nexport async function applyHtmlTransforms(\n  html: string,\n  hooks: IndexHtmlTransformHook[],\n  pluginContext: MinimalPluginContextWithoutEnvironment,\n  ctx: IndexHtmlTransformContext,\n): Promise<string> {\n  for (const hook of hooks) {\n    const res = await hook.call(pluginContext, html, ctx)\n    if (!res) {\n      continue\n    }\n    if (typeof res === 'string') {\n      html = res\n    } else {\n      let tags: HtmlTagDescriptor[]\n      if (Array.isArray(res)) {\n        tags = res\n      } else {\n        html = res.html || html\n        tags = res.tags\n      }\n\n      let headTags: HtmlTagDescriptor[] | undefined\n      let headPrependTags: HtmlTagDescriptor[] | undefined\n      let bodyTags: HtmlTagDescriptor[] | undefined\n      let bodyPrependTags: HtmlTagDescriptor[] | undefined\n\n      for (const tag of tags) {\n        switch (tag.injectTo) {\n          case 'body':\n            ;(bodyTags ??= []).push(tag)\n            break\n          case 'body-prepend':\n            ;(bodyPrependTags ??= []).push(tag)\n            break\n          case 'head':\n            ;(headTags ??= []).push(tag)\n            break\n          default:\n            ;(headPrependTags ??= []).push(tag)\n        }\n      }\n      headTagInsertCheck([...(headTags || []), ...(headPrependTags || [])], ctx)\n      if (headPrependTags) html = injectToHead(html, headPrependTags, true)\n      if (headTags) html = injectToHead(html, headTags)\n      if (bodyPrependTags) html = injectToBody(html, bodyPrependTags, true)\n      if (bodyTags) html = injectToBody(html, bodyTags)\n    }\n  }\n\n  return html\n}\n\nconst entirelyImportRE =\n  /^(?:import\\s*(?:\"[^\"\\n]*[^\\\\\\n]\"|'[^'\\n]*[^\\\\\\n]');*|\\/\\*[\\s\\S]*?\\*\\/|\\/\\/.*[$\\n])*$/\nfunction isEntirelyImport(code: string) {\n  // only consider \"side-effect\" imports, which match <script type=module> semantics exactly\n  // the regexes will remove too little in some exotic cases, but false-negatives are alright\n  return entirelyImportRE.test(code.trim())\n}\n\nfunction getBaseInHTML(urlRelativePath: string, config: ResolvedConfig) {\n  // Prefer explicit URL if defined for linking to assets and public files from HTML,\n  // even when base relative is specified\n  return config.base === './' || config.base === ''\n    ? path.posix.join(\n        path.posix.relative(urlRelativePath, '').slice(0, -2),\n        './',\n      )\n    : config.base\n}\n\nconst headInjectRE = /([ \\t]*)<\\/head>/i\nconst headPrependInjectRE = /([ \\t]*)<head[^>]*>/i\n\nconst htmlInjectRE = /<\\/html>/i\nconst htmlPrependInjectRE = /([ \\t]*)<html[^>]*>/i\n\nconst bodyInjectRE = /([ \\t]*)<\\/body>/i\nconst bodyPrependInjectRE = /([ \\t]*)<body[^>]*>/i\n\nconst doctypePrependInjectRE = /<!doctype html>/i\n\nfunction injectToHead(\n  html: string,\n  tags: HtmlTagDescriptor[],\n  prepend = false,\n) {\n  if (tags.length === 0) return html\n\n  if (prepend) {\n    // inject as the first element of head\n    if (headPrependInjectRE.test(html)) {\n      return html.replace(\n        headPrependInjectRE,\n        (match, p1) => `${match}\\n${serializeTags(tags, incrementIndent(p1))}`,\n      )\n    }\n  } else {\n    // inject before head close\n    if (headInjectRE.test(html)) {\n      // respect indentation of head tag\n      return html.replace(\n        headInjectRE,\n        (match, p1) => `${serializeTags(tags, incrementIndent(p1))}${match}`,\n      )\n    }\n    // try to inject before the body tag\n    if (bodyPrependInjectRE.test(html)) {\n      return html.replace(\n        bodyPrependInjectRE,\n        (match, p1) => `${serializeTags(tags, p1)}\\n${match}`,\n      )\n    }\n  }\n  // if no head tag is present, we prepend the tag for both prepend and append\n  return prependInjectFallback(html, tags)\n}\n\nfunction injectToBody(\n  html: string,\n  tags: HtmlTagDescriptor[],\n  prepend = false,\n) {\n  if (tags.length === 0) return html\n\n  if (prepend) {\n    // inject after body open\n    if (bodyPrependInjectRE.test(html)) {\n      return html.replace(\n        bodyPrependInjectRE,\n        (match, p1) => `${match}\\n${serializeTags(tags, incrementIndent(p1))}`,\n      )\n    }\n    // if no there is no body tag, inject after head or fallback to prepend in html\n    if (headInjectRE.test(html)) {\n      return html.replace(\n        headInjectRE,\n        (match, p1) => `${match}\\n${serializeTags(tags, p1)}`,\n      )\n    }\n    return prependInjectFallback(html, tags)\n  } else {\n    // inject before body close\n    if (bodyInjectRE.test(html)) {\n      return html.replace(\n        bodyInjectRE,\n        (match, p1) => `${serializeTags(tags, incrementIndent(p1))}${match}`,\n      )\n    }\n    // if no body tag is present, append to the html tag, or at the end of the file\n    if (htmlInjectRE.test(html)) {\n      return html.replace(htmlInjectRE, `${serializeTags(tags)}\\n$&`)\n    }\n    return html + `\\n` + serializeTags(tags)\n  }\n}\n\nfunction prependInjectFallback(html: string, tags: HtmlTagDescriptor[]) {\n  // prepend to the html tag, append after doctype, or the document start\n  if (htmlPrependInjectRE.test(html)) {\n    return html.replace(htmlPrependInjectRE, `$&\\n${serializeTags(tags)}`)\n  }\n  if (doctypePrependInjectRE.test(html)) {\n    return html.replace(doctypePrependInjectRE, `$&\\n${serializeTags(tags)}`)\n  }\n  return serializeTags(tags) + html\n}\n\nconst unaryTags = new Set(['link', 'meta', 'base'])\n\nfunction serializeTag(\n  { tag, attrs, children }: HtmlTagDescriptor,\n  indent: string = '',\n): string {\n  if (unaryTags.has(tag)) {\n    return `<${tag}${serializeAttrs(attrs)}>`\n  } else {\n    return `<${tag}${serializeAttrs(attrs)}>${serializeTags(\n      children,\n      incrementIndent(indent),\n    )}</${tag}>`\n  }\n}\n\nfunction serializeTags(\n  tags: HtmlTagDescriptor['children'],\n  indent: string = '',\n): string {\n  if (typeof tags === 'string') {\n    return tags\n  } else if (tags && tags.length) {\n    return tags.map((tag) => `${indent}${serializeTag(tag, indent)}\\n`).join('')\n  }\n  return ''\n}\n\nfunction serializeAttrs(attrs: HtmlTagDescriptor['attrs']): string {\n  let res = ''\n  for (const key in attrs) {\n    if (typeof attrs[key] === 'boolean') {\n      res += attrs[key] ? ` ${key}` : ``\n    } else {\n      res += ` ${key}=\"${escapeHtml(attrs[key])}\"`\n    }\n  }\n  return res\n}\n\nfunction incrementIndent(indent: string = '') {\n  return `${indent}${indent[0] === '\\t' ? '\\t' : '  '}`\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/importAnalysis.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport { performance } from 'node:perf_hooks'\nimport colors from 'picocolors'\nimport MagicString from 'magic-string'\nimport type {\n  ParseError as EsModuleLexerParseError,\n  ExportSpecifier,\n  ImportSpecifier,\n} from 'es-module-lexer'\nimport { init, parse as parseImports } from 'es-module-lexer'\nimport { parseAst } from 'rolldown/parseAst'\nimport type { StaticImport } from 'mlly'\nimport { ESM_STATIC_IMPORT_RE, parseStaticImport } from 'mlly'\nimport { makeLegalIdentifier } from '@rollup/pluginutils'\nimport type { PartialResolvedId, RollupError } from 'rolldown'\nimport type { ESTree } from 'rolldown/utils'\nimport {\n  CLIENT_DIR,\n  CLIENT_PUBLIC_PATH,\n  DEP_VERSION_RE,\n  FS_PREFIX,\n  SPECIAL_QUERY_RE,\n} from '../constants'\nimport {\n  debugHmr,\n  handlePrunedModules,\n  lexAcceptedHmrDeps,\n  lexAcceptedHmrExports,\n  normalizeHmrUrl,\n} from '../server/hmr'\nimport {\n  createDebugger,\n  fsPathFromUrl,\n  generateCodeFrame,\n  getHash,\n  injectQuery,\n  isBuiltin,\n  isCSSRequest,\n  isDataUrl,\n  isDefined,\n  isExternalUrl,\n  isFilePathESM,\n  isInNodeModules,\n  isJSRequest,\n  joinUrlSegments,\n  moduleListContains,\n  normalizePath,\n  prettifyUrl,\n  removeImportQuery,\n  removeTimestampQuery,\n  stripBase,\n  stripBomTag,\n  timeFrom,\n  transformStableResult,\n  urlRE,\n} from '../utils'\nimport { checkPublicFile } from '../publicDir'\nimport type { ResolvedConfig } from '../config'\nimport type { Plugin } from '../plugin'\nimport type { DevEnvironment } from '../server/environment'\nimport { shouldExternalize } from '../external'\nimport {\n  optimizedDepInfoFromFile,\n  optimizedDepNeedsInterop,\n} from '../optimizer'\nimport {\n  cleanUrl,\n  unwrapId,\n  withTrailingSlash,\n  wrapId,\n} from '../../shared/utils'\nimport type { TransformPluginContext } from '../server/pluginContainer'\nimport { throwOutdatedRequest } from './optimizedDeps'\nimport { isDirectCSSRequest } from './css'\nimport { browserExternalId } from './resolve'\nimport { serializeDefine } from './define'\nimport { WORKER_FILE_ID } from './worker'\nimport { getAliasPatternMatcher } from './preAlias'\n\nconst debug = createDebugger('vite:import-analysis')\n\nconst clientDir = normalizePath(CLIENT_DIR)\n\nconst skipRE = /\\.(?:map|json)(?:$|\\?)/\nexport const canSkipImportAnalysis = (id: string): boolean =>\n  skipRE.test(id) || isDirectCSSRequest(id)\n\nconst optimizedDepChunkRE = /\\/chunk-[A-Z\\d]{8}\\.js/\n\nexport const hasViteIgnoreRE: RegExp = /\\/\\*\\s*@vite-ignore\\s*\\*\\//\n\nconst urlIsStringRE = /^(?:'.*'|\".*\"|`.*`)$/\n\nconst templateLiteralRE = /^\\s*`(.*)`\\s*$/\n\ninterface UrlPosition {\n  url: string\n  start: number\n  end: number\n}\n\nexport function isExplicitImportRequired(url: string): boolean {\n  return !isJSRequest(url) && !isCSSRequest(url)\n}\n\nfunction normalizeResolvedIdToUrl(\n  environment: DevEnvironment,\n  url: string,\n  resolved: PartialResolvedId,\n): string {\n  const root = environment.config.root\n  const depsOptimizer = environment.depsOptimizer\n\n  // normalize all imports into resolved URLs\n  // e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`\n  if (resolved.id.startsWith(withTrailingSlash(root))) {\n    // in root: infer short absolute path from root\n    url = resolved.id.slice(root.length)\n  } else if (\n    depsOptimizer?.isOptimizedDepFile(resolved.id) ||\n    // vite-plugin-react isn't following the leading \\0 virtual module convention.\n    // This is a temporary hack to avoid expensive fs checks for React apps.\n    // We'll remove this as soon we're able to fix the react plugins.\n    (resolved.id !== '/@react-refresh' &&\n      path.isAbsolute(resolved.id) &&\n      fs.existsSync(cleanUrl(resolved.id)))\n  ) {\n    // an optimized deps may not yet exists in the filesystem, or\n    // a regular file exists but is out of root: rewrite to absolute /@fs/ paths\n    url = path.posix.join(FS_PREFIX, resolved.id)\n  } else {\n    url = resolved.id\n  }\n\n  // if the resolved id is not a valid browser import specifier,\n  // prefix it to make it valid. We will strip this before feeding it\n  // back into the transform pipeline\n  if (url[0] !== '.' && url[0] !== '/') {\n    url = wrapId(resolved.id)\n  }\n\n  return url\n}\n\nfunction extractImportedBindings(\n  id: string,\n  source: string,\n  importSpec: ImportSpecifier,\n  importedBindings: Map<string, Set<string>>,\n) {\n  let bindings = importedBindings.get(id)\n  if (!bindings) {\n    bindings = new Set<string>()\n    importedBindings.set(id, bindings)\n  }\n\n  const isDynamic = importSpec.d > -1\n  const isMeta = importSpec.d === -2\n  if (isDynamic || isMeta) {\n    // this basically means the module will be impacted by any change in its dep\n    bindings.add('*')\n    return\n  }\n\n  const exp = source.slice(importSpec.ss, importSpec.se)\n  ESM_STATIC_IMPORT_RE.lastIndex = 0\n  const match = ESM_STATIC_IMPORT_RE.exec(exp)\n  if (!match) {\n    return\n  }\n\n  const staticImport: StaticImport = {\n    type: 'static',\n    code: match[0],\n    start: match.index,\n    end: match.index + match[0].length,\n    imports: match.groups!.imports,\n    specifier: match.groups!.specifier,\n  }\n  const parsed = parseStaticImport(staticImport)\n  if (parsed.namespacedImport) {\n    bindings.add('*')\n  }\n  if (parsed.defaultImport) {\n    bindings.add('default')\n  }\n  if (parsed.namedImports) {\n    for (const name of Object.keys(parsed.namedImports)) {\n      bindings.add(name)\n    }\n  }\n}\n\n/**\n * Dev-only plugin that lexes, resolves, rewrites and analyzes url imports.\n *\n * - Imports are resolved to ensure they exist on disk\n *\n * - Lexes HMR accept calls and updates import relationships in the module graph\n *\n * - Bare module imports are resolved (by @rollup-plugin/node-resolve) to\n * absolute file paths, e.g.\n *\n *     ```js\n *     import 'foo'\n *     ```\n *     is rewritten to\n *     ```js\n *     import '/@fs//project/node_modules/foo/dist/foo.js'\n *     ```\n *\n * - CSS imports are appended with `.js` since both the js module and the actual\n * css (referenced via `<link>`) may go through the transform pipeline:\n *\n *     ```js\n *     import './style.css'\n *     ```\n *     is rewritten to\n *     ```js\n *     import './style.css.js'\n *     ```\n */\nexport function importAnalysisPlugin(config: ResolvedConfig): Plugin {\n  const { root, base } = config\n  const clientPublicPath = path.posix.join(base, CLIENT_PUBLIC_PATH)\n  const enablePartialAccept = config.experimental.hmrPartialAccept\n  const matchAlias = getAliasPatternMatcher(config.resolve.alias)\n\n  let _env: string | undefined\n  let _ssrEnv: string | undefined\n  function getEnv(ssr: boolean) {\n    if (!_ssrEnv || !_env) {\n      const importMetaEnvKeys: Record<string, any> = {}\n      const userDefineEnv: Record<string, any> = {}\n      for (const key in config.env) {\n        importMetaEnvKeys[key] = JSON.stringify(config.env[key])\n      }\n      for (const key in config.define) {\n        // non-import.meta.env.* is handled in `clientInjection` plugin\n        if (key.startsWith('import.meta.env.')) {\n          userDefineEnv[key.slice(16)] = config.define[key]\n        }\n      }\n      const env = `import.meta.env = ${serializeDefine({\n        ...importMetaEnvKeys,\n        SSR: '__vite_ssr__',\n        ...userDefineEnv,\n      })};`\n      _ssrEnv = env.replace('__vite_ssr__', 'true')\n      _env = env.replace('__vite_ssr__', 'false')\n    }\n    return ssr ? _ssrEnv : _env\n  }\n\n  return {\n    name: 'vite:import-analysis',\n\n    async transform(source, importer) {\n      const environment = this.environment as DevEnvironment\n      const ssr = environment.config.consumer === 'server'\n      const moduleGraph = environment.moduleGraph\n\n      if (canSkipImportAnalysis(importer)) {\n        debug?.(colors.dim(`[skipped] ${prettifyUrl(importer, root)}`))\n        return null\n      }\n\n      const msAtStart = debug ? performance.now() : 0\n      await init\n      let imports!: readonly ImportSpecifier[]\n      let exports!: readonly ExportSpecifier[]\n      source = stripBomTag(source)\n      try {\n        ;[imports, exports] = parseImports(source)\n      } catch (_e: unknown) {\n        const e = _e as EsModuleLexerParseError\n        const { message, showCodeFrame } = createParseErrorInfo(\n          importer,\n          source,\n        )\n        this.error(message, showCodeFrame ? e.idx : undefined)\n      }\n\n      const depsOptimizer = environment.depsOptimizer\n\n      // since we are already in the transform phase of the importer, it must\n      // have been loaded so its entry is guaranteed in the module graph.\n      const importerModule = moduleGraph.getModuleById(importer)\n      if (!importerModule) {\n        // This request is no longer valid. It could happen for optimized deps\n        // requests. A full reload is going to request this id again.\n        // Throwing an outdated error so we properly finish the request with a\n        // 504 sent to the browser.\n        throwOutdatedRequest(importer)\n      }\n\n      if (\n        !imports.length &&\n        !(this as unknown as TransformPluginContext)._addedImports\n      ) {\n        const prunedImports = await moduleGraph.updateModuleInfo(\n          importerModule,\n          new Set(),\n          null,\n          new Set(),\n          null,\n          false,\n        )\n        if (prunedImports) {\n          handlePrunedModules(prunedImports, environment)\n        }\n        debug?.(\n          `${timeFrom(msAtStart)} ${colors.dim(\n            `[no imports] ${prettifyUrl(importer, root)}`,\n          )}`,\n        )\n        return source\n      }\n\n      let hasHMR = false\n      let isSelfAccepting = false\n      let hasEnv = false\n      let needQueryInjectHelper = false\n      let s: MagicString | undefined\n      const str = () => s || (s = new MagicString(source))\n      let isPartiallySelfAccepting = false\n      const importedBindings = enablePartialAccept\n        ? new Map<string, Set<string>>()\n        : null\n\n      const normalizeUrl = async (\n        url: string,\n        pos: number,\n        forceSkipImportAnalysis: boolean = false,\n      ): Promise<[string, string | null]> => {\n        let importerFile = importer\n\n        if (\n          depsOptimizer &&\n          moduleListContains(depsOptimizer.options.exclude, url)\n        ) {\n          await depsOptimizer.scanProcessing\n\n          // if the dependency encountered in the optimized file was excluded from the optimization\n          // the dependency needs to be resolved starting from the original source location of the optimized file\n          // because starting from node_modules/.vite will not find the dependency if it was not hoisted\n          // (that is, if it is under node_modules directory in the package source of the optimized file)\n          for (const optimizedModule of depsOptimizer.metadata.depInfoList) {\n            if (!optimizedModule.src) continue // Ignore chunks\n            if (optimizedModule.file === importerModule.file) {\n              importerFile = optimizedModule.src\n            }\n          }\n        }\n\n        const resolved = await this.resolve(url, importerFile).catch((e) => {\n          if (e instanceof Error) {\n            ;(e as RollupError).pos ??= pos\n          }\n          throw e\n        })\n\n        // NOTE: resolved.meta is undefined in dev\n        if (!resolved || resolved.meta?.['vite:alias']?.noResolved) {\n          // in ssr, we should let node handle the missing modules\n          if (ssr) {\n            return [url, null]\n          }\n          // fix#9534, prevent the importerModuleNode being stopped from propagating updates\n          importerModule.isSelfAccepting = false\n          moduleGraph._hasResolveFailedErrorModules.add(importerModule)\n          return this.error(\n            `Failed to resolve import \"${url}\" from \"${normalizePath(\n              path.relative(process.cwd(), importerFile),\n            )}\". Does the file exist?`,\n            pos,\n          )\n        }\n\n        if (isExternalUrl(resolved.id)) {\n          return [resolved.id, resolved.id]\n        }\n\n        url = normalizeResolvedIdToUrl(environment, url, resolved)\n\n        try {\n          // delay setting `isSelfAccepting` until the file is actually used (#7870)\n          // We use an internal function to avoid resolving the url again\n          const depModule = await moduleGraph._ensureEntryFromUrl(\n            unwrapId(url),\n            canSkipImportAnalysis(url) || forceSkipImportAnalysis,\n            resolved,\n          )\n          // check if the dep has been hmr updated. If yes, we need to attach\n          // its last updated timestamp to force the browser to fetch the most\n          // up-to-date version of this module.\n          if (\n            environment.config.consumer === 'client' &&\n            depModule.lastHMRTimestamp > 0\n          ) {\n            url = injectQuery(url, `t=${depModule.lastHMRTimestamp}`)\n          }\n        } catch (e: any) {\n          // it's possible that the dep fails to resolve (non-existent import)\n          // attach location to the missing import\n          e.pos = pos\n          throw e\n        }\n\n        // make the URL browser-valid\n        if (environment.config.consumer === 'client') {\n          const isRelative = url[0] === '.'\n          const isSelfImport =\n            !isRelative && cleanUrl(url) === cleanUrl(importer)\n\n          // mark non-js/css imports with `?import`\n          if (isExplicitImportRequired(url)) {\n            url = injectQuery(url, 'import')\n          } else if (\n            (isRelative || isSelfImport) &&\n            !DEP_VERSION_RE.test(url)\n          ) {\n            // If the url isn't a request for a pre-bundled common chunk,\n            // for relative js/css imports, or self-module virtual imports\n            // (e.g. vue blocks), inherit importer's version query\n            // do not do this for unknown type imports, otherwise the appended\n            // query can break 3rd party plugin's extension checks.\n            const versionMatch = DEP_VERSION_RE.exec(importer)\n            if (versionMatch) {\n              url = injectQuery(url, versionMatch[1])\n            }\n          }\n        }\n\n        // prepend base\n        if (!ssr) url = joinUrlSegments(base, url)\n\n        return [url, resolved.id]\n      }\n\n      const orderedImportedUrls = new Array<string | undefined>(imports.length)\n      const orderedAcceptedUrls = new Array<Set<UrlPosition> | undefined>(\n        imports.length,\n      )\n      const orderedAcceptedExports = new Array<Set<string> | undefined>(\n        imports.length,\n      )\n\n      let _isNodeModeResult = config.legacy?.inconsistentCjsInterop\n        ? false\n        : undefined\n      const isNodeMode = () => {\n        _isNodeModeResult ??= isFilePathESM(importer, config.packageCache)\n        return _isNodeModeResult\n      }\n\n      await Promise.all(\n        imports.map(async (importSpecifier, index) => {\n          const {\n            s: start,\n            e: end,\n            ss: expStart,\n            se: expEnd,\n            d: dynamicIndex,\n            a: attributeIndex,\n          } = importSpecifier\n\n          // #2083 User may use escape path,\n          // so use imports[index].n to get the unescaped string\n          let specifier = importSpecifier.n\n\n          const rawUrl = source.slice(start, end)\n\n          // check import.meta usage\n          if (rawUrl === 'import.meta') {\n            const prop = source.slice(end, end + 4)\n            if (prop === '.hot') {\n              hasHMR = true\n              const endHot = end + 4 + (source[end + 4] === '?' ? 1 : 0)\n              if (source.slice(endHot, endHot + 7) === '.accept') {\n                // further analyze accepted modules\n                if (source.slice(endHot, endHot + 14) === '.acceptExports') {\n                  const importAcceptedExports = (orderedAcceptedExports[index] =\n                    new Set<string>())\n                  lexAcceptedHmrExports(\n                    source,\n                    source.indexOf('(', endHot + 14) + 1,\n                    importAcceptedExports,\n                  )\n                  isPartiallySelfAccepting = true\n                } else {\n                  const importAcceptedUrls = (orderedAcceptedUrls[index] =\n                    new Set<UrlPosition>())\n                  if (\n                    lexAcceptedHmrDeps(\n                      source,\n                      source.indexOf('(', endHot + 7) + 1,\n                      importAcceptedUrls,\n                    )\n                  ) {\n                    isSelfAccepting = true\n                  }\n                }\n              }\n            } else if (prop === '.env') {\n              hasEnv = true\n            }\n            return\n          } else if (templateLiteralRE.test(rawUrl)) {\n            // If the import has backticks but isn't transformed as a glob import\n            // (as there's nothing to glob), check if it's simply a plain string.\n            // If so, we can replace the specifier as a plain string to prevent\n            // an incorrect \"cannot be analyzed\" warning.\n            if (!(rawUrl.includes('${') && rawUrl.includes('}'))) {\n              specifier = rawUrl.replace(templateLiteralRE, '$1')\n            }\n          }\n\n          const isDynamicImport = dynamicIndex > -1\n\n          // strip import attributes as we can process them ourselves\n          if (!isDynamicImport && attributeIndex > -1) {\n            str().remove(end + 1, expEnd)\n          }\n\n          // static import or valid string in dynamic import\n          // If resolvable, let's resolve it\n          if (specifier !== undefined) {\n            // skip external / data uri\n            if (\n              ((isExternalUrl(specifier) && !specifier.startsWith('file://')) ||\n                isDataUrl(specifier)) &&\n              !matchAlias(specifier)\n            ) {\n              return\n            }\n            // skip ssr externals and builtins\n            if (ssr && !matchAlias(specifier)) {\n              if (shouldExternalize(environment, specifier, importer)) {\n                return\n              }\n              if (isBuiltin(environment.config.resolve.builtins, specifier)) {\n                return\n              }\n            }\n            // skip client\n            if (specifier === clientPublicPath) {\n              return\n            }\n\n            // warn imports to non-asset /public files\n            if (\n              specifier[0] === '/' &&\n              !(\n                config.assetsInclude(cleanUrl(specifier)) ||\n                urlRE.test(specifier)\n              ) &&\n              checkPublicFile(specifier, config)\n            ) {\n              throw new Error(\n                `Cannot import non-asset file ${specifier} which is inside /public. ` +\n                  `JS/CSS files inside /public are copied as-is on build and ` +\n                  `can only be referenced via <script src> or <link href> in html. ` +\n                  `If you want to get the URL of that file, use ${injectQuery(\n                    specifier,\n                    'url',\n                  )} instead.`,\n              )\n            }\n\n            // normalize\n            let [url, resolvedId] = await normalizeUrl(specifier, start)\n            resolvedId = resolvedId || url\n\n            // record as safe modules\n            // safeModulesPath should not include the base prefix.\n            // See https://github.com/vitejs/vite/issues/9438#issuecomment-1465270409\n            config.safeModulePaths.add(fsPathFromUrl(stripBase(url, base)))\n\n            if (url !== specifier) {\n              let rewriteDone = false\n              if (\n                !depsOptimizer?.isOptimizedDepFile(importer) &&\n                depsOptimizer?.isOptimizedDepFile(resolvedId) &&\n                !optimizedDepChunkRE.test(resolvedId)\n              ) {\n                // for optimized cjs deps, support named imports by rewriting named imports to const assignments.\n                // internal optimized chunks don't need es interop and are excluded\n\n                // The browserHash in resolvedId could be stale in which case there will be a full\n                // page reload. We could return a 404 in that case but it is safe to return the request\n                const file = cleanUrl(resolvedId) // Remove ?v={hash}\n\n                const depInfo = optimizedDepInfoFromFile(\n                  depsOptimizer.metadata,\n                  file,\n                )\n                const needsInterop = await optimizedDepNeedsInterop(\n                  environment,\n                  depsOptimizer.metadata,\n                  file,\n                )\n\n                if (needsInterop === undefined) {\n                  // Non-entry dynamic imports from dependencies will reach here as there isn't\n                  // optimize info for them, but they don't need es interop. If the request isn't\n                  // a dynamic import, then it is an internal Vite error\n                  if (depInfo?.isDynamicEntry) {\n                    config.logger.error(\n                      colors.red(\n                        `Vite Error, ${url} optimized info should be defined`,\n                      ),\n                    )\n                  }\n                } else if (needsInterop) {\n                  debug?.(`${url} needs interop`)\n                  interopNamedImports(\n                    str(),\n                    importSpecifier,\n                    url,\n                    index,\n                    importer,\n                    isNodeMode(),\n                    config,\n                  )\n                  rewriteDone = true\n                }\n              }\n              // If source code imports builtin modules via named imports, the stub proxy export\n              // would fail as it's `export default` only. Apply interop for builtin modules to\n              // correctly throw the error message.\n              else if (\n                url.startsWith(wrapId(browserExternalId)) &&\n                source.slice(expStart, start).includes('{')\n              ) {\n                interopNamedImports(\n                  str(),\n                  importSpecifier,\n                  url,\n                  index,\n                  importer,\n                  isNodeMode(),\n                  config,\n                )\n                rewriteDone = true\n              }\n              if (!rewriteDone) {\n                const rewrittenUrl = JSON.stringify(url)\n                const s = isDynamicImport ? start : start - 1\n                const e = isDynamicImport ? end : end + 1\n                str().overwrite(s, e, rewrittenUrl, {\n                  contentOnly: true,\n                })\n              }\n            }\n\n            // record for HMR import chain analysis\n            // make sure to unwrap and normalize away base\n            const hmrUrl = unwrapId(stripBase(url, base))\n            const isLocalImport = !isExternalUrl(hmrUrl) && !isDataUrl(hmrUrl)\n            if (isLocalImport) {\n              orderedImportedUrls[index] = hmrUrl\n            }\n\n            if (enablePartialAccept && importedBindings) {\n              extractImportedBindings(\n                resolvedId,\n                source,\n                importSpecifier,\n                importedBindings,\n              )\n            }\n\n            if (\n              !isDynamicImport &&\n              isLocalImport &&\n              environment.config.dev.preTransformRequests\n            ) {\n              // pre-transform known direct imports\n              // These requests will also be registered in transformRequest to be awaited\n              // by the deps optimizer\n              const url = removeImportQuery(hmrUrl)\n              environment.warmupRequest(url)\n            }\n          } else if (!importer.startsWith(withTrailingSlash(clientDir))) {\n            if (!isInNodeModules(importer)) {\n              // check @vite-ignore which suppresses dynamic import warning\n              const hasViteIgnore = hasViteIgnoreRE.test(\n                // complete expression inside parens\n                source.slice(dynamicIndex + 1, end),\n              )\n              if (!hasViteIgnore) {\n                this.warn(\n                  `\\n` +\n                    colors.cyan(importerModule.file) +\n                    `\\n` +\n                    colors.reset(generateCodeFrame(source, start, end)) +\n                    colors.yellow(\n                      `\\nThe above dynamic import cannot be analyzed by Vite.\\n` +\n                        `See ${colors.blue(\n                          `https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations`,\n                        )} ` +\n                        `for supported dynamic import formats. ` +\n                        `If this is intended to be left as-is, you can use the ` +\n                        `/* @vite-ignore */ comment inside the import() call to suppress this warning.\\n`,\n                    ),\n                )\n              }\n            }\n\n            if (!ssr) {\n              if (\n                !urlIsStringRE.test(rawUrl) ||\n                isExplicitImportRequired(rawUrl.slice(1, -1))\n              ) {\n                needQueryInjectHelper = true\n                str().overwrite(\n                  start,\n                  end,\n                  `__vite__injectQuery(${rawUrl}, 'import')`,\n                  { contentOnly: true },\n                )\n              }\n            }\n          }\n        }),\n      )\n\n      const _orderedImportedUrls = orderedImportedUrls.filter(isDefined)\n      const importedUrls = new Set(_orderedImportedUrls)\n      // `importedUrls` will be mixed with watched files for the module graph,\n      // `staticImportedUrls` will only contain the static top-level imports and\n      // dynamic imports\n      const staticImportedUrls = new Set(\n        _orderedImportedUrls.map((url) => removeTimestampQuery(url)),\n      )\n      const acceptedUrls = mergeAcceptedUrls(orderedAcceptedUrls)\n      const acceptedExports = mergeAcceptedUrls(orderedAcceptedExports)\n\n      // While we always expect to work with ESM, a classic worker is the only\n      // case where it's not ESM and we need to avoid injecting ESM-specific code\n      const isClassicWorker =\n        importer.includes(WORKER_FILE_ID) && importer.includes('type=classic')\n\n      if (hasEnv && !isClassicWorker) {\n        // inject import.meta.env\n        str().prepend(getEnv(ssr))\n      }\n\n      if (hasHMR && !ssr && !isClassicWorker) {\n        debugHmr?.(\n          `${\n            isSelfAccepting\n              ? `[self-accepts]`\n              : isPartiallySelfAccepting\n                ? `[accepts-exports]`\n                : acceptedUrls.size\n                  ? `[accepts-deps]`\n                  : `[detected api usage]`\n          } ${prettifyUrl(importer, root)}`,\n        )\n        // inject hot context\n        str().prepend(\n          `import { createHotContext as __vite__createHotContext } from \"${clientPublicPath}\";` +\n            `import.meta.hot = __vite__createHotContext(${JSON.stringify(\n              normalizeHmrUrl(importerModule.url),\n            )});`,\n        )\n      }\n\n      if (needQueryInjectHelper) {\n        if (isClassicWorker) {\n          str().append('\\n' + __vite__injectQuery.toString())\n        } else {\n          str().prepend(\n            `import { injectQuery as __vite__injectQuery } from \"${clientPublicPath}\";`,\n          )\n        }\n      }\n\n      // normalize and rewrite accepted urls\n      const normalizedAcceptedUrls = new Set<string>()\n      for (const { url, start, end } of acceptedUrls) {\n        let [normalized, resolvedId] = await normalizeUrl(url, start).catch(\n          () => [],\n        )\n        if (resolvedId) {\n          const mod = moduleGraph.getModuleById(resolvedId)\n          if (!mod) {\n            this.error(\n              `module was not found for ${JSON.stringify(resolvedId)}`,\n              start,\n            )\n            return\n          }\n          normalized = mod.url\n        } else {\n          this.error({\n            message: `Failed to resolve ${JSON.stringify(url)} from ${importer}.`,\n            pos: start,\n          })\n        }\n        normalizedAcceptedUrls.add(normalized)\n        const hmrAccept = normalizeHmrUrl(normalized)\n        str().overwrite(start, end, JSON.stringify(hmrAccept), {\n          contentOnly: true,\n        })\n      }\n\n      // update the module graph for HMR analysis.\n      // node CSS imports does its own graph update in the css-analysis plugin so we\n      // only handle js graph updates here.\n      // note that we want to handle .css?raw and .css?url here\n      if (!isCSSRequest(importer) || SPECIAL_QUERY_RE.test(importer)) {\n        // attached by pluginContainer.addWatchFile\n        const pluginImports = (this as unknown as TransformPluginContext)\n          ._addedImports\n        if (pluginImports) {\n          ;(\n            await Promise.all(\n              [...pluginImports].map((id) => normalizeUrl(id, 0, true)),\n            )\n          ).forEach(([url]) => importedUrls.add(stripBase(url, base)))\n        }\n        // HMR transforms are no-ops in SSR, so an `accept` call will\n        // never be injected. Avoid updating the `isSelfAccepting`\n        // property for our module node in that case.\n        if (ssr && importerModule.isSelfAccepting) {\n          isSelfAccepting = true\n        }\n        // a partially accepted module that accepts all its exports\n        // behaves like a self-accepted module in practice\n        if (\n          !isSelfAccepting &&\n          isPartiallySelfAccepting &&\n          acceptedExports.size >= exports.length &&\n          exports.every((e) => acceptedExports.has(e.n))\n        ) {\n          isSelfAccepting = true\n        }\n        const prunedImports = await moduleGraph.updateModuleInfo(\n          importerModule,\n          importedUrls,\n          importedBindings,\n          normalizedAcceptedUrls,\n          isPartiallySelfAccepting ? acceptedExports : null,\n          isSelfAccepting,\n          staticImportedUrls,\n        )\n        if (prunedImports) {\n          handlePrunedModules(prunedImports, environment)\n        }\n      }\n\n      debug?.(\n        `${timeFrom(msAtStart)} ${colors.dim(\n          `[${importedUrls.size} imports rewritten] ${prettifyUrl(\n            importer,\n            root,\n          )}`,\n        )}`,\n      )\n\n      if (s) {\n        return transformStableResult(s, importer, config)\n      } else {\n        return source\n      }\n    },\n  }\n}\n\nfunction mergeAcceptedUrls<T>(orderedUrls: Array<Set<T> | undefined>) {\n  const acceptedUrls = new Set<T>()\n  for (const urls of orderedUrls) {\n    if (!urls) continue\n    for (const url of urls) acceptedUrls.add(url)\n  }\n  return acceptedUrls\n}\n\nexport function createParseErrorInfo(\n  importer: string,\n  source: string,\n): { message: string; showCodeFrame: boolean } {\n  const isVue = importer.endsWith('.vue')\n  const isJsx = importer.endsWith('.jsx') || importer.endsWith('.tsx')\n  const maybeJSX = !isVue && isJSRequest(importer)\n  const probablyBinary = source.includes(\n    '\\ufffd' /* unicode replacement character */,\n  )\n\n  const msg = isVue\n    ? `Install @vitejs/plugin-vue to handle .vue files.`\n    : maybeJSX\n      ? isJsx\n        ? `If you use tsconfig.json, make sure to not set jsx to preserve.`\n        : `If you are using JSX, make sure to name the file with the .jsx or .tsx extension.`\n      : `You may need to install appropriate plugins to handle the ${path.extname(\n          importer,\n        )} file format, or if it's an asset, add \"**/*${path.extname(\n          importer,\n        )}\" to \\`assetsInclude\\` in your configuration.`\n\n  return {\n    message:\n      `Failed to parse source for import analysis because the content ` +\n      `contains invalid JS syntax. ` +\n      msg,\n    showCodeFrame: !probablyBinary,\n  }\n}\n\nconst interopHelper = (m: any, n: boolean) =>\n  n || !m?.__esModule\n    ? {\n        ...((typeof m === 'object' && !Array.isArray(m)) ||\n        typeof m === 'function'\n          ? m\n          : {}),\n        default: m,\n      }\n    : m\nconst interopHelperStr = interopHelper.toString().replaceAll('\\n', '')\n\nexport function interopNamedImports(\n  str: MagicString,\n  importSpecifier: ImportSpecifier,\n  rewrittenUrl: string,\n  importIndex: number,\n  importer: string,\n  isNodeMode: boolean,\n  config: ResolvedConfig,\n): void {\n  const source = str.original\n  const {\n    s: start,\n    e: end,\n    ss: expStart,\n    se: expEnd,\n    d: dynamicIndex,\n  } = importSpecifier\n  const exp = source.slice(expStart, expEnd)\n  if (dynamicIndex > -1) {\n    const inconsistentCjsInterop = !!config.legacy?.inconsistentCjsInterop\n    // rewrite `import('package')` to expose the default directly\n    str.overwrite(\n      expStart,\n      expEnd,\n      `import('${rewrittenUrl}').then(m => (${interopHelperStr})(m.default, ${inconsistentCjsInterop ? 0 : 1}))` +\n        getLineBreaks(exp),\n      { contentOnly: true },\n    )\n  } else {\n    const rawUrl = source.slice(start, end)\n    const rewritten = transformCjsImport(\n      exp,\n      rewrittenUrl,\n      rawUrl,\n      importIndex,\n      importer,\n      isNodeMode,\n      config,\n    )\n    if (rewritten) {\n      str.overwrite(expStart, expEnd, rewritten + getLineBreaks(exp), {\n        contentOnly: true,\n      })\n    } else {\n      // #1439 export * from '...'\n      str.overwrite(\n        start,\n        end,\n        rewrittenUrl + getLineBreaks(source.slice(start, end)),\n        {\n          contentOnly: true,\n        },\n      )\n    }\n  }\n}\n\n// get line breaks to preserve line count for not breaking source maps\nfunction getLineBreaks(str: string) {\n  return str.includes('\\n') ? '\\n'.repeat(str.split('\\n').length - 1) : ''\n}\n\ntype ImportNameSpecifier = { importedName: string; localName: string }\n\n/**\n * Detect import statements to a known optimized CJS dependency and provide\n * ES named imports interop. We do this by rewriting named imports to a variable\n * assignment to the corresponding property on the `module.exports` of the cjs\n * module. Note this doesn't support dynamic re-assignments from within the cjs\n * module.\n *\n * Note that es-module-lexer treats `export * from '...'` as an import as well,\n * so, we may encounter ExportAllDeclaration here, in which case `undefined`\n * will be returned.\n *\n * Credits \\@csr632 via #837\n */\nexport function transformCjsImport(\n  importExp: string,\n  url: string,\n  rawUrl: string,\n  importIndex: number,\n  importer: string,\n  isNodeMode: boolean,\n  config: ResolvedConfig,\n): string | undefined {\n  const node = parseAst(importExp).body[0]\n\n  // `export * from '...'` may cause unexpected problem, so give it a warning\n  if (\n    config.command === 'serve' &&\n    node.type === 'ExportAllDeclaration' &&\n    !node.exported\n  ) {\n    config.logger.warn(\n      colors.yellow(\n        `\\nUnable to interop \\`${importExp}\\` in ${importer}, this may lose module exports. Please export \"${rawUrl}\" as ESM or use named exports instead, e.g. \\`export { A, B } from \"${rawUrl}\"\\``,\n      ),\n    )\n  } else if (\n    node.type === 'ImportDeclaration' ||\n    node.type === 'ExportNamedDeclaration'\n  ) {\n    if (!node.specifiers.length) {\n      return `import \"${url}\"`\n    }\n\n    const importNames: ImportNameSpecifier[] = []\n    const exportNames: string[] = []\n    let defaultExports: string = ''\n    for (const spec of node.specifiers) {\n      if (spec.type === 'ImportSpecifier') {\n        const importedName = getIdentifierNameOrLiteralValue(spec.imported)\n        const localName = spec.local.name\n        importNames.push({ importedName, localName })\n      } else if (spec.type === 'ImportDefaultSpecifier') {\n        importNames.push({\n          importedName: 'default',\n          localName: spec.local.name,\n        })\n      } else if (spec.type === 'ImportNamespaceSpecifier') {\n        importNames.push({ importedName: '*', localName: spec.local.name })\n      } else if (spec.type === 'ExportSpecifier') {\n        // for ExportSpecifier, local name is same as imported name\n        // prefix the variable name to avoid clashing with other local variables\n        const importedName = getIdentifierNameOrLiteralValue(spec.local)\n        // we want to specify exported name as variable and re-export it\n        const exportedName = getIdentifierNameOrLiteralValue(spec.exported)\n        if (exportedName === 'default') {\n          defaultExports = makeLegalIdentifier(\n            `__vite__cjsExportDefault_${importIndex}`,\n          )\n          importNames.push({ importedName, localName: defaultExports })\n        } else {\n          const localName = `__vite__cjsExport${\n            spec.exported.type === 'Literal'\n              ? `L_${getHash(spec.exported.value)}`\n              : 'I_' + spec.exported.name\n          }`\n          importNames.push({ importedName, localName })\n          exportNames.push(\n            `${localName} as ${spec.exported.type === 'Literal' ? JSON.stringify(exportedName) : exportedName}`,\n          )\n        }\n      }\n    }\n\n    // If there is multiple import for same id in one file,\n    // importIndex will prevent the cjsModuleName to be duplicate\n    const cjsModuleName = makeLegalIdentifier(\n      `__vite__cjsImport${importIndex}_${rawUrl}`,\n    )\n    const lines: string[] = [`import ${cjsModuleName} from \"${url}\"`]\n    importNames.forEach(({ importedName, localName }) => {\n      if (importedName === '*') {\n        lines.push(\n          `const ${localName} = (${interopHelperStr})(${cjsModuleName}, ${+isNodeMode})`,\n        )\n      } else if (importedName === 'default') {\n        if (isNodeMode) {\n          lines.push(`const ${localName} = ${cjsModuleName}`)\n        } else {\n          lines.push(\n            `const ${localName} = !${cjsModuleName}.__esModule ? ${cjsModuleName} : ${cjsModuleName}.default`,\n          )\n        }\n      } else {\n        lines.push(`const ${localName} = ${cjsModuleName}[\"${importedName}\"]`)\n      }\n    })\n    if (defaultExports) {\n      lines.push(`export default ${defaultExports}`)\n    }\n    if (exportNames.length) {\n      lines.push(`export { ${exportNames.join(', ')} }`)\n    }\n\n    return lines.join('; ')\n  }\n}\n\nfunction getIdentifierNameOrLiteralValue(node: ESTree.ModuleExportName) {\n  return node.type === 'Identifier' ? node.name : node.value\n}\n\n// Copied from `client/client.ts`. Only needed so we can inline inject this function for classic workers.\nfunction __vite__injectQuery(url: string, queryToInject: string): string {\n  // skip urls that won't be handled by vite\n  if (url[0] !== '.' && url[0] !== '/') {\n    return url\n  }\n\n  // can't use pathname from URL since it may be relative like ../\n  const pathname = url.replace(/[?#].*$/, '')\n  const { search, hash } = new URL(url, 'http://vite.dev')\n\n  return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${\n    hash || ''\n  }`\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/importAnalysisBuild.ts",
    "content": "import path from 'node:path'\nimport MagicString from 'magic-string'\nimport type { ImportSpecifier } from 'es-module-lexer'\nimport { init, parse as parseImports } from 'es-module-lexer'\nimport type { SourceMap } from 'rolldown'\nimport { viteBuildImportAnalysisPlugin as nativeBuildImportAnalysisPlugin } from 'rolldown/experimental'\nimport type { RawSourceMap } from '@jridgewell/remapping'\nimport convertSourceMap from 'convert-source-map'\nimport { combineSourcemaps, generateCodeFrame, numberToPos } from '../utils'\nimport { type Plugin, perEnvironmentPlugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport { toOutputFilePathInJS } from '../build'\nimport { genSourceMapUrl } from '../server/sourcemap'\nimport type { PartialEnvironment } from '../baseEnvironment'\nimport { removedPureCssFilesCache } from './css'\n\ntype FileDep = {\n  url: string\n  runtime: boolean\n}\n\ntype VitePreloadErrorEvent = Event & { payload: Error }\n\n/**\n * A flag for injected helpers. This flag will be set to `false` if the output\n * target is not native es - so that injected helper logic can be conditionally\n * dropped.\n */\nexport const isModernFlag = `__VITE_IS_MODERN__`\nexport const preloadMethod = `__vitePreload`\nexport const preloadMarker = `__VITE_PRELOAD__`\n\nexport const preloadHelperId = '\\0vite/preload-helper.js'\nconst preloadMarkerRE = new RegExp(preloadMarker, 'g')\n\nfunction toRelativePath(filename: string, importer: string) {\n  const relPath = path.posix.relative(path.posix.dirname(importer), filename)\n  return relPath[0] === '.' ? relPath : `./${relPath}`\n}\n\nfunction findPreloadMarker(str: string, pos: number = 0): number {\n  preloadMarkerRE.lastIndex = pos\n  const result = preloadMarkerRE.exec(str)\n  return result?.index ?? -1\n}\n\n/**\n * Helper for preloading CSS and direct imports of async chunks in parallel to\n * the async chunk itself.\n */\n\nfunction detectScriptRel() {\n  const relList =\n    typeof document !== 'undefined' && document.createElement('link').relList\n  return relList && relList.supports && relList.supports('modulepreload')\n    ? 'modulepreload'\n    : 'preload'\n}\n\ndeclare const scriptRel: string\ndeclare const seen: Record<string, boolean>\nfunction preload(\n  baseModule: () => Promise<unknown>,\n  deps?: string[],\n  importerUrl?: string,\n) {\n  let promise: Promise<PromiseSettledResult<unknown>[] | void> =\n    Promise.resolve()\n  // @ts-expect-error __VITE_IS_MODERN__ will be replaced with boolean later\n  if (__VITE_IS_MODERN__ && deps && deps.length > 0) {\n    const links = document.getElementsByTagName('link')\n    const cspNonceMeta = document.querySelector<HTMLMetaElement>(\n      'meta[property=csp-nonce]',\n    )\n    // `.nonce` should be used to get along with nonce hiding (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#accessing_nonces_and_nonce_hiding)\n    // Firefox 67-74 uses modern chunks and supports CSP nonce, but does not support `.nonce`\n    // in that case fallback to getAttribute\n    const cspNonce = cspNonceMeta?.nonce || cspNonceMeta?.getAttribute('nonce')\n\n    // Promise.allSettled is not supported by Chrome 64-75, Firefox 67-70, Safari 11.1-12.1\n    function allSettled<T>(\n      promises: Array<T | PromiseLike<T>>,\n    ): Promise<PromiseSettledResult<T>[]> {\n      return Promise.all(\n        promises.map((p) =>\n          Promise.resolve(p).then(\n            (value: T) => ({ status: 'fulfilled' as const, value }),\n            (reason: unknown) => ({ status: 'rejected' as const, reason }),\n          ),\n        ),\n      )\n    }\n\n    promise = allSettled(\n      deps.map((dep) => {\n        // @ts-expect-error assetsURL is declared before preload.toString()\n        dep = assetsURL(dep, importerUrl)\n        if (dep in seen) return\n        seen[dep] = true\n        const isCss = dep.endsWith('.css')\n        const cssSelector = isCss ? '[rel=\"stylesheet\"]' : ''\n        const isBaseRelative = !!importerUrl\n\n        // check if the file is already preloaded by SSR markup\n        if (isBaseRelative) {\n          // When isBaseRelative is true then we have `importerUrl` and `dep` is\n          // already converted to an absolute URL by the `assetsURL` function\n          for (let i = links.length - 1; i >= 0; i--) {\n            const link = links[i]\n            // The `links[i].href` is an absolute URL thanks to browser doing the work\n            // for us. See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:idl-domstring-5\n            if (link.href === dep && (!isCss || link.rel === 'stylesheet')) {\n              return\n            }\n          }\n        } else if (\n          document.querySelector(`link[href=\"${dep}\"]${cssSelector}`)\n        ) {\n          return\n        }\n\n        const link = document.createElement('link')\n        link.rel = isCss ? 'stylesheet' : scriptRel\n        if (!isCss) {\n          link.as = 'script'\n        }\n        link.crossOrigin = ''\n        link.href = dep\n        if (cspNonce) {\n          link.setAttribute('nonce', cspNonce)\n        }\n        document.head.appendChild(link)\n        if (isCss) {\n          return new Promise((res, rej) => {\n            link.addEventListener('load', res)\n            link.addEventListener('error', () =>\n              rej(new Error(`Unable to preload CSS for ${dep}`)),\n            )\n          })\n        }\n      }),\n    )\n  }\n\n  function handlePreloadError(err: Error) {\n    const e = new Event('vite:preloadError', {\n      cancelable: true,\n    }) as VitePreloadErrorEvent\n    e.payload = err\n    window.dispatchEvent(e)\n    if (!e.defaultPrevented) {\n      throw err\n    }\n  }\n\n  return promise.then((res) => {\n    for (const item of res || []) {\n      if (item.status !== 'rejected') continue\n      handlePreloadError(item.reason)\n    }\n    return baseModule().catch(handlePreloadError)\n  })\n}\n\nfunction getPreloadCode(\n  environment: PartialEnvironment,\n  renderBuiltUrlBoolean: boolean,\n  isRelativeBase: boolean,\n) {\n  const { modulePreload } = environment.config.build\n\n  const scriptRel =\n    modulePreload && modulePreload.polyfill\n      ? `'modulepreload'`\n      : `/* @__PURE__ */ (${detectScriptRel.toString()})()`\n\n  // There are two different cases for the preload list format in __vitePreload\n  //\n  // __vitePreload(() => import(asyncChunk), [ ...deps... ])\n  //\n  // This is maintained to keep backwards compatibility as some users developed plugins\n  // using regex over this list to workaround the fact that module preload wasn't\n  // configurable.\n  const assetsURL =\n    renderBuiltUrlBoolean || isRelativeBase\n      ? // If `experimental.renderBuiltUrl` is used, the dependencies might be relative to the current chunk.\n        // If relative base is used, the dependencies are relative to the current chunk.\n        // The importerUrl is passed as third parameter to __vitePreload in this case\n        `function(dep, importerUrl) { return new URL(dep, importerUrl).href }`\n      : // If the base isn't relative, then the deps are relative to the projects `outDir` and the base\n        // is appended inside __vitePreload too.\n        `function(dep) { return ${JSON.stringify(environment.config.base)}+dep }`\n  const preloadCode = `const scriptRel = ${scriptRel};const assetsURL = ${assetsURL};const seen = {};export const ${preloadMethod} = ${preload.toString()}`\n  return preloadCode\n}\n\n/**\n * Build only. During serve this is performed as part of ./importAnalysis.\n */\nexport function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin[] {\n  const getInsertPreload = (environment: PartialEnvironment) =>\n    environment.config.consumer === 'client' &&\n    !config.isWorker &&\n    !config.build.lib\n\n  const renderBuiltUrl = config.experimental.renderBuiltUrl\n  const isRelativeBase = config.base === './' || config.base === ''\n\n  const plugin: Plugin = {\n    name: 'vite:build-import-analysis',\n\n    renderChunk(code, _, { format }) {\n      // make sure we only perform the preload logic in modern builds.\n      if (code.indexOf(isModernFlag) > -1) {\n        const re = new RegExp(isModernFlag, 'g')\n        const isModern = String(format === 'es')\n        const isModernWithPadding =\n          isModern + ' '.repeat(isModernFlag.length - isModern.length)\n        return {\n          code: code.replace(re, isModernWithPadding),\n          map: null,\n        }\n      }\n      return null\n    },\n\n    async generateBundle({ format }, bundle) {\n      if (format !== 'es') {\n        return\n      }\n\n      await init\n\n      // If preload is not enabled, we parse through each imports and remove any imports to pure CSS chunks\n      // as they are removed from the bundle\n      if (!getInsertPreload(this.environment)) {\n        const removedPureCssFiles = removedPureCssFilesCache.get(config)\n        if (removedPureCssFiles && removedPureCssFiles.size > 0) {\n          for (const file in bundle) {\n            const chunk = bundle[file]\n            if (chunk.type === 'chunk' && chunk.code.includes('import')) {\n              const code = chunk.code\n              let imports!: ImportSpecifier[]\n              try {\n                imports = parseImports(code)[0].filter((i) => i.d > -1)\n              } catch (e: any) {\n                const loc = numberToPos(code, e.idx)\n                this.error({\n                  name: e.name,\n                  message: e.message,\n                  stack: e.stack,\n                  cause: e.cause,\n                  pos: e.idx,\n                  loc: { ...loc, file: chunk.fileName },\n                  frame: generateCodeFrame(code, loc),\n                })\n              }\n\n              for (const imp of imports) {\n                const {\n                  n: name,\n                  s: start,\n                  e: end,\n                  ss: expStart,\n                  se: expEnd,\n                } = imp\n                let url = name\n                if (!url) {\n                  const rawUrl = code.slice(start, end)\n                  if (\n                    (rawUrl[0] === `\"` && rawUrl[rawUrl.length - 1] === `\"`) ||\n                    (rawUrl[0] === '`' && rawUrl[rawUrl.length - 1] === '`')\n                  )\n                    url = rawUrl.slice(1, -1)\n                }\n                if (!url) continue\n\n                const normalizedFile = path.posix.join(\n                  path.posix.dirname(chunk.fileName),\n                  url,\n                )\n                if (removedPureCssFiles.has(normalizedFile)) {\n                  // remove with Promise.resolve({}) while preserving source map location\n                  chunk.code =\n                    chunk.code.slice(0, expStart) +\n                    `Promise.resolve({${''.padEnd(expEnd - expStart - 19, ' ')}})` +\n                    chunk.code.slice(expEnd)\n                }\n              }\n            }\n          }\n        }\n        return\n      }\n      const buildSourcemap = this.environment.config.build.sourcemap\n      const { modulePreload } = this.environment.config.build\n\n      for (const file in bundle) {\n        const chunk = bundle[file]\n        // can't use chunk.dynamicImports.length here since some modules e.g.\n        // dynamic import to constant json may get inlined.\n        if (chunk.type === 'chunk' && chunk.code.indexOf(preloadMarker) > -1) {\n          const code = chunk.code\n          let imports!: ImportSpecifier[]\n          try {\n            imports = parseImports(code)[0].filter((i) => i.d > -1)\n          } catch (e: any) {\n            const loc = numberToPos(code, e.idx)\n            this.error({\n              name: e.name,\n              message: e.message,\n              stack: e.stack,\n              cause: e.cause,\n              pos: e.idx,\n              loc: { ...loc, file: chunk.fileName },\n              frame: generateCodeFrame(code, loc),\n            })\n          }\n\n          const s = new MagicString(code)\n          const rewroteMarkerStartPos = new Set() // position of the leading double quote\n\n          const fileDeps: FileDep[] = []\n          const addFileDep = (\n            url: string,\n            runtime: boolean = false,\n          ): number => {\n            const index = fileDeps.findIndex((dep) => dep.url === url)\n            if (index === -1) {\n              return fileDeps.push({ url, runtime }) - 1\n            } else {\n              return index\n            }\n          }\n\n          if (imports.length) {\n            for (let index = 0; index < imports.length; index++) {\n              // To handle escape sequences in specifier strings, the .n field will be provided where possible.\n              const {\n                n: name,\n                s: start,\n                e: end,\n                ss: expStart,\n                se: expEnd,\n              } = imports[index]\n              // check the chunk being imported\n              let url = name\n              if (!url) {\n                const rawUrl = code.slice(start, end)\n                if (\n                  (rawUrl[0] === `\"` && rawUrl[rawUrl.length - 1] === `\"`) ||\n                  (rawUrl[0] === '`' && rawUrl[rawUrl.length - 1] === '`')\n                )\n                  url = rawUrl.slice(1, -1)\n              }\n              const deps = new Set<string>()\n              let hasRemovedPureCssChunk = false\n\n              let normalizedFile: string | undefined = undefined\n\n              if (url) {\n                normalizedFile = path.posix.join(\n                  path.posix.dirname(chunk.fileName),\n                  url,\n                )\n\n                const ownerFilename = chunk.fileName\n                // literal import - trace direct imports and add to deps\n                const analyzed: Set<string> = new Set<string>()\n                const addDeps = (filename: string) => {\n                  if (filename === ownerFilename) return\n                  if (analyzed.has(filename)) return\n                  analyzed.add(filename)\n                  const chunk = bundle[filename]\n                  if (chunk) {\n                    deps.add(chunk.fileName)\n                    if (chunk.type === 'chunk') {\n                      chunk.imports.forEach(addDeps)\n                      // Ensure that the css imported by current chunk is loaded after the dependencies.\n                      // So the style of current chunk won't be overwritten unexpectedly.\n                      chunk.viteMetadata!.importedCss.forEach((file) => {\n                        deps.add(file)\n                      })\n                    }\n                  } else {\n                    const removedPureCssFiles =\n                      removedPureCssFilesCache.get(config)!\n                    const chunk = removedPureCssFiles.get(filename)\n                    if (chunk) {\n                      if (chunk.viteMetadata!.importedCss.size) {\n                        chunk.viteMetadata!.importedCss.forEach((file) => {\n                          deps.add(file)\n                        })\n                        hasRemovedPureCssChunk = true\n                      }\n\n                      s.update(expStart, expEnd, 'Promise.resolve({})')\n                    }\n                  }\n                }\n                addDeps(normalizedFile)\n              }\n\n              let markerStartPos = findPreloadMarker(code, end)\n              // fix issue #3051\n              if (markerStartPos === -1 && imports.length === 1) {\n                markerStartPos = findPreloadMarker(code)\n              }\n\n              if (markerStartPos > 0) {\n                // the dep list includes the main chunk, so only need to reload when there are actual other deps.\n                let depsArray =\n                  deps.size > 1 ||\n                  // main chunk is removed\n                  (hasRemovedPureCssChunk && deps.size > 0)\n                    ? modulePreload === false\n                      ? // CSS deps use the same mechanism as module preloads, so even if disabled,\n                        // we still need to pass these deps to the preload helper in dynamic imports.\n                        [...deps].filter((d) => d.endsWith('.css'))\n                      : [...deps]\n                    : []\n\n                const resolveDependencies = modulePreload\n                  ? modulePreload.resolveDependencies\n                  : undefined\n                if (resolveDependencies && normalizedFile) {\n                  // We can't let the user remove css deps as these aren't really preloads, they are just using\n                  // the same mechanism as module preloads for this chunk\n                  const cssDeps: string[] = []\n                  const otherDeps: string[] = []\n                  for (const dep of depsArray) {\n                    ;(dep.endsWith('.css') ? cssDeps : otherDeps).push(dep)\n                  }\n                  depsArray = [\n                    ...resolveDependencies(normalizedFile, otherDeps, {\n                      hostId: file,\n                      hostType: 'js',\n                    }),\n                    ...cssDeps,\n                  ]\n                }\n\n                let renderedDeps: number[]\n                if (renderBuiltUrl) {\n                  renderedDeps = depsArray.map((dep) => {\n                    const replacement = toOutputFilePathInJS(\n                      this.environment,\n                      dep,\n                      'asset',\n                      chunk.fileName,\n                      'js',\n                      toRelativePath,\n                    )\n\n                    if (typeof replacement === 'string') {\n                      return addFileDep(replacement)\n                    }\n\n                    return addFileDep(replacement.runtime, true)\n                  })\n                } else {\n                  renderedDeps = depsArray.map((d) =>\n                    // Don't include the assets dir if the default asset file names\n                    // are used, the path will be reconstructed by the import preload helper\n                    isRelativeBase\n                      ? addFileDep(toRelativePath(d, file))\n                      : addFileDep(d),\n                  )\n                }\n\n                s.update(\n                  markerStartPos,\n                  markerStartPos + preloadMarker.length,\n                  renderedDeps.length > 0\n                    ? `__vite__mapDeps([${renderedDeps.join(',')}])`\n                    : `[]`,\n                )\n                rewroteMarkerStartPos.add(markerStartPos)\n              }\n            }\n          }\n\n          if (fileDeps.length > 0) {\n            const fileDepsCode = `[${fileDeps\n              .map((fileDep) =>\n                fileDep.runtime ? fileDep.url : JSON.stringify(fileDep.url),\n              )\n              .join(',')}]`\n\n            const mapDepsCode = `const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=${fileDepsCode})))=>i.map(i=>d[i]);\\n`\n\n            // inject extra code at the top or next line of hashbang\n            if (code.startsWith('#!')) {\n              s.prependLeft(code.indexOf('\\n') + 1, mapDepsCode)\n            } else {\n              s.prepend(mapDepsCode)\n            }\n          }\n\n          // there may still be markers due to inlined dynamic imports, remove\n          // all the markers regardless\n          let markerStartPos = findPreloadMarker(code)\n          while (markerStartPos >= 0) {\n            if (!rewroteMarkerStartPos.has(markerStartPos)) {\n              s.update(\n                markerStartPos,\n                markerStartPos + preloadMarker.length,\n                'void 0',\n              )\n            }\n            markerStartPos = findPreloadMarker(\n              code,\n              markerStartPos + preloadMarker.length,\n            )\n          }\n\n          if (s.hasChanged()) {\n            chunk.code = s.toString()\n            if (buildSourcemap && chunk.map) {\n              const nextMap = s.generateMap({\n                source: chunk.fileName,\n                hires: 'boundary',\n              })\n              const originalFile = chunk.map.file\n              const map = combineSourcemaps(chunk.fileName, [\n                nextMap as RawSourceMap,\n                chunk.map as RawSourceMap,\n              ]) as SourceMap\n              map.toUrl = () => genSourceMapUrl(map)\n              if (originalFile) {\n                map.file = originalFile\n              }\n\n              const originalDebugId = chunk.map.debugId\n              chunk.map = map\n\n              if (buildSourcemap === 'inline') {\n                chunk.code = chunk.code.replace(\n                  convertSourceMap.mapFileCommentRegex,\n                  '',\n                )\n                chunk.code += `\\n//# sourceMappingURL=${genSourceMapUrl(map)}`\n              } else {\n                if (originalDebugId) {\n                  map.debugId = originalDebugId\n                }\n                const mapAsset = bundle[chunk.fileName + '.map']\n                if (mapAsset && mapAsset.type === 'asset') {\n                  mapAsset.source = map.toString()\n                }\n              }\n            }\n          }\n        }\n      }\n    },\n  }\n\n  return [\n    plugin,\n    perEnvironmentPlugin('native:import-analysis-build', (environment) => {\n      const preloadCode = getPreloadCode(\n        environment,\n        !!renderBuiltUrl,\n        isRelativeBase,\n      )\n      return nativeBuildImportAnalysisPlugin({\n        preloadCode,\n        insertPreload: getInsertPreload(environment),\n        // this field looks redundant, put a dummy value for now\n        optimizeModulePreloadRelativePaths: false,\n        renderBuiltUrl: !!renderBuiltUrl,\n        isRelativeBase,\n      })\n    }),\n  ]\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/importMetaGlob.ts",
    "content": "import { isAbsolute, posix } from 'node:path'\nimport picomatch from 'picomatch'\nimport { stripLiteral } from 'strip-literal'\nimport colors from 'picocolors'\nimport type { ESTree } from 'rolldown/utils'\nimport type { CustomPluginOptions, RollupError } from 'rolldown'\nimport MagicString from 'magic-string'\nimport { stringifyQuery } from 'ufo'\nimport { parseAstAsync } from 'rolldown/parseAst'\nimport { escapePath, glob } from 'tinyglobby'\nimport { viteImportGlobPlugin as nativeImportGlobPlugin } from 'rolldown/experimental'\nimport type { GeneralImportGlobOptions } from '#types/importGlob'\nimport type { Plugin } from '../plugin'\nimport type { EnvironmentModuleNode } from '../server/moduleGraph'\nimport type { ResolvedConfig } from '../config'\nimport { evalValue, normalizePath, transformStableResult } from '../utils'\nimport type { Logger } from '../logger'\nimport { slash } from '../../shared/utils'\nimport type { Environment } from '../environment'\n\nexport interface ParsedImportGlob {\n  index: number\n  globs: string[]\n  globsResolved: string[]\n  isRelative: boolean\n  options: ParsedGeneralImportGlobOptions\n  start: number\n  end: number\n  onlyKeys: boolean\n  onlyValues: boolean\n}\n\ninterface ParsedGeneralImportGlobOptions extends GeneralImportGlobOptions {\n  query?: string\n}\n\nexport function importGlobPlugin(config: ResolvedConfig): Plugin {\n  if (config.isBundled) {\n    return nativeImportGlobPlugin({\n      root: config.root,\n      sourcemap: !!config.build.sourcemap,\n      restoreQueryExtension: config.experimental.importGlobRestoreExtension,\n    })\n  }\n\n  const importGlobMaps = new Map<\n    Environment,\n    Map<string, Array<(file: string) => boolean>>\n  >()\n\n  return {\n    name: 'vite:import-glob',\n    buildStart() {\n      importGlobMaps.clear()\n    },\n    transform: {\n      filter: { code: 'import.meta.glob' },\n      async handler(code, id) {\n        const result = await transformGlobImport(\n          code,\n          id,\n          config.root,\n          (im, _, options) =>\n            this.resolve(im, id, options).then((i) => i?.id || im),\n          config.experimental.importGlobRestoreExtension,\n          config.logger,\n        )\n        if (result) {\n          const allGlobs = result.matches.map((i) => i.globsResolved)\n          if (!importGlobMaps.has(this.environment)) {\n            importGlobMaps.set(this.environment, new Map())\n          }\n\n          const globMatchers = allGlobs.map((globs) => {\n            const affirmed: string[] = []\n            const negated: string[] = []\n            for (const glob of globs) {\n              if (glob[0] === '!') {\n                negated.push(glob.slice(1))\n              } else {\n                affirmed.push(glob)\n              }\n            }\n            const affirmedMatcher = picomatch(affirmed)\n            const negatedMatcher = picomatch(negated)\n\n            return (file: string) => {\n              // (glob1 || glob2) && !(glob3 || glob4)...\n              return (\n                (affirmed.length === 0 || affirmedMatcher(file)) &&\n                !(negated.length > 0 && negatedMatcher(file))\n              )\n            }\n          })\n          importGlobMaps.get(this.environment)!.set(id, globMatchers)\n\n          return transformStableResult(result.s, id, config)\n        }\n      },\n    },\n    hotUpdate({ type, file, modules: oldModules }) {\n      if (type === 'update') return\n\n      const importGlobMap = importGlobMaps.get(this.environment)\n      if (!importGlobMap) return\n\n      const modules: EnvironmentModuleNode[] = []\n      for (const [id, globMatchers] of importGlobMap) {\n        if (globMatchers.some((matcher) => matcher(file))) {\n          const mod = this.environment.moduleGraph.getModuleById(id)\n          if (mod) modules.push(mod)\n        }\n      }\n      return modules.length > 0 ? [...oldModules, ...modules] : undefined\n    },\n  }\n}\n\nconst importGlobRE = /\\bimport\\.meta\\.glob(?:<\\w+>)?\\s*\\(/g\nconst objectKeysRE = /\\bObject\\.keys\\(\\s*$/\nconst objectValuesRE = /\\bObject\\.values\\(\\s*$/\n\nconst knownOptions = {\n  as: ['string'],\n  eager: ['boolean'],\n  import: ['string'],\n  exhaustive: ['boolean'],\n  query: ['object', 'string'],\n  base: ['string'],\n}\n\nconst forceDefaultAs = ['raw', 'url']\n\nfunction err(e: string, pos: number) {\n  const error = new Error(e) as RollupError\n  error.pos = pos\n  return error\n}\n\nfunction parseGlobOptions(\n  rawOpts: string,\n  optsStartIndex: number,\n  logger?: Logger,\n): ParsedGeneralImportGlobOptions {\n  let opts: GeneralImportGlobOptions = {}\n  try {\n    opts = evalValue(rawOpts)\n  } catch {\n    throw err(\n      'Vite is unable to parse the glob options as the value is not static',\n      optsStartIndex,\n    )\n  }\n\n  if (opts == null) {\n    return {}\n  }\n\n  for (const key in opts) {\n    if (!(key in knownOptions)) {\n      throw err(`Unknown glob option \"${key}\"`, optsStartIndex)\n    }\n    const allowedTypes = knownOptions[key as keyof typeof knownOptions]\n    const valueType = typeof opts[key as keyof GeneralImportGlobOptions]\n    if (!allowedTypes.includes(valueType)) {\n      throw err(\n        `Expected glob option \"${key}\" to be of type ${allowedTypes.join(\n          ' or ',\n        )}, but got ${valueType}`,\n        optsStartIndex,\n      )\n    }\n  }\n\n  if (opts.base) {\n    if (opts.base[0] === '!') {\n      throw err('Option \"base\" cannot start with \"!\"', optsStartIndex)\n    } else if (\n      opts.base[0] !== '/' &&\n      !opts.base.startsWith('./') &&\n      !opts.base.startsWith('../')\n    ) {\n      throw err(\n        `Option \"base\" must start with '/', './' or '../', but got \"${opts.base}\"`,\n        optsStartIndex,\n      )\n    }\n  }\n\n  if (typeof opts.query === 'object') {\n    for (const key in opts.query) {\n      const value = opts.query[key]\n      if (!['string', 'number', 'boolean'].includes(typeof value)) {\n        throw err(\n          `Expected glob option \"query.${key}\" to be of type string, number, or boolean, but got ${typeof value}`,\n          optsStartIndex,\n        )\n      }\n    }\n    // normalize query as string so it's easier to handle later\n    opts.query = stringifyQuery(opts.query)\n  }\n\n  if (opts.as && logger) {\n    const importSuggestion = forceDefaultAs.includes(opts.as)\n      ? `, import: 'default'`\n      : ''\n    logger.warn(\n      colors.yellow(\n        `The glob option \"as\" has been deprecated in favour of \"query\". Please update \\`as: '${opts.as}'\\` to \\`query: '?${opts.as}'${importSuggestion}\\`.`,\n      ),\n    )\n  }\n\n  // validate `import` option based on `as` option\n  if (opts.as && forceDefaultAs.includes(opts.as)) {\n    if (opts.import && opts.import !== 'default' && opts.import !== '*')\n      throw err(\n        `Option \"import\" can only be \"default\" or \"*\" when \"as\" is \"${opts.as}\", but got \"${opts.import}\"`,\n        optsStartIndex,\n      )\n    opts.import = opts.import || 'default'\n  }\n\n  if (opts.as && opts.query)\n    throw err(\n      'Options \"as\" and \"query\" cannot be used together',\n      optsStartIndex,\n    )\n\n  if (opts.as) opts.query = opts.as\n\n  if (opts.query && opts.query[0] !== '?') opts.query = `?${opts.query}`\n\n  return opts as ParsedGeneralImportGlobOptions\n}\n\nexport async function parseImportGlob(\n  code: string,\n  importer: string | undefined,\n  root: string,\n  resolveId: IdResolver,\n  logger?: Logger,\n): Promise<ParsedImportGlob[]> {\n  let cleanCode: string\n  try {\n    cleanCode = stripLiteral(code)\n  } catch {\n    // skip invalid js code\n    return []\n  }\n  const matches = Array.from(cleanCode.matchAll(importGlobRE))\n\n  const tasks = matches.map(async (match, index) => {\n    const start = match.index!\n\n    const err = (msg: string) => {\n      const e = new Error(`Invalid glob import syntax: ${msg}`)\n      ;(e as any).pos = start\n      return e\n    }\n\n    const end =\n      findCorrespondingCloseParenthesisPosition(\n        cleanCode,\n        start + match[0].length,\n      ) + 1\n    if (end <= 0) {\n      throw err('Close parenthesis not found')\n    }\n\n    const statementCode = code.slice(start, end)\n\n    const rootAst = (await parseAstAsync(statementCode)).body[0]\n    if (rootAst.type !== 'ExpressionStatement') {\n      throw err(`Expect CallExpression, got ${rootAst.type}`)\n    }\n    const ast = rootAst.expression\n    if (ast.type !== 'CallExpression') {\n      throw err(`Expect CallExpression, got ${ast.type}`)\n    }\n    if (ast.arguments.length < 1 || ast.arguments.length > 2)\n      throw err(`Expected 1-2 arguments, but got ${ast.arguments.length}`)\n\n    const arg1 = ast.arguments[0]\n    const arg2 = ast.arguments[1]\n\n    const globs: string[] = []\n\n    const validateLiteral = (\n      element: ESTree.Expression | ESTree.SpreadElement | null,\n    ) => {\n      if (!element) return\n      if (element.type === 'Literal') {\n        if (typeof element.value !== 'string')\n          throw err(\n            `Expected glob to be a string, but got \"${typeof element.value}\"`,\n          )\n        globs.push(element.value)\n      } else if (element.type === 'TemplateLiteral') {\n        if (element.expressions.length !== 0) {\n          throw err(\n            `Expected glob to be a string, but got dynamic template literal`,\n          )\n        }\n        globs.push(element.quasis[0].value.raw)\n      } else {\n        throw err('Could only use literals')\n      }\n    }\n\n    if (arg1.type === 'ArrayExpression') {\n      for (const element of arg1.elements) {\n        validateLiteral(element)\n      }\n    } else {\n      validateLiteral(arg1)\n    }\n\n    // arg2\n    let options: ParsedGeneralImportGlobOptions = {}\n    if (arg2) {\n      if (arg2.type !== 'ObjectExpression')\n        throw err(\n          `Expected the second argument to be an object literal, but got \"${arg2.type}\"`,\n        )\n\n      options = parseGlobOptions(\n        code.slice(start + arg2.start, start + arg2.end),\n        start + arg2.start,\n        logger,\n      )\n    }\n\n    const globsResolved = await Promise.all(\n      globs.map((glob) =>\n        toAbsoluteGlob(glob, root, importer, resolveId, options.base),\n      ),\n    )\n    const isRelative = globs.every((i) => '.!'.includes(i[0]))\n    const sliceCode = cleanCode.slice(0, start)\n    const onlyKeys = objectKeysRE.test(sliceCode)\n    let onlyValues = false\n    if (!onlyKeys) {\n      onlyValues = objectValuesRE.test(sliceCode)\n    }\n\n    return {\n      index,\n      globs,\n      globsResolved,\n      isRelative,\n      options,\n      start,\n      end,\n      onlyKeys,\n      onlyValues,\n    }\n  })\n\n  return (await Promise.all(tasks)).filter(Boolean)\n}\n\nfunction findCorrespondingCloseParenthesisPosition(\n  cleanCode: string,\n  openPos: number,\n) {\n  const closePos = cleanCode.indexOf(')', openPos)\n  if (closePos < 0) return -1\n\n  if (!cleanCode.slice(openPos, closePos).includes('(')) return closePos\n\n  let remainingParenthesisCount = 0\n  const cleanCodeLen = cleanCode.length\n  for (let pos = openPos; pos < cleanCodeLen; pos++) {\n    switch (cleanCode[pos]) {\n      case '(': {\n        remainingParenthesisCount++\n        break\n      }\n      case ')': {\n        remainingParenthesisCount--\n        if (remainingParenthesisCount <= 0) {\n          return pos\n        }\n      }\n    }\n  }\n  return -1\n}\n\nconst importPrefix = '__vite_glob_'\n\nconst { basename, dirname, relative } = posix\n\nexport interface TransformGlobImportResult {\n  s: MagicString\n  matches: ParsedImportGlob[]\n  files: Set<string>\n}\n\n/**\n * @param optimizeExport for dynamicImportVar plugin don't need to optimize export.\n */\nexport async function transformGlobImport(\n  code: string,\n  id: string,\n  root: string,\n  resolveId: IdResolver,\n  restoreQueryExtension = false,\n  logger?: Logger,\n): Promise<TransformGlobImportResult | null> {\n  id = slash(id)\n  root = slash(root)\n  const isVirtual = isVirtualModule(id)\n  const dir = isVirtual ? undefined : dirname(id)\n  const matches = await parseImportGlob(\n    code,\n    isVirtual ? undefined : id,\n    root,\n    resolveId,\n    logger,\n  )\n  const matchedFiles = new Set<string>()\n\n  if (!matches.length) return null\n\n  const s = new MagicString(code)\n\n  const staticImports = (\n    await Promise.all(\n      matches.map(\n        async ({\n          globsResolved,\n          isRelative,\n          options,\n          index,\n          start,\n          end,\n          onlyKeys,\n          onlyValues,\n        }) => {\n          const cwd = getCommonBase(globsResolved) ?? root\n          const files = (\n            await glob(globsResolved, {\n              absolute: true,\n              cwd,\n              dot: !!options.exhaustive,\n              expandDirectories: false,\n              ignore: options.exhaustive ? [] : ['**/node_modules/**'],\n              extglob: false,\n            })\n          )\n            .filter((file) => file !== id)\n            .sort()\n\n          const objectProps: string[] = []\n          const staticImports: string[] = []\n\n          const resolvePaths = (file: string) => {\n            if (!dir) {\n              if (!options.base && isRelative)\n                throw new Error(\n                  \"In virtual modules, all globs must start with '/'\",\n                )\n              const importPath = `/${relative(root, file)}`\n              let filePath = options.base\n                ? `${relative(posix.join(root, options.base), file)}`\n                : importPath\n              if (\n                options.base &&\n                !filePath.startsWith('./') &&\n                !filePath.startsWith('../')\n              ) {\n                filePath = `./${filePath}`\n              }\n              return { filePath, importPath }\n            }\n\n            let importPath = relative(dir, file)\n            if (!importPath.startsWith('./') && !importPath.startsWith('../')) {\n              importPath = `./${importPath}`\n            }\n\n            let filePath: string\n            if (options.base) {\n              const resolvedBasePath = options.base[0] === '/' ? root : dir\n              filePath = relative(\n                posix.join(resolvedBasePath, options.base),\n                file,\n              )\n              if (!filePath.startsWith('./') && !filePath.startsWith('../')) {\n                filePath = `./${filePath}`\n              }\n              if (options.base[0] === '/') {\n                importPath = `/${relative(root, file)}`\n              }\n            } else if (isRelative) {\n              filePath = importPath\n            } else {\n              filePath = relative(root, file)\n              if (!filePath.startsWith('./') && !filePath.startsWith('../')) {\n                filePath = `/${filePath}`\n              }\n            }\n\n            return { filePath, importPath }\n          }\n\n          files.forEach((file, i) => {\n            const paths = resolvePaths(file)\n            const filePath = paths.filePath\n            let importPath = paths.importPath\n            let importQuery = options.query ?? ''\n\n            if (onlyKeys) {\n              objectProps.push(`${JSON.stringify(filePath)}: 0`)\n              return\n            }\n\n            if (importQuery && importQuery !== '?raw') {\n              const fileExtension = basename(file).split('.').slice(-1)[0]\n              if (fileExtension && restoreQueryExtension)\n                importQuery = `${importQuery}&lang.${fileExtension}`\n            }\n\n            importPath = `${importPath}${importQuery}`\n\n            const importKey =\n              options.import && options.import !== '*'\n                ? options.import\n                : undefined\n\n            if (options.eager) {\n              const variableName = `${importPrefix}${index}_${i}`\n              const expression = importKey\n                ? `{ ${importKey} as ${variableName} }`\n                : `* as ${variableName}`\n              staticImports.push(\n                `import ${expression} from ${JSON.stringify(importPath)}`,\n              )\n              objectProps.push(\n                onlyValues\n                  ? `${variableName}`\n                  : `${JSON.stringify(filePath)}: ${variableName}`,\n              )\n            } else {\n              let importStatement = `import(${JSON.stringify(importPath)})`\n              if (importKey)\n                importStatement += `.then(m => m[${JSON.stringify(importKey)}])`\n              objectProps.push(\n                onlyValues\n                  ? `() => ${importStatement}`\n                  : `${JSON.stringify(filePath)}: () => ${importStatement}`,\n              )\n            }\n          })\n\n          files.forEach((i) => matchedFiles.add(i))\n\n          const originalLineBreakCount =\n            code.slice(start, end).match(/\\n/g)?.length ?? 0\n          const lineBreaks =\n            originalLineBreakCount > 0\n              ? '\\n'.repeat(originalLineBreakCount)\n              : ''\n          let replacement = ''\n          if (onlyKeys) {\n            replacement = `{${objectProps.join(',')}${lineBreaks}}`\n          } else if (onlyValues) {\n            replacement = `[${objectProps.join(',')}${lineBreaks}]`\n          } else {\n            replacement = `/* #__PURE__ */ Object.assign({${objectProps.join(\n              ',',\n            )}${lineBreaks}})`\n          }\n\n          s.overwrite(start, end, replacement)\n\n          return staticImports\n        },\n      ),\n    )\n  ).flat()\n\n  if (staticImports.length) s.prepend(`${staticImports.join(';')};`)\n\n  return {\n    s,\n    matches,\n    files: matchedFiles,\n  }\n}\n\ntype IdResolver = (\n  id: string,\n  importer?: string,\n  options?: {\n    attributes?: Record<string, string>\n    custom?: CustomPluginOptions\n    isEntry?: boolean\n    skipSelf?: boolean\n  },\n) => Promise<string | undefined> | string | undefined\n\nfunction globSafePath(path: string) {\n  // slash path to ensure \\ is converted to / as \\ could lead to a double escape scenario\n  return escapePath(normalizePath(path))\n}\n\nfunction lastNthChar(str: string, n: number) {\n  return str.charAt(str.length - 1 - n)\n}\n\nfunction globSafeResolvedPath(resolved: string, glob: string) {\n  // we have to escape special glob characters in the resolved path, but keep the user specified globby suffix\n  // walk back both strings until a character difference is found\n  // then slice up the resolved path at that pos and escape the first part\n  let numEqual = 0\n  const maxEqual = Math.min(resolved.length, glob.length)\n  while (\n    numEqual < maxEqual &&\n    lastNthChar(resolved, numEqual) === lastNthChar(glob, numEqual)\n  ) {\n    numEqual += 1\n  }\n  const staticPartEnd = resolved.length - numEqual\n  const staticPart = resolved.slice(0, staticPartEnd)\n  const dynamicPart = resolved.slice(staticPartEnd)\n  return globSafePath(staticPart) + dynamicPart\n}\n\nexport async function toAbsoluteGlob(\n  glob: string,\n  root: string,\n  importer: string | undefined,\n  resolveId: IdResolver,\n  base?: string,\n): Promise<string> {\n  let pre = ''\n  if (glob[0] === '!') {\n    pre = '!'\n    glob = glob.slice(1)\n  }\n  root = globSafePath(root)\n  let dir\n  if (base) {\n    if (base[0] === '/') {\n      dir = posix.join(root, base)\n    } else {\n      dir = posix.resolve(\n        importer ? globSafePath(dirname(importer)) : root,\n        base,\n      )\n    }\n  } else {\n    dir = importer ? globSafePath(dirname(importer)) : root\n  }\n\n  if (glob[0] === '/') return pre + posix.join(root, glob.slice(1))\n  if (glob.startsWith('./')) return pre + posix.join(dir, glob.slice(2))\n  if (glob.startsWith('../')) return pre + posix.join(dir, glob)\n  if (glob.startsWith('**')) return pre + glob\n\n  const isSubImportsPattern = glob[0] === '#' && glob.includes('*')\n\n  const resolved = normalizePath(\n    (await resolveId(glob, importer, {\n      custom: { 'vite:import-glob': { isSubImportsPattern } },\n    })) || glob,\n  )\n  if (isAbsolute(resolved)) {\n    return pre + globSafeResolvedPath(resolved, glob)\n  }\n\n  throw new Error(\n    `Invalid glob: \"${glob}\" (resolved: \"${resolved}\"). It must start with '/' or './'`,\n  )\n}\n\nexport function getCommonBase(globsResolved: string[]): null | string {\n  const bases = globsResolved\n    .filter((g) => g[0] !== '!')\n    .map((glob) => {\n      let { base } = picomatch.scan(glob)\n      // `scan('a/foo.js')` returns `base: 'a/foo.js'`\n      if (posix.basename(base).includes('.')) base = posix.dirname(base)\n\n      return base\n    })\n\n  if (!bases.length) return null\n\n  let commonAncestor = ''\n  const dirS = bases[0].split('/')\n  for (let i = 0; i < dirS.length; i++) {\n    const candidate = dirS.slice(0, i + 1).join('/')\n    if (bases.every((base) => base.startsWith(candidate)))\n      commonAncestor = candidate\n    else break\n  }\n  if (!commonAncestor) commonAncestor = '/'\n\n  return commonAncestor\n}\n\nexport function isVirtualModule(id: string): boolean {\n  // https://vite.dev/guide/api-plugin.html#virtual-modules-convention\n  return id.startsWith('virtual:') || id[0] === '\\0' || !id.includes('/')\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/index.ts",
    "content": "import aliasPlugin, { type ResolverFunction } from '@rollup/plugin-alias'\nimport type { ObjectHook } from 'rolldown'\nimport {\n  viteAliasPlugin as nativeAliasPlugin,\n  viteJsonPlugin as nativeJsonPlugin,\n  viteWasmFallbackPlugin as nativeWasmFallbackPlugin,\n  oxcRuntimePlugin,\n} from 'rolldown/experimental'\nimport type { PluginHookUtils, ResolvedConfig } from '../config'\nimport {\n  type HookHandler,\n  type Plugin,\n  type PluginWithRequiredHook,\n} from '../plugin'\nimport { watchPackageDataPlugin } from '../packages'\nimport { oxcResolvePlugin } from './resolve'\nimport { optimizedDepsPlugin } from './optimizedDeps'\nimport { importAnalysisPlugin } from './importAnalysis'\nimport { cssAnalysisPlugin, cssPlugin, cssPostPlugin } from './css'\nimport { assetPlugin } from './asset'\nimport { clientInjectionsPlugin } from './clientInjections'\nimport { buildHtmlPlugin, htmlInlineProxyPlugin } from './html'\nimport { wasmHelperPlugin } from './wasm'\nimport { modulePreloadPolyfillPlugin } from './modulePreloadPolyfill'\nimport { webWorkerPlugin } from './worker'\nimport { preAliasPlugin } from './preAlias'\nimport { definePlugin } from './define'\nimport { workerImportMetaUrlPlugin } from './workerImportMetaUrl'\nimport { assetImportMetaUrlPlugin } from './assetImportMetaUrl'\nimport { dynamicImportVarsPlugin } from './dynamicImportVars'\nimport { importGlobPlugin } from './importMetaGlob'\nimport {\n  type PluginFilter,\n  type TransformHookFilter,\n  createFilterForTransform,\n  createIdFilter,\n} from './pluginFilter'\nimport { forwardConsolePlugin } from './forwardConsole'\nimport { oxcPlugin } from './oxc'\nimport { esbuildBannerFooterCompatPlugin } from './esbuildBannerFooterCompatPlugin'\n\nexport async function resolvePlugins(\n  config: ResolvedConfig,\n  prePlugins: Plugin[],\n  normalPlugins: Plugin[],\n  postPlugins: Plugin[],\n): Promise<Plugin[]> {\n  const isBuild = config.command === 'build'\n  const isBundled = config.isBundled\n  const isWorker = config.isWorker\n  const buildPlugins = isBundled\n    ? await (await import('../build')).resolveBuildPlugins(config)\n    : { pre: [], post: [] }\n  const { modulePreload } = config.build\n\n  return [\n    !isBundled ? optimizedDepsPlugin() : null,\n    !isWorker ? watchPackageDataPlugin(config.packageCache) : null,\n    !isBundled ? preAliasPlugin(config) : null,\n    isBundled && !config.resolve.alias.some((v) => v.customResolver)\n      ? nativeAliasPlugin({\n          entries: config.resolve.alias.map((item) => {\n            return {\n              find: item.find,\n              replacement: item.replacement,\n            }\n          }),\n        })\n      : aliasPlugin({\n          // @ts-expect-error aliasPlugin receives rollup types\n          entries: config.resolve.alias,\n          customResolver: viteAliasCustomResolver,\n        }),\n\n    ...prePlugins,\n\n    modulePreload !== false && modulePreload.polyfill\n      ? modulePreloadPolyfillPlugin(config)\n      : null,\n    ...oxcResolvePlugin(\n      {\n        root: config.root,\n        isProduction: config.isProduction,\n        isBuild,\n        packageCache: config.packageCache,\n        asSrc: true,\n        optimizeDeps: true,\n        externalize: true,\n        legacyInconsistentCjsInterop: config.legacy?.inconsistentCjsInterop,\n      },\n      isWorker\n        ? { ...config, consumer: 'client', optimizeDepsPluginNames: [] }\n        : undefined,\n    ),\n    htmlInlineProxyPlugin(config),\n    cssPlugin(config),\n    esbuildBannerFooterCompatPlugin(config),\n    // @oxc-project/runtime resolution is handled by rolldown in build\n    config.oxc !== false && !isBundled ? oxcRuntimePlugin() : null,\n    config.oxc !== false ? oxcPlugin(config) : null,\n    nativeJsonPlugin({ ...config.json, minify: isBuild }),\n    wasmHelperPlugin(),\n    webWorkerPlugin(config),\n    assetPlugin(config),\n    // for now client only\n    config.server.forwardConsole.enabled &&\n      forwardConsolePlugin({ environments: ['client'] }),\n\n    ...normalPlugins,\n\n    nativeWasmFallbackPlugin(),\n    definePlugin(config),\n    cssPostPlugin(config),\n    isBundled && buildHtmlPlugin(config),\n    workerImportMetaUrlPlugin(config),\n    assetImportMetaUrlPlugin(config),\n    ...buildPlugins.pre,\n    dynamicImportVarsPlugin(config),\n    importGlobPlugin(config),\n\n    ...postPlugins,\n\n    ...buildPlugins.post,\n\n    // internal server-only plugins are always applied after everything else\n    ...(isBundled\n      ? []\n      : [\n          clientInjectionsPlugin(config),\n          cssAnalysisPlugin(config),\n          importAnalysisPlugin(config),\n        ]),\n  ].filter(Boolean) as Plugin[]\n}\n\nexport function createPluginHookUtils(\n  plugins: readonly Plugin[],\n): PluginHookUtils {\n  // sort plugins per hook\n  const sortedPluginsCache = new Map<keyof Plugin, Plugin[]>()\n  function getSortedPlugins<K extends keyof Plugin>(\n    hookName: K,\n  ): PluginWithRequiredHook<K>[] {\n    if (sortedPluginsCache.has(hookName))\n      return sortedPluginsCache.get(hookName) as PluginWithRequiredHook<K>[]\n    const sorted = getSortedPluginsByHook(hookName, plugins)\n    sortedPluginsCache.set(hookName, sorted)\n    return sorted\n  }\n  function getSortedPluginHooks<K extends keyof Plugin>(\n    hookName: K,\n  ): NonNullable<HookHandler<Plugin[K]>>[] {\n    const plugins = getSortedPlugins(hookName)\n    return plugins.map((p) => getHookHandler(p[hookName])).filter(Boolean)\n  }\n\n  return {\n    getSortedPlugins,\n    getSortedPluginHooks,\n  }\n}\n\nexport function getSortedPluginsByHook<K extends keyof Plugin>(\n  hookName: K,\n  plugins: readonly Plugin[],\n): PluginWithRequiredHook<K>[] {\n  const sortedPlugins: Plugin[] = []\n  // Use indexes to track and insert the ordered plugins directly in the\n  // resulting array to avoid creating 3 extra temporary arrays per hook\n  let pre = 0,\n    normal = 0,\n    post = 0\n  for (const plugin of plugins) {\n    const hook = plugin[hookName]\n    if (hook) {\n      if (typeof hook === 'object') {\n        if (hook.order === 'pre') {\n          sortedPlugins.splice(pre++, 0, plugin)\n          continue\n        }\n        if (hook.order === 'post') {\n          sortedPlugins.splice(pre + normal + post++, 0, plugin)\n          continue\n        }\n      }\n      sortedPlugins.splice(pre + normal++, 0, plugin)\n    }\n  }\n\n  return sortedPlugins as PluginWithRequiredHook<K>[]\n}\n\nexport function getHookHandler<T extends ObjectHook<Function>>(\n  hook: T,\n): HookHandler<T> {\n  return (typeof hook === 'object' ? hook.handler : hook) as HookHandler<T>\n}\n\ntype FilterForPluginValue = {\n  resolveId?: PluginFilter | undefined\n  load?: PluginFilter | undefined\n  transform?: TransformHookFilter | undefined\n}\nconst filterForPlugin = new WeakMap<Plugin, FilterForPluginValue>()\n\nexport function getCachedFilterForPlugin<\n  H extends 'resolveId' | 'load' | 'transform',\n>(plugin: Plugin, hookName: H): FilterForPluginValue[H] | undefined {\n  let filters = filterForPlugin.get(plugin)\n  if (filters && hookName in filters) {\n    return filters[hookName]\n  }\n\n  if (!filters) {\n    filters = {}\n    filterForPlugin.set(plugin, filters)\n  }\n\n  let filter: PluginFilter | TransformHookFilter | undefined\n  switch (hookName) {\n    case 'resolveId': {\n      const rawFilter = extractFilter(plugin.resolveId)?.id\n      filters.resolveId = createIdFilter(rawFilter)\n      filter = filters.resolveId\n      break\n    }\n    case 'load': {\n      const rawFilter = extractFilter(plugin.load)?.id\n      filters.load = createIdFilter(rawFilter)\n      filter = filters.load\n      break\n    }\n    case 'transform': {\n      const rawFilters = extractFilter(plugin.transform)\n      filters.transform = createFilterForTransform(\n        rawFilters?.id,\n        rawFilters?.code,\n        rawFilters?.moduleType,\n      )\n      filter = filters.transform\n      break\n    }\n  }\n  return filter as FilterForPluginValue[H] | undefined\n}\n\nfunction extractFilter<T extends Function, F>(\n  hook: ObjectHook<T, { filter?: F }> | undefined,\n) {\n  return hook && 'filter' in hook && hook.filter ? hook.filter : undefined\n}\n\n// Same as `@rollup/plugin-alias` default resolver, but we attach additional meta\n// if we can't resolve to something, which will error in `importAnalysis`\nexport const viteAliasCustomResolver: ResolverFunction = async function (\n  id,\n  importer,\n  options,\n) {\n  const resolved = await this.resolve(id, importer, options)\n  return resolved || { id, meta: { 'vite:alias': { noResolved: true } } }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/json.ts",
    "content": "export interface JsonOptions {\n  /**\n   * Generate a named export for every property of the JSON object\n   * @default true\n   */\n  namedExports?: boolean\n  /**\n   * Generate performant output as JSON.parse(\"stringified\").\n   *\n   * When set to 'auto', the data will be stringified only if the data is bigger than 10kB.\n   * @default 'auto'\n   */\n  stringify?: boolean | 'auto'\n}\n\nconst jsonLangs = `\\\\.(?:json|json5)(?:$|\\\\?)`\nconst jsonLangRE = new RegExp(jsonLangs)\nexport const isJSONRequest = (request: string): boolean =>\n  jsonLangRE.test(request)\n"
  },
  {
    "path": "packages/vite/src/node/plugins/license.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Plugin } from '../plugin'\nimport { isInNodeModules, sortObjectKeys } from '../utils'\nimport type { PackageCache } from '../packages'\nimport { findNearestMainPackageData } from '../packages'\n\nexport interface LicenseEntry {\n  /**\n   * Package name\n   */\n  name: string\n  /**\n   * Package version\n   */\n  version: string\n  /**\n   * SPDX license identifier (from package.json \"license\" field)\n   */\n  identifier?: string\n  /**\n   * License file text\n   */\n  text?: string\n}\n\nexport interface LicenseOptions {\n  /**\n   * The output file name of the license file relative to the output directory.\n   * Specify a path that ends with `.json` to output the raw JSON metadata.\n   *\n   * @default '.vite/license.md'\n   */\n  fileName: string\n}\n\nconst licenseConfigDefaults = Object.freeze({\n  fileName: '.vite/license.md',\n} satisfies LicenseOptions)\n\n// https://github.com/npm/npm-packlist/blob/53b2a4f42b7fef0f63e8f26a3ea4692e23a58fed/lib/index.js#L284-L286\nconst licenseFiles = [/^license/i, /^licence/i, /^copying/i]\n\nexport function licensePlugin(): Plugin {\n  return {\n    name: 'vite:license',\n\n    async generateBundle(_, bundle) {\n      const licenseOption = this.environment.config.build.license\n      if (licenseOption === false) return\n\n      const packageCache: PackageCache = new Map()\n      // Track license via a key to its license entry.\n      // A key consists of \"name@version\" of a package.\n      const licenses: Record<string, LicenseEntry> = {}\n\n      for (const file in bundle) {\n        const chunk = bundle[file]\n        if (chunk.type === 'asset') continue\n\n        for (const moduleId of chunk.moduleIds) {\n          if (moduleId.startsWith('\\0') || !isInNodeModules(moduleId)) continue\n\n          // Find the dependency package.json\n          const pkgData = findNearestMainPackageData(\n            path.dirname(moduleId),\n            packageCache,\n          )\n          if (!pkgData) continue\n\n          // Grab the package.json keys and check if already exists in the licenses\n          const { name, version = '0.0.0', license } = pkgData.data\n          const key = `${name}@${version}`\n          if (licenses[key]) continue\n\n          // If not, create a new license entry\n          const entry: LicenseEntry = { name, version }\n          if (license) {\n            entry.identifier = license.trim()\n          }\n          const licenseFile = findLicenseFile(pkgData.dir)\n          if (licenseFile) {\n            entry.text = fs.readFileSync(licenseFile, 'utf-8').trim()\n          }\n          licenses[key] = entry\n        }\n      }\n\n      const licenseEntries = Object.values(sortObjectKeys(licenses))\n      const licenseOutputFileName =\n        typeof licenseOption === 'object'\n          ? licenseOption.fileName\n          : licenseConfigDefaults.fileName\n\n      // Emit as a JSON file\n      if (licenseOutputFileName.endsWith('.json')) {\n        this.emitFile({\n          fileName: licenseOutputFileName,\n          type: 'asset',\n          source: JSON.stringify(licenseEntries, null, 2),\n        })\n        return\n      }\n\n      // Emit a license file as markdown\n      const markdown = licenseEntryToMarkdown(licenseEntries)\n      this.emitFile({\n        fileName: licenseOutputFileName,\n        type: 'asset',\n        source: markdown,\n      })\n    },\n  }\n}\n\nfunction licenseEntryToMarkdown(licenses: LicenseEntry[]) {\n  if (licenses.length === 0) {\n    return `\\\n# Licenses\n\nThe app does not bundle any dependencies with licenses.\n`\n  }\n\n  let text = `\\\n# Licenses\n\nThe app bundles dependencies which contain the following licenses:\n`\n  for (const license of licenses) {\n    const nameAndVersionText = `${license.name} - ${license.version}`\n    const identifierText = license.identifier ? ` (${license.identifier})` : ''\n\n    text += `\\n## ${nameAndVersionText}${identifierText}\\n`\n    if (license.text) {\n      text += `\\n${license.text}\\n`\n    }\n  }\n  return text\n}\n\nfunction findLicenseFile(pkgDir: string) {\n  const files = fs.readdirSync(pkgDir)\n  const matchedFile = files.find((file) =>\n    licenseFiles.some((re) => re.test(file)),\n  )\n  if (matchedFile) {\n    return path.join(pkgDir, matchedFile)\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/manifest.ts",
    "content": "import path from 'node:path'\nimport type { OutputChunk, RenderedChunk } from 'rolldown'\nimport { viteManifestPlugin as nativeManifestPlugin } from 'rolldown/experimental'\nimport type { Plugin } from '../plugin'\nimport { normalizePath } from '../utils'\nimport { perEnvironmentState } from '../environment'\nimport { type Environment, perEnvironmentPlugin } from '..'\nimport { cssEntriesMap } from './asset'\n\nconst endsWithJSRE = /\\.[cm]?js$/\n\nexport type Manifest = Record<string, ManifestChunk>\n\nexport interface ManifestChunk {\n  /**\n   * The input file name of this chunk / asset if known\n   */\n  src?: string\n  /**\n   * The output file name of this chunk / asset\n   */\n  file: string\n  /**\n   * The list of CSS files imported by this chunk\n   */\n  css?: string[]\n  /**\n   * The list of asset files imported by this chunk, excluding CSS files\n   */\n  assets?: string[]\n  /**\n   * Whether this chunk or asset is an entry point\n   */\n  isEntry?: boolean\n  /**\n   * The name of this chunk / asset if known\n   */\n  name?: string\n  // names field is deprecated (removed from types, but still emitted for backward compatibility)\n  /**\n   * Whether this chunk is a dynamic entry point\n   *\n   * This field is only present in JS chunks.\n   */\n  isDynamicEntry?: boolean\n  /**\n   * The list of statically imported chunks by this chunk\n   *\n   * The values are the keys of the manifest. This field is only present in JS chunks.\n   */\n  imports?: string[]\n  /**\n   * The list of dynamically imported chunks by this chunk\n   *\n   * The values are the keys of the manifest. This field is only present in JS chunks.\n   */\n  dynamicImports?: string[]\n}\n\nexport function manifestPlugin(): Plugin {\n  const getState = perEnvironmentState(() => {\n    return {\n      manifest: {} as Manifest,\n      outputCount: 0,\n      reset() {\n        this.manifest = {}\n        this.outputCount = 0\n      },\n    }\n  })\n\n  return perEnvironmentPlugin('native:manifest', (environment) => {\n    if (!environment.config.build.manifest) return false\n\n    const root = environment.config.root\n    const outPath =\n      environment.config.build.manifest === true\n        ? '.vite/manifest.json'\n        : environment.config.build.manifest\n\n    const envs: Record<string, Environment> = {}\n    function getChunkName(chunk: OutputChunk) {\n      return (\n        getChunkOriginalFileName(chunk, root, false) ??\n        `_${path.basename(chunk.fileName)}`\n      )\n    }\n\n    return [\n      {\n        name: 'native:manifest-envs',\n        buildStart() {\n          envs[environment.name] = this.environment\n        },\n      },\n      nativeManifestPlugin({\n        root,\n        outPath,\n        isOutputOptionsForLegacyChunks:\n          environment.config.isOutputOptionsForLegacyChunks,\n        cssEntries() {\n          return Object.fromEntries(\n            cssEntriesMap.get(envs[environment.name])!.entries(),\n          )\n        },\n      }),\n      {\n        name: 'native:manifest-compatible',\n        generateBundle(_, bundle) {\n          const asset = bundle[outPath]\n          if (asset.type === 'asset') {\n            let manifest: Manifest | undefined\n            for (const output of Object.values(bundle)) {\n              const importedCss = output.viteMetadata?.importedCss\n              const importedAssets = output.viteMetadata?.importedAssets\n              if (!importedCss?.size && !importedAssets?.size) continue\n              manifest ??= JSON.parse(asset.source.toString()) as Manifest\n              if (output.type === 'chunk') {\n                const item = manifest[getChunkName(output)]\n                if (!item) continue\n                if (importedCss?.size) {\n                  item.css = [...importedCss]\n                }\n                if (importedAssets?.size) {\n                  item.assets = [...importedAssets]\n                }\n              } else if (output.type === 'asset' && output.names.length > 0) {\n                // Add every unique asset to the manifest, keyed by its original name\n                const keys =\n                  output.originalFileNames.length > 0\n                    ? output.originalFileNames\n                    : [`_${path.basename(output.fileName)}`]\n\n                for (const key of keys) {\n                  const item = manifest[key]\n                  if (!item) continue\n                  if (!(item.file && endsWithJSRE.test(item.file))) {\n                    if (importedCss?.size) {\n                      item.css = [...importedCss]\n                    }\n                    if (importedAssets?.size) {\n                      item.assets = [...importedAssets]\n                    }\n                  }\n                }\n              }\n            }\n            const output = this.environment.config.build.rolldownOptions.output\n            const outputLength = Array.isArray(output) ? output.length : 1\n            if (manifest && outputLength === 1) {\n              asset.source = JSON.stringify(manifest, undefined, 2)\n              return\n            }\n\n            const state = getState(this)\n            state.outputCount++\n            state.manifest = Object.assign(\n              state.manifest,\n              manifest ?? JSON.parse(asset.source.toString()),\n            )\n            if (state.outputCount >= outputLength) {\n              asset.source = JSON.stringify(state.manifest, undefined, 2)\n              state.reset()\n            } else {\n              delete bundle[outPath]\n            }\n          }\n        },\n      },\n    ]\n  })\n}\n\nexport function getChunkOriginalFileName(\n  chunk: OutputChunk | RenderedChunk,\n  root: string,\n  isLegacy: boolean,\n): string | undefined {\n  if (chunk.facadeModuleId) {\n    let name = normalizePath(path.relative(root, chunk.facadeModuleId))\n    if (isLegacy && !chunk.name.includes('-legacy')) {\n      const ext = path.extname(name)\n      const endPos = ext.length !== 0 ? -ext.length : undefined\n      name = `${name.slice(0, endPos)}-legacy${ext}`\n    }\n    return name.replace(/\\0/g, '')\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/modulePreloadPolyfill.ts",
    "content": "import { exactRegex } from 'rolldown/filter'\nimport { viteModulePreloadPolyfillPlugin as nativeModulePreloadPolyfillPlugin } from 'rolldown/experimental'\nimport { type ResolvedConfig, perEnvironmentPlugin } from '..'\nimport type { Plugin } from '../plugin'\n\nexport const modulePreloadPolyfillId = 'vite/modulepreload-polyfill'\nconst resolvedModulePreloadPolyfillId = '\\0' + modulePreloadPolyfillId + '.js'\n\nexport function modulePreloadPolyfillPlugin(config: ResolvedConfig): Plugin {\n  if (config.isBundled) {\n    return perEnvironmentPlugin(\n      'native:modulepreload-polyfill',\n      (environment) => {\n        return nativeModulePreloadPolyfillPlugin({\n          isServer: environment.config.consumer !== 'client',\n        })\n      },\n    )\n  }\n\n  return {\n    name: 'vite:modulepreload-polyfill',\n    resolveId: {\n      filter: { id: exactRegex(modulePreloadPolyfillId) },\n      handler(_id) {\n        return resolvedModulePreloadPolyfillId\n      },\n    },\n    load: {\n      filter: { id: exactRegex(resolvedModulePreloadPolyfillId) },\n      handler(_id) {\n        // Should resolve to an empty module in dev\n        return ''\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/optimizedDeps.ts",
    "content": "import fsp from 'node:fs/promises'\nimport colors from 'picocolors'\nimport type { DevEnvironment } from '..'\nimport type { Plugin } from '../plugin'\nimport {\n  DEP_VERSION_RE,\n  ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR,\n  ERR_OPTIMIZE_DEPS_PROCESSING_ERROR,\n} from '../constants'\nimport { createDebugger } from '../utils'\nimport {\n  isDepOptimizationDisabled,\n  optimizedDepInfoFromFile,\n} from '../optimizer'\nimport { cleanUrl } from '../../shared/utils'\nimport { ERR_OUTDATED_OPTIMIZED_DEP } from '../../shared/constants'\n\nconst debug = createDebugger('vite:optimize-deps')\n\nexport function optimizedDepsPlugin(): Plugin {\n  return {\n    name: 'vite:optimized-deps',\n\n    applyToEnvironment(environment) {\n      return !isDepOptimizationDisabled(environment.config.optimizeDeps)\n    },\n\n    resolveId(id) {\n      const environment = this.environment as DevEnvironment\n      if (environment.depsOptimizer?.isOptimizedDepFile(id)) {\n        return id\n      }\n    },\n\n    // this.load({ id }) isn't implemented in PluginContainer\n    // The logic to register an id to wait until it is processed\n    // is in importAnalysis, see call to delayDepsOptimizerUntil\n\n    async load(id) {\n      const environment = this.environment as DevEnvironment\n      const depsOptimizer = environment.depsOptimizer\n      if (depsOptimizer?.isOptimizedDepFile(id)) {\n        const metadata = depsOptimizer.metadata\n        const file = cleanUrl(id)\n        const versionMatch = DEP_VERSION_RE.exec(id)\n        const browserHash = versionMatch\n          ? versionMatch[1].split('=')[1]\n          : undefined\n\n        // Search in both the currently optimized and newly discovered deps\n        const info = optimizedDepInfoFromFile(metadata, file)\n        if (info) {\n          if (\n            browserHash &&\n            info.browserHash !== browserHash &&\n            !environment.config.optimizeDeps.ignoreOutdatedRequests\n          ) {\n            throwOutdatedRequest(id)\n          }\n          try {\n            // This is an entry point, it may still not be bundled\n            await info.processing\n          } catch {\n            // If the refresh has not happened after timeout, Vite considers\n            // something unexpected has happened. In this case, Vite\n            // returns an empty response that will error.\n            throwProcessingError(id)\n          }\n          const newMetadata = depsOptimizer.metadata\n          if (metadata !== newMetadata) {\n            const currentInfo = optimizedDepInfoFromFile(newMetadata!, file)\n            if (\n              info.browserHash !== currentInfo?.browserHash &&\n              !environment.config.optimizeDeps.ignoreOutdatedRequests\n            ) {\n              throwOutdatedRequest(id)\n            }\n          }\n        }\n        debug?.(`load ${colors.cyan(file)}`)\n        // Load the file from the cache instead of waiting for other plugin\n        // load hooks to avoid race conditions, once processing is resolved,\n        // we are sure that the file has been properly save to disk\n        try {\n          return await fsp.readFile(file, 'utf-8')\n        } catch {\n          if (\n            browserHash &&\n            !environment.config.optimizeDeps.ignoreOutdatedRequests\n          ) {\n            // Outdated optimized files loaded after a rerun\n            throwOutdatedRequest(id)\n          }\n          throwFileNotFoundInOptimizedDep(id)\n        }\n      }\n    },\n  }\n}\n\nfunction throwProcessingError(id: string): never {\n  const err: any = new Error(\n    `Something unexpected happened while optimizing \"${id}\". ` +\n      `The current page should have reloaded by now`,\n  )\n  err.code = ERR_OPTIMIZE_DEPS_PROCESSING_ERROR\n  // This error will be caught by the transform middleware that will\n  // send a 504 status code request timeout\n  throw err\n}\n\nexport function throwOutdatedRequest(id: string): never {\n  const err: any = new Error(\n    `There is a new version of the pre-bundle for \"${id}\", ` +\n      `a page reload is going to ask for it.`,\n  )\n  err.code = ERR_OUTDATED_OPTIMIZED_DEP\n  // This error will be caught by the transform middleware that will\n  // send a 504 status code request timeout\n  throw err\n}\n\nexport function throwFileNotFoundInOptimizedDep(id: string): never {\n  const err: any = new Error(\n    `The file does not exist at \"${id}\" which is in the optimize deps directory. ` +\n      `The dependency might be incompatible with the dep optimizer. ` +\n      `Try adding it to \\`optimizeDeps.exclude\\`.`,\n  )\n  err.code = ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR\n  // This error will be caught by the transform middleware that will\n  // send a 404 status code not found\n  throw err\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/oxc.ts",
    "content": "import path from 'node:path'\nimport type {\n  TransformOptions as OxcTransformOptions,\n  TransformResult as OxcTransformResult,\n} from 'rolldown/utils'\nimport { transformSync } from 'rolldown/utils'\nimport { viteTransformPlugin as nativeTransformPlugin } from 'rolldown/experimental'\nimport type { RolldownError, RolldownLog, SourceMap } from 'rolldown'\nimport colors from 'picocolors'\nimport type { FSWatcher } from '#dep-types/chokidar'\nimport { createFilter, ensureWatchedFile, normalizePath } from '../utils'\nimport type { ResolvedConfig } from '../config'\nimport type { Plugin } from '../plugin'\nimport { cleanUrl } from '../../shared/utils'\nimport { type Environment, perEnvironmentPlugin } from '..'\nimport type { ViteDevServer } from '../server'\nimport { JS_TYPES_RE } from '../constants'\nimport type { Logger } from '../logger'\nimport { type ESBuildOptions, getTSConfigResolutionCache } from './esbuild'\n\n// IIFE content looks like `var MyLib = (function() {` or `this.nested.myLib = (function() {`.\nexport const IIFE_BEGIN_RE: RegExp =\n  /(?:(?:(?:const|var)\\s+[^.\\s]+|[^.\\s]+\\.[^.\\s]+\\.[^.\\s]+)\\s*=\\s*|^|\\n)\\(?function\\([^()]*\\)\\s*\\{(?:\\s*\"use strict\";)?/\n// UMD content looks like `})(this, function(exports, external1, external2) {`.\nexport const UMD_BEGIN_RE: RegExp =\n  /\\}\\)\\((?:this,\\s*)?function\\([^()]*\\)\\s*\\{(?:\\s*\"use strict\";)?/\n\nconst jsxExtensionsRE = /\\.(?:j|t)sx\\b/\nconst validExtensionRE = /\\.\\w+$/\n\nexport interface OxcOptions extends Omit<\n  OxcTransformOptions,\n  | 'cwd'\n  | 'sourceType'\n  | 'lang'\n  | 'sourcemap'\n  | 'helpers'\n  | 'inject'\n  | 'tsconfig'\n  | 'inputMap'\n> {\n  include?: string | RegExp | ReadonlyArray<string | RegExp>\n  exclude?: string | RegExp | ReadonlyArray<string | RegExp>\n  jsxInject?: string\n  jsxRefreshInclude?: string | RegExp | ReadonlyArray<string | RegExp>\n  jsxRefreshExclude?: string | RegExp | ReadonlyArray<string | RegExp>\n}\n\nexport function getRollupJsxPresets(\n  preset: 'react' | 'react-jsx',\n): OxcJsxOptions {\n  switch (preset) {\n    case 'react':\n      return {\n        runtime: 'classic',\n        pragma: 'React.createElement',\n        pragmaFrag: 'React.Fragment',\n        importSource: 'react',\n      }\n    case 'react-jsx':\n      return {\n        runtime: 'automatic',\n        pragma: 'React.createElement',\n        importSource: 'react',\n      }\n  }\n  preset satisfies never\n}\n\n// Copy from rolldown's packages/rolldown/src/utils/errors.ts\nfunction joinNewLine(s1: string, s2: string): string {\n  // ensure single new line in between\n  return s1.replace(/\\n+$/, '') + '\\n' + s2.replace(/^\\n+/, '')\n}\n\n// Copy from rolldown's packages/rolldown/src/utils/errors.ts\nfunction getErrorMessage(e: RolldownError): string {\n  // If the `kind` field is present, we assume it represents\n  // a custom error defined by rolldown on the Rust side.\n  if (Object.hasOwn(e, 'kind')) {\n    return e.message\n  }\n\n  let s = ''\n  if (e.plugin) {\n    s += `[plugin ${e.plugin}]`\n  }\n  const id = e.id ?? e.loc?.file\n  if (id) {\n    s += ' ' + id\n    if (e.loc) {\n      s += `:${e.loc.line}:${e.loc.column}`\n    }\n  }\n  if (s) {\n    s += '\\n'\n  }\n  const message = `${e.name ?? 'Error'}: ${e.message}`\n  s += message\n  if (e.frame) {\n    s = joinNewLine(s, e.frame)\n  }\n  // copy stack since it's important for js plugin error\n  if (e.stack) {\n    s = joinNewLine(s, e.stack.replace(message, ''))\n  }\n  if (e.cause) {\n    s = joinNewLine(s, 'Caused by:')\n    s = joinNewLine(\n      s,\n      getErrorMessage(e.cause as any)\n        .split('\\n')\n        .map((line) => '  ' + line)\n        .join('\\n'),\n    )\n  }\n  return s\n}\n\nexport async function transformWithOxc(\n  code: string,\n  filename: string,\n  options?: OxcTransformOptions,\n  inMap?: object,\n  config?: ResolvedConfig,\n  watcher?: FSWatcher,\n): Promise<Omit<OxcTransformResult, 'errors'>> {\n  let lang = options?.lang\n  if (!lang) {\n    // if the id ends with a valid ext, use it (e.g. vue blocks)\n    // otherwise, cleanup the query before checking the ext\n    const ext = path\n      .extname(validExtensionRE.test(filename) ? filename : cleanUrl(filename))\n      .slice(1)\n\n    if (ext === 'cjs' || ext === 'mjs') {\n      lang = 'js'\n    } else if (ext === 'cts' || ext === 'mts') {\n      lang = 'ts'\n    } else {\n      lang = ext as 'js' | 'jsx' | 'ts' | 'tsx'\n    }\n  }\n\n  const resolvedOptions = {\n    sourcemap: true,\n    ...options,\n    inputMap: inMap as SourceMap | undefined,\n    lang,\n  }\n\n  const result = transformSync(\n    filename,\n    code,\n    resolvedOptions,\n    getTSConfigResolutionCache(config),\n  )\n  if (\n    watcher &&\n    config &&\n    result.tsconfigFilePaths &&\n    result.tsconfigFilePaths.length > 0\n  ) {\n    for (const tsconfigFile of result.tsconfigFilePaths) {\n      ensureWatchedFile(watcher, normalizePath(tsconfigFile), config.root)\n    }\n  }\n\n  if (result.errors.length > 0) {\n    // Copy from rolldown's packages/rolldown/src/utils/errors.ts\n    let summary = `Transform failed with ${result.errors.length} error${result.errors.length < 2 ? '' : 's'}:\\n`\n    for (let i = 0; i < result.errors.length; i++) {\n      summary += '\\n'\n      if (i >= 5) {\n        summary += '...'\n        break\n      }\n      summary += getErrorMessage(result.errors[i])\n    }\n\n    const wrapper = new Error(summary)\n    // expose individual errors as getters so that\n    // `console.error(wrapper)` doesn't expand unnecessary details\n    // when they are already presented in `wrapper.message`\n    Object.defineProperty(wrapper, 'errors', {\n      configurable: true,\n      enumerable: true,\n      get: () => result.errors,\n      set: (value) =>\n        Object.defineProperty(wrapper, 'errors', {\n          configurable: true,\n          enumerable: true,\n          value,\n        }),\n    })\n    throw wrapper\n  }\n  return result\n}\n\nconst warnedMessages = new Set<string>()\nfunction shouldSkipWarning(warning: RolldownLog): boolean {\n  if (warning.code === 'UNSUPPORTED_TSCONFIG_OPTION') {\n    if (warnedMessages.has(warning.message)) return true\n    warnedMessages.add(warning.message)\n  }\n  return false\n}\n\nexport function oxcPlugin(config: ResolvedConfig): Plugin {\n  if (config.isBundled) {\n    return perEnvironmentPlugin('native:transform', (environment) => {\n      const {\n        jsxInject,\n        include = /\\.(m?ts|[jt]sx)$/,\n        exclude = /\\.js$/,\n        jsxRefreshInclude,\n        jsxRefreshExclude,\n        ..._transformOptions\n      } = config.oxc as Exclude<OxcOptions, false | undefined>\n\n      const transformOptions: OxcTransformOptions = _transformOptions\n      transformOptions.sourcemap =\n        environment.config.mode !== 'build' ||\n        !!environment.config.build.sourcemap\n\n      return nativeTransformPlugin({\n        root: environment.config.root,\n        include,\n        exclude,\n        jsxRefreshInclude,\n        jsxRefreshExclude,\n        isServerConsumer: environment.config.consumer === 'server',\n        jsxInject,\n        transformOptions,\n      })\n    })\n  }\n\n  const options = config.oxc as OxcOptions\n  const {\n    jsxInject,\n    include,\n    exclude,\n    jsxRefreshInclude,\n    jsxRefreshExclude,\n    ...oxcTransformOptions\n  } = options\n\n  const filter = createFilter(include || /\\.(m?ts|[jt]sx)$/, exclude || /\\.js$/)\n  const jsxRefreshFilter =\n    jsxRefreshInclude || jsxRefreshExclude\n      ? createFilter(jsxRefreshInclude, jsxRefreshExclude)\n      : undefined\n\n  const jsxImportSource =\n    (typeof oxcTransformOptions.jsx === 'object' &&\n      oxcTransformOptions.jsx.importSource) ||\n    'react'\n  const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`\n  const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`\n\n  const getModifiedOxcTransformOptions = (\n    oxcTransformOptions: OxcTransformOptions,\n    id: string,\n    code: string,\n    environment: Environment,\n  ): OxcTransformOptions => {\n    const result: OxcTransformOptions = {\n      ...oxcTransformOptions,\n      sourcemap:\n        environment.mode !== 'build' || !!environment.config.build.sourcemap,\n    }\n\n    const jsxOptions = result.jsx\n\n    // disable refresh based by the same condition as @vitejs/plugin-react\n    // https://github.com/vitejs/vite-plugin-react/blob/c8ecad052001b6fc42e508f18433e6b305bca641/packages/plugin-react/src/index.ts#L261-L269\n    const [filepath] = id.split('?')\n    const isJSX = filepath.endsWith('x')\n\n    if (\n      typeof jsxOptions === 'object' &&\n      jsxOptions.refresh &&\n      (environment.config.consumer === 'server' ||\n        (jsxRefreshFilter && !jsxRefreshFilter(id)) ||\n        !(\n          isJSX ||\n          code.includes(jsxImportRuntime) ||\n          code.includes(jsxImportDevRuntime)\n        ))\n    ) {\n      result.jsx = { ...jsxOptions, refresh: false }\n    }\n    if (jsxRefreshFilter?.(id) && !JS_TYPES_RE.test(cleanUrl(id))) {\n      result.lang = 'js'\n    }\n\n    return result\n  }\n\n  let server: ViteDevServer\n\n  return {\n    name: 'vite:oxc',\n    configureServer(_server) {\n      server = _server\n    },\n    async transform(code, id) {\n      if (filter(id) || filter(cleanUrl(id)) || jsxRefreshFilter?.(id)) {\n        const modifiedOxcTransformOptions = getModifiedOxcTransformOptions(\n          oxcTransformOptions,\n          id,\n          code,\n          this.environment,\n        )\n        const result = await transformWithOxc(\n          code,\n          id,\n          modifiedOxcTransformOptions,\n          undefined,\n          config,\n          server?.watcher,\n        )\n        if (jsxInject && jsxExtensionsRE.test(id)) {\n          result.code = jsxInject + ';' + result.code\n        }\n        for (const warning of result.warnings) {\n          if (!shouldSkipWarning(warning)) {\n            this.warn(warning)\n          }\n        }\n        return {\n          code: result.code,\n          map: result.map,\n          moduleType: 'js',\n        }\n      }\n    },\n  }\n}\n\ntype OxcJsxOptions = Exclude<OxcOptions['jsx'], string | undefined>\n\nexport function convertEsbuildConfigToOxcConfig(\n  esbuildConfig: ESBuildOptions,\n  logger: Logger,\n): OxcOptions {\n  const { jsxInject, include, exclude, ...esbuildTransformOptions } =\n    esbuildConfig\n\n  const oxcOptions: OxcOptions = {\n    jsxInject,\n    include,\n    exclude,\n  }\n\n  if (esbuildTransformOptions.jsx === 'preserve') {\n    oxcOptions.jsx = 'preserve'\n  } else {\n    const jsxOptions: OxcJsxOptions = {}\n\n    switch (esbuildTransformOptions.jsx) {\n      case 'automatic':\n        jsxOptions.runtime = 'automatic'\n        if (esbuildTransformOptions.jsxImportSource) {\n          jsxOptions.importSource = esbuildTransformOptions.jsxImportSource\n        }\n        break\n      case 'transform':\n        jsxOptions.runtime = 'classic'\n        if (esbuildTransformOptions.jsxFactory) {\n          jsxOptions.pragma = esbuildTransformOptions.jsxFactory\n        }\n        if (esbuildTransformOptions.jsxFragment) {\n          jsxOptions.pragmaFrag = esbuildTransformOptions.jsxFragment\n        }\n        break\n      default:\n        break\n    }\n\n    if (esbuildTransformOptions.jsxDev !== undefined) {\n      jsxOptions.development = esbuildTransformOptions.jsxDev\n    }\n    if (esbuildTransformOptions.jsxSideEffects !== undefined) {\n      jsxOptions.pure = esbuildTransformOptions.jsxSideEffects\n    }\n\n    oxcOptions.jsx = jsxOptions\n  }\n\n  if (esbuildTransformOptions.define) {\n    oxcOptions.define = esbuildTransformOptions.define\n  }\n\n  // these backward compat are supported by esbuildBannerFooterCompatPlugin\n  if (esbuildTransformOptions.banner) {\n    warnDeprecatedShouldBeConvertedToPluginOptions(logger, 'banner')\n  }\n  if (esbuildTransformOptions.footer) {\n    warnDeprecatedShouldBeConvertedToPluginOptions(logger, 'footer')\n  }\n\n  return oxcOptions\n}\n\nfunction warnDeprecatedShouldBeConvertedToPluginOptions(\n  logger: Logger,\n  name: string,\n) {\n  logger.warn(\n    colors.yellow(\n      `\\`esbuild.${name}\\` option was specified. ` +\n        `But this option is deprecated and will be removed in future versions. ` +\n        'This option can be achieved by using a plugin with transform hook, please use that instead.',\n    ),\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/pluginFilter.ts",
    "content": "import path from 'node:path'\nimport picomatch from 'picomatch'\nimport type { ModuleTypeFilter } from 'rolldown'\nimport { arraify } from '../utils'\nimport { slash } from '../../shared/utils'\n\nexport type PluginFilter = (input: string) => boolean\nexport type TransformHookFilter = (\n  id: string,\n  code: string,\n  moduleType: string,\n) => boolean\n\nexport type StringFilter<Value = string | RegExp> =\n  | Value\n  | Array<Value>\n  | {\n      include?: Value | Array<Value>\n      exclude?: Value | Array<Value>\n    }\n\ntype NormalizedStringFilter = {\n  include?: Array<string | RegExp>\n  exclude?: Array<string | RegExp>\n}\n\nfunction getMatcherString(glob: string, cwd: string) {\n  if (glob.startsWith('**') || path.isAbsolute(glob)) {\n    return slash(glob)\n  }\n\n  const resolved = path.join(cwd, glob)\n  return slash(resolved)\n}\n\nfunction patternToIdFilter(\n  pattern: string | RegExp,\n  cwd: string,\n): PluginFilter {\n  if (pattern instanceof RegExp) {\n    return (id: string) => {\n      const normalizedId = slash(id)\n      const result = pattern.test(normalizedId)\n      pattern.lastIndex = 0\n      return result\n    }\n  }\n\n  const glob = getMatcherString(pattern, cwd)\n  const matcher = picomatch(glob, { dot: true })\n  return (id: string) => {\n    const normalizedId = slash(id)\n    return matcher(normalizedId)\n  }\n}\n\nfunction patternToCodeFilter(pattern: string | RegExp): PluginFilter {\n  if (pattern instanceof RegExp) {\n    return (code: string) => {\n      const result = pattern.test(code)\n      pattern.lastIndex = 0\n      return result\n    }\n  }\n  return (code: string) => code.includes(pattern)\n}\n\nfunction createFilter(\n  exclude: Array<PluginFilter> | undefined,\n  include: Array<PluginFilter> | undefined,\n): PluginFilter | undefined {\n  if (!exclude && !include) {\n    return\n  }\n\n  return (input) => {\n    if (exclude?.some((filter) => filter(input))) {\n      return false\n    }\n    if (include?.some((filter) => filter(input))) {\n      return true\n    }\n    return !(include && include.length > 0)\n  }\n}\n\nfunction normalizeFilter(filter: StringFilter): NormalizedStringFilter {\n  if (typeof filter === 'string' || filter instanceof RegExp) {\n    return {\n      include: [filter],\n    }\n  }\n  if (Array.isArray(filter)) {\n    return {\n      include: filter,\n    }\n  }\n  return {\n    include: filter.include ? arraify(filter.include) : undefined,\n    exclude: filter.exclude ? arraify(filter.exclude) : undefined,\n  }\n}\n\nexport function createIdFilter(\n  filter: StringFilter | undefined,\n  cwd: string = process.cwd(),\n): PluginFilter | undefined {\n  if (!filter) return\n  const { exclude, include } = normalizeFilter(filter)\n  const excludeFilter = exclude?.map((p) => patternToIdFilter(p, cwd))\n  const includeFilter = include?.map((p) => patternToIdFilter(p, cwd))\n  return createFilter(excludeFilter, includeFilter)\n}\n\nexport function createCodeFilter(\n  filter: StringFilter | undefined,\n): PluginFilter | undefined {\n  if (!filter) return\n  const { exclude, include } = normalizeFilter(filter)\n  const excludeFilter = exclude?.map(patternToCodeFilter)\n  const includeFilter = include?.map(patternToCodeFilter)\n  return createFilter(excludeFilter, includeFilter)\n}\n\nfunction createModuleTypeFilter(\n  filter: ModuleTypeFilter | undefined,\n): PluginFilter | undefined {\n  if (!filter) return\n  const include = Array.isArray(filter) ? filter : (filter.include ?? [])\n  return (moduleType: string) => include.includes(moduleType)\n}\n\nexport function createFilterForTransform(\n  idFilter: StringFilter | undefined,\n  codeFilter: StringFilter | undefined,\n  moduleTypeFilter: ModuleTypeFilter | undefined,\n  cwd?: string,\n): TransformHookFilter | undefined {\n  if (!idFilter && !codeFilter && !moduleTypeFilter) return\n  const idFilterFn = createIdFilter(idFilter, cwd)\n  const codeFilterFn = createCodeFilter(codeFilter)\n  const moduleTypeFilterFn = createModuleTypeFilter(moduleTypeFilter)\n  return (id, code, moduleType) => {\n    let fallback = moduleTypeFilterFn?.(moduleType) ?? true\n    if (!fallback) {\n      return false\n    }\n\n    if (idFilterFn) {\n      fallback &&= idFilterFn(id)\n    }\n    if (!fallback) {\n      return false\n    }\n\n    if (codeFilterFn) {\n      fallback &&= codeFilterFn(code)\n    }\n    return fallback\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/preAlias.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport type {\n  Alias,\n  AliasOptions,\n  DepOptimizationOptions,\n  DevEnvironment,\n  ResolvedConfig,\n} from '..'\nimport type { Plugin } from '../plugin'\nimport {\n  bareImportRE,\n  isInNodeModules,\n  isOptimizable,\n  moduleListContains,\n} from '../utils'\nimport { cleanUrl, withTrailingSlash } from '../../shared/utils'\nimport { isDepOptimizationDisabled } from '../optimizer'\nimport { tryOptimizedResolve } from './resolve'\n\n/**\n * A plugin to avoid an aliased AND optimized dep from being aliased in src\n */\nexport function preAliasPlugin(config: ResolvedConfig): Plugin {\n  const findPatterns = getAliasPatterns(config.resolve.alias)\n  return {\n    name: 'vite:pre-alias',\n    applyToEnvironment(environment) {\n      return !isDepOptimizationDisabled(environment.config.optimizeDeps)\n    },\n    async resolveId(id, importer, options) {\n      const environment = this.environment as DevEnvironment\n      const ssr = environment.config.consumer === 'server'\n      const depsOptimizer = environment.depsOptimizer\n      if (\n        importer &&\n        depsOptimizer &&\n        bareImportRE.test(id) &&\n        !options.scan &&\n        id !== '@vite/client' &&\n        id !== '@vite/env'\n      ) {\n        if (findPatterns.find((pattern) => matches(pattern, id))) {\n          const optimizedId = await tryOptimizedResolve(\n            depsOptimizer,\n            id,\n            importer,\n            config.resolve.preserveSymlinks,\n            config.packageCache,\n          )\n          if (optimizedId) {\n            return optimizedId // aliased dep already optimized\n          }\n          if (depsOptimizer.options.noDiscovery) {\n            return\n          }\n          const resolved = await this.resolve(id, importer, options)\n          if (resolved && !depsOptimizer.isOptimizedDepFile(resolved.id)) {\n            const optimizeDeps = depsOptimizer.options\n            const resolvedId = cleanUrl(resolved.id)\n            const isVirtual = resolvedId === id || resolvedId.includes('\\0')\n            if (\n              !isVirtual &&\n              fs.existsSync(resolvedId) &&\n              !moduleListContains(optimizeDeps.exclude, id) &&\n              path.isAbsolute(resolvedId) &&\n              (isInNodeModules(resolvedId) ||\n                optimizeDeps.include?.includes(id)) &&\n              isOptimizable(resolvedId, optimizeDeps) &&\n              (!ssr || optimizeAliasReplacementForSSR(resolvedId, optimizeDeps))\n            ) {\n              // aliased dep has not yet been optimized\n              const optimizedInfo = depsOptimizer!.registerMissingImport(\n                id,\n                resolvedId,\n              )\n              return { id: depsOptimizer!.getOptimizedDepId(optimizedInfo) }\n            }\n          }\n          return resolved\n        }\n      }\n    },\n  }\n}\n\nfunction optimizeAliasReplacementForSSR(\n  id: string,\n  optimizeDeps: DepOptimizationOptions,\n) {\n  if (optimizeDeps.include?.includes(id)) {\n    return true\n  }\n  // In the regular resolution, the default for non-external modules is to\n  // be optimized if they are CJS. Here, we don't have the package id but\n  // only the replacement file path. We could find the package.json from\n  // the id and respect the same default in the future.\n  // Default to not optimize an aliased replacement for now, forcing the\n  // user to explicitly add it to the ssr.optimizeDeps.include list.\n  return false\n}\n\n// In sync with rollup plugin alias logic\nfunction matches(pattern: string | RegExp, importee: string) {\n  if (pattern instanceof RegExp) {\n    return pattern.test(importee)\n  }\n  if (importee.length < pattern.length) {\n    return false\n  }\n  if (importee === pattern) {\n    return true\n  }\n  return importee.startsWith(withTrailingSlash(pattern))\n}\n\nfunction getAliasPatterns(\n  entries: (AliasOptions | undefined) & Alias[],\n): (string | RegExp)[] {\n  if (Array.isArray(entries)) {\n    return entries.map((entry) => entry.find)\n  }\n  return Object.entries(entries).map(([find]) => find)\n}\n\nexport function getAliasPatternMatcher(\n  entries: (AliasOptions | undefined) & Alias[],\n): (importee: string) => boolean {\n  const patterns = getAliasPatterns(entries)\n  return (importee: string) =>\n    patterns.some((pattern) => matches(pattern, importee))\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/prepareOutDir.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport colors from 'picocolors'\nimport type { Plugin } from '../plugin'\nimport { getResolvedOutDirs, resolveEmptyOutDir } from '../watch'\nimport type { Environment } from '../environment'\nimport { copyDir, emptyDir, normalizePath } from '../utils'\nimport { withTrailingSlash } from '../../shared/utils'\n\nexport function prepareOutDirPlugin(): Plugin {\n  const rendered = new Set<Environment>()\n  return {\n    name: 'vite:prepare-out-dir',\n    options() {\n      rendered.delete(this.environment)\n    },\n    renderStart: {\n      order: 'pre',\n      handler() {\n        if (rendered.has(this.environment)) {\n          return\n        }\n        rendered.add(this.environment)\n\n        const { config } = this.environment\n        if (config.build.write) {\n          const { root, build: options } = config\n          const resolvedOutDirs = getResolvedOutDirs(\n            root,\n            options.outDir,\n            options.rollupOptions.output,\n          )\n          const emptyOutDir = resolveEmptyOutDir(\n            options.emptyOutDir,\n            root,\n            resolvedOutDirs,\n            this.environment.logger,\n          )\n          prepareOutDir(resolvedOutDirs, emptyOutDir, this.environment)\n        }\n      },\n    },\n  }\n}\n\nfunction prepareOutDir(\n  outDirs: Set<string>,\n  emptyOutDir: boolean | null,\n  environment: Environment,\n) {\n  const { publicDir } = environment.config\n  const outDirsArray = [...outDirs]\n  for (const outDir of outDirs) {\n    if (emptyOutDir !== false && fs.existsSync(outDir)) {\n      // skip those other outDirs which are nested in current outDir\n      const skipDirs = outDirsArray\n        .map((dir) => {\n          const relative = path.relative(outDir, dir)\n          if (\n            relative &&\n            !relative.startsWith('..') &&\n            !path.isAbsolute(relative)\n          ) {\n            return relative\n          }\n          return ''\n        })\n        .filter(Boolean)\n      emptyDir(outDir, [...skipDirs, '.git'])\n    }\n    if (\n      environment.config.build.copyPublicDir &&\n      publicDir &&\n      fs.existsSync(publicDir)\n    ) {\n      if (!areSeparateFolders(outDir, publicDir)) {\n        environment.logger.warn(\n          colors.yellow(\n            `\\n${colors.bold(\n              `(!)`,\n            )} The public directory feature may not work correctly. outDir ${colors.white(\n              colors.dim(outDir),\n            )} and publicDir ${colors.white(\n              colors.dim(publicDir),\n            )} are not separate folders.\\n`,\n          ),\n        )\n      }\n      copyDir(publicDir, outDir)\n    }\n  }\n}\n\nfunction areSeparateFolders(a: string, b: string) {\n  const na = normalizePath(a)\n  const nb = normalizePath(b)\n  return (\n    na !== nb &&\n    !na.startsWith(withTrailingSlash(nb)) &&\n    !nb.startsWith(withTrailingSlash(na))\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/reporter.ts",
    "content": "import path from 'node:path'\nimport { viteReporterPlugin as nativeReporterPlugin } from 'rolldown/experimental'\nimport { type Plugin, perEnvironmentPlugin } from '../plugin'\nimport type { ResolvedConfig } from '../config'\nimport { LogLevels } from '../logger'\n\nexport function buildReporterPlugin(config: ResolvedConfig): Plugin {\n  return perEnvironmentPlugin('native:reporter', (env) => {\n    const tty = process.stdout.isTTY && !process.env.CI\n    const shouldLogInfo = LogLevels[config.logLevel || 'info'] >= LogLevels.info\n    const assetsDir = path.join(env.config.build.assetsDir, '/')\n    return nativeReporterPlugin({\n      root: env.config.root,\n      isTty: !!tty,\n      isLib: !!env.config.build.lib,\n      assetsDir,\n      chunkLimit: env.config.build.chunkSizeWarningLimit,\n      logInfo: shouldLogInfo ? (msg) => env.logger.info(msg) : undefined,\n      reportCompressedSize: env.config.build.reportCompressedSize,\n      warnLargeChunks:\n        env.config.build.minify &&\n        !env.config.build.lib &&\n        env.config.consumer === 'client',\n    })\n  })\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/resolve.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport colors from 'picocolors'\nimport type { PartialResolvedId } from 'rolldown'\nimport { viteResolvePlugin } from 'rolldown/experimental'\nimport { exports, imports } from 'resolve.exports'\nimport { hasESMSyntax } from 'mlly'\nimport type { Plugin } from '../plugin'\nimport {\n  CLIENT_ENTRY,\n  DEP_VERSION_RE,\n  DEV_PROD_CONDITION,\n  ENV_ENTRY,\n  FS_PREFIX,\n  SPECIAL_QUERY_RE,\n} from '../constants'\nimport {\n  bareImportRE,\n  createDebugger,\n  deepImportRE,\n  fsPathFromId,\n  getNpmPackageName,\n  injectQuery,\n  isBuiltin,\n  isDataUrl,\n  isExternalUrl,\n  isInNodeModules,\n  isObject,\n  isOptimizable,\n  normalizePath,\n  safeRealpathSync,\n  tryStatSync,\n} from '../utils'\nimport {\n  isDepOptimizationDisabled,\n  optimizedDepInfoFromFile,\n  optimizedDepInfoFromId,\n} from '../optimizer'\nimport type { DepsOptimizer } from '../optimizer'\nimport type { Environment } from '..'\nimport type { PackageCache, PackageData } from '../packages'\nimport { canExternalizeFile } from '../external'\nimport {\n  findNearestMainPackageData,\n  findNearestPackageData,\n  loadPackageData,\n  resolvePackageData,\n} from '../packages'\nimport {\n  cleanUrl,\n  splitFileAndPostfix,\n  withTrailingSlash,\n} from '../../shared/utils'\nimport type { ResolvedConfig, ResolvedEnvironmentOptions } from '../config'\n\nconst normalizedClientEntry = normalizePath(CLIENT_ENTRY)\nconst normalizedEnvEntry = normalizePath(ENV_ENTRY)\n\nconst ERR_RESOLVE_PACKAGE_ENTRY_FAIL = 'ERR_RESOLVE_PACKAGE_ENTRY_FAIL'\n\n// special id for paths marked with browser: false\n// https://github.com/defunctzombie/package-browser-field-spec#ignore-a-module\nexport const browserExternalId = '__vite-browser-external'\n// special id for packages that are optional peer deps\nexport const optionalPeerDepId = '__vite-optional-peer-dep'\n\nconst subpathImportsPrefix = '#'\n\nconst relativePrefixRE = /^\\.\\.?(?:[/\\\\]|$)/\nconst startsWithWordCharRE = /^\\w/\n\nconst debug = createDebugger('vite:resolve-details', {\n  onlyWhenFocused: true,\n})\n\nexport interface EnvironmentResolveOptions {\n  /**\n   * @default ['browser', 'module', 'jsnext:main', 'jsnext']\n   */\n  mainFields?: string[]\n  conditions?: string[]\n  externalConditions?: string[]\n  /**\n   * @default ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']\n   */\n  extensions?: string[]\n  dedupe?: string[]\n  // TODO: better abstraction that works for the client environment too?\n  /**\n   * Prevent listed dependencies from being externalized and will get bundled in build.\n   * Only works in server environments for now. Previously this was `ssr.noExternal`.\n   * @experimental\n   */\n  noExternal?: string | RegExp | (string | RegExp)[] | true\n  /**\n   * Externalize the given dependencies and their transitive dependencies.\n   * Only works in server environments for now. Previously this was `ssr.external`.\n   * @experimental\n   */\n  external?: string[] | true\n  /**\n   * Array of strings or regular expressions that indicate what modules are builtin for the environment.\n   */\n  builtins?: (string | RegExp)[]\n}\n\nexport interface ResolveOptions extends EnvironmentResolveOptions {\n  /**\n   * @default false\n   */\n  preserveSymlinks?: boolean\n  /**\n   * Enable tsconfig paths resolution\n   *\n   * @default false\n   * @experimental\n   */\n  tsconfigPaths?: boolean\n}\n\ninterface ResolvePluginOptions {\n  root: string\n  isBuild: boolean\n  isProduction: boolean\n  packageCache?: PackageCache\n  /**\n   * src code mode also attempts the following:\n   * - resolving /xxx as URLs\n   * - resolving bare imports from optimized deps\n   */\n  asSrc?: boolean\n  tryIndex?: boolean\n  tryPrefix?: string\n  preferRelative?: boolean\n  isRequire?: boolean\n  // True when resolving during the scan phase to discover dependencies\n  scan?: boolean\n  /**\n   * @internal\n   */\n  skipMainField?: boolean\n\n  /**\n   * Optimize deps during dev, defaults to false // TODO: Review default\n   * @internal\n   */\n  optimizeDeps?: boolean\n\n  /**\n   * Externalize using `resolve.external` and `resolve.noExternal` when running a build in\n   * a server environment. Defaults to false (only for createResolver)\n   * @internal\n   */\n  externalize?: boolean\n\n  /**\n   * Set by createResolver, we only care about the resolved id. moduleSideEffects\n   * and other fields are discarded so we can avoid computing them.\n   * @internal\n   */\n  idOnly?: boolean\n\n  /**\n   * Set by `nodeResolveWithVite`, disables optional peer dependency handling.\n   * @internal\n   */\n  disableOptionalPeerDepHandling?: boolean\n\n  /**\n   * Enable when `legacy.inconsistentCjsInterop` is true. See that option for more details.\n   */\n  legacyInconsistentCjsInterop?: boolean\n}\n\nexport interface InternalResolveOptions\n  extends Required<ResolveOptions>, ResolvePluginOptions {}\n\n// Defined ResolveOptions are used to overwrite the values for all environments\n// It is used when creating custom resolvers (for CSS, scanning, etc)\nexport interface ResolvePluginOptionsWithOverrides\n  extends ResolveOptions, ResolvePluginOptions {}\n\nconst perEnvironmentOrWorkerPlugin = (\n  name: string,\n  overrideEnvConfig: (ResolvedConfig & ResolvedEnvironmentOptions) | undefined,\n  f: (\n    env: {\n      name: string\n      config: ResolvedConfig & ResolvedEnvironmentOptions\n    },\n    getEnvironment: () => Environment,\n  ) => Plugin,\n): Plugin[] => {\n  const envs: Record<string, Environment> = {}\n  const getEnvironmentPlugin: Plugin = {\n    name: `${name}:get-environment`,\n    buildStart() {\n      envs[this.environment.name] = this.environment\n    },\n    perEnvironmentStartEndDuringDev: true,\n  }\n  const createGetEnvironment = (name: string) => () => envs[name]\n\n  if (overrideEnvConfig) {\n    return [\n      getEnvironmentPlugin,\n      f(\n        { name: 'client', config: overrideEnvConfig },\n        createGetEnvironment('client'),\n      ),\n    ]\n  }\n  return [\n    getEnvironmentPlugin,\n    {\n      name,\n      applyToEnvironment(environment) {\n        return f(environment, createGetEnvironment(environment.name))\n      },\n    },\n  ]\n}\n\nexport function oxcResolvePlugin(\n  resolveOptions: ResolvePluginOptionsWithOverrides,\n  overrideEnvConfig: (ResolvedConfig & ResolvedEnvironmentOptions) | undefined,\n): Plugin[] {\n  return [\n    ...(resolveOptions.optimizeDeps && !resolveOptions.isBuild\n      ? [optimizerResolvePlugin(resolveOptions)]\n      : []),\n    ...perEnvironmentOrWorkerPlugin(\n      'vite:resolve-builtin',\n      overrideEnvConfig,\n      (partialEnv, getEnv) => {\n        // The resolve plugin is used for createIdResolver and the depsOptimizer should be\n        // disabled in that case, so deps optimization is opt-in when creating the plugin.\n        const depsOptimizerEnabled =\n          resolveOptions.optimizeDeps &&\n          !resolveOptions.isBuild &&\n          !partialEnv.config.experimental.bundledDev &&\n          !isDepOptimizationDisabled(partialEnv.config.optimizeDeps)\n        const getDepsOptimizer = () => {\n          const env = getEnv()\n          if (env.mode !== 'dev')\n            throw new Error('The environment mode should be dev')\n          if (!env.depsOptimizer)\n            throw new Error('The environment should have a depsOptimizer')\n          return env.depsOptimizer\n        }\n\n        const options: InternalResolveOptions = {\n          ...partialEnv.config.resolve,\n          ...resolveOptions, // plugin options + resolve options overrides\n        }\n        const noExternal =\n          Array.isArray(options.noExternal) || options.noExternal === true\n            ? options.noExternal\n            : [options.noExternal]\n\n        const plugin = viteResolvePlugin({\n          resolveOptions: {\n            isBuild: options.isBuild,\n            isProduction: options.isProduction,\n            asSrc: options.asSrc ?? false,\n            preferRelative: options.preferRelative ?? false,\n            isRequire: options.isRequire,\n            root: options.root,\n            scan: options.scan ?? false,\n\n            mainFields: options.skipMainField\n              ? options.mainFields\n              : options.mainFields.concat(['main']),\n            conditions: options.conditions,\n            externalConditions: options.externalConditions,\n            extensions: options.extensions,\n            tryIndex: options.tryIndex ?? true,\n            tryPrefix: options.tryPrefix,\n            preserveSymlinks: options.preserveSymlinks,\n            tsconfigPaths: options.tsconfigPaths,\n          },\n          environmentConsumer: partialEnv.config.consumer,\n          environmentName: partialEnv.name,\n          builtins: partialEnv.config.resolve.builtins,\n          external: options.external,\n          noExternal: noExternal,\n          dedupe: options.dedupe,\n          disableCache:\n            partialEnv.config.command === 'serve' &&\n            // eslint-disable-next-line eqeqeq\n            partialEnv.config.server.watch === null,\n          legacyInconsistentCjsInterop: options.legacyInconsistentCjsInterop,\n          finalizeBareSpecifier: !depsOptimizerEnabled\n            ? undefined\n            : (resolvedId, rawId, importer) => {\n                const depsOptimizer = getDepsOptimizer()\n                // if we reach here, it's a valid dep import that hasn't been optimized.\n                const isJsType = isOptimizable(\n                  resolvedId,\n                  depsOptimizer.options,\n                )\n                const exclude = depsOptimizer?.options.exclude\n\n                // check for deep import, e.g. \"my-lib/foo\"\n                const deepMatch = deepImportRE.exec(rawId)\n                // package name doesn't include postfixes\n                // trim them to support importing package with queries (e.g. `import css from 'normalize.css?inline'`)\n                const pkgId = deepMatch\n                  ? deepMatch[1] || deepMatch[2]\n                  : cleanUrl(rawId)\n\n                const skipOptimization =\n                  depsOptimizer.options.noDiscovery ||\n                  !isJsType ||\n                  (importer && isInNodeModules(importer)) ||\n                  exclude?.includes(pkgId) ||\n                  exclude?.includes(rawId) ||\n                  SPECIAL_QUERY_RE.test(resolvedId)\n\n                let newId = resolvedId\n                if (skipOptimization) {\n                  // excluded from optimization\n                  // Inject a version query to npm deps so that the browser\n                  // can cache it without re-validation, but only do so for known js types.\n                  // otherwise we may introduce duplicated modules for externalized files\n                  // from pre-bundled deps.\n                  const versionHash = depsOptimizer!.metadata.browserHash\n                  if (versionHash && isJsType) {\n                    newId = injectQuery(newId, `v=${versionHash}`)\n                  }\n                } else {\n                  // this is a missing import, queue optimize-deps re-run and\n                  // get a resolved its optimized info\n                  const optimizedInfo = depsOptimizer!.registerMissingImport(\n                    rawId,\n                    newId,\n                  )\n                  newId = depsOptimizer!.getOptimizedDepId(optimizedInfo)\n                }\n                return newId\n              },\n          finalizeOtherSpecifiers: !depsOptimizerEnabled\n            ? undefined\n            : (resolvedId, rawId) => {\n                const depsOptimizer = getDepsOptimizer()\n                const newResolvedId = ensureVersionQuery(\n                  resolvedId,\n                  rawId,\n                  options,\n                  depsOptimizer,\n                )\n                return newResolvedId === resolvedId ? undefined : newResolvedId\n              },\n          resolveSubpathImports(id, importer, isRequire, scan) {\n            return resolveSubpathImports(id, importer, {\n              ...options,\n              isRequire: resolveOptions.isRequire ?? isRequire,\n              scan,\n            })\n          },\n\n          ...(partialEnv.config.command === 'serve'\n            ? {\n                async onWarn(msg) {\n                  getEnv().logger.warn(`warning: ${msg}`, {\n                    clear: true,\n                    timestamp: true,\n                  })\n                },\n              }\n            : {}),\n          ...(debug\n            ? {\n                async onDebug(message) {\n                  debug(message)\n                },\n              }\n            : {}),\n        })\n        ;(plugin as Plugin).perEnvironmentWatchChangeDuringDev = true\n        return plugin\n      },\n    ),\n  ]\n}\n\nfunction optimizerResolvePlugin(\n  resolveOptions: ResolvePluginOptionsWithOverrides,\n): Plugin {\n  const { root, asSrc } = resolveOptions\n\n  return {\n    name: 'vite:resolve-dev',\n    applyToEnvironment(environment) {\n      return (\n        !environment.config.experimental.bundledDev &&\n        !isDepOptimizationDisabled(environment.config.optimizeDeps)\n      )\n    },\n    resolveId: {\n      filter: {\n        id: {\n          exclude: [\n            /^\\0/,\n            /^virtual:/,\n            // When injected directly in html/client code\n            /^\\/virtual:/,\n            /^__vite-/,\n          ],\n        },\n      },\n      async handler(id, importer, resolveOpts) {\n        // The resolve plugin is used for createIdResolver and the depsOptimizer should be\n        // disabled in that case, so deps optimization is opt-in when creating the plugin.\n        const depsOptimizer =\n          resolveOptions.optimizeDeps && this.environment.mode === 'dev'\n            ? this.environment.depsOptimizer\n            : undefined\n        if (!depsOptimizer) {\n          return\n        }\n\n        const options: InternalResolveOptions = {\n          isRequire: resolveOpts.kind === 'require-call',\n          ...this.environment.config.resolve,\n          ...resolveOptions,\n          scan: resolveOpts.scan ?? resolveOptions.scan,\n        }\n        options.preferRelative ||= importer?.endsWith('.html')\n\n        // resolve pre-bundled deps requests, these could be resolved by\n        // tryFileResolve or /fs/ resolution but these files may not yet\n        // exists if we are in the middle of a deps re-processing\n        if (asSrc && depsOptimizer.isOptimizedDepUrl(id)) {\n          const optimizedPath = id.startsWith(FS_PREFIX)\n            ? fsPathFromId(id)\n            : normalizePath(path.resolve(root, id.slice(1)))\n          return optimizedPath\n        }\n\n        if (!isDataUrl(id) && !isExternalUrl(id)) {\n          if (\n            id[0] === '.' ||\n            (options.preferRelative && startsWithWordCharRE.test(id))\n          ) {\n            const basedir = importer ? path.dirname(importer) : root\n            const fsPath = path.resolve(basedir, id)\n            // handle browser field mapping for relative imports\n\n            const normalizedFsPath = normalizePath(fsPath)\n\n            if (depsOptimizer.isOptimizedDepFile(normalizedFsPath)) {\n              // Optimized files could not yet exist in disk, resolve to the full path\n              // Inject the current browserHash version if the path doesn't have one\n              if (!DEP_VERSION_RE.test(normalizedFsPath)) {\n                const browserHash = optimizedDepInfoFromFile(\n                  depsOptimizer.metadata,\n                  normalizedFsPath,\n                )?.browserHash\n                if (browserHash) {\n                  return injectQuery(normalizedFsPath, `v=${browserHash}`)\n                }\n              }\n              return normalizedFsPath\n            }\n          }\n\n          // bare package imports, perform node resolve\n          if (bareImportRE.test(id)) {\n            let res: string | PartialResolvedId | undefined\n            if (\n              asSrc &&\n              !options.scan &&\n              (res = await tryOptimizedResolve(\n                depsOptimizer,\n                id,\n                importer,\n                options.preserveSymlinks,\n                options.packageCache,\n              ))\n            ) {\n              return res\n            }\n          }\n        }\n      },\n    },\n  }\n}\n\nfunction resolveSubpathImports(\n  id: string,\n  importer: string | undefined,\n  options: InternalResolveOptions,\n) {\n  if (!importer || !id.startsWith(subpathImportsPrefix)) return\n  const basedir = path.dirname(importer)\n  const pkgData = findNearestPackageData(basedir, options.packageCache)\n  if (!pkgData) return\n\n  let { file: idWithoutPostfix, postfix } = splitFileAndPostfix(id.slice(1))\n  idWithoutPostfix = '#' + idWithoutPostfix\n\n  let importsPath = resolveExportsOrImports(\n    pkgData.data,\n    idWithoutPostfix,\n    options,\n    'imports',\n  )\n\n  if (importsPath?.[0] === '.') {\n    importsPath = path.relative(basedir, path.join(pkgData.dir, importsPath))\n\n    if (!relativePrefixRE.test(importsPath)) {\n      importsPath = `./${importsPath}`\n    }\n  }\n\n  return importsPath + postfix\n}\n\nfunction ensureVersionQuery(\n  resolved: string,\n  id: string,\n  options: InternalResolveOptions,\n  depsOptimizer?: DepsOptimizer,\n): string {\n  if (\n    !options.isBuild &&\n    !options.scan &&\n    depsOptimizer &&\n    !(resolved === normalizedClientEntry || resolved === normalizedEnvEntry)\n  ) {\n    // Ensure that direct imports of node_modules have the same version query\n    // as if they would have been imported through a bare import\n    // Use the original id to do the check as the resolved id may be the real\n    // file path after symlinks resolution\n    const isNodeModule = isInNodeModules(id) || isInNodeModules(resolved)\n\n    if (isNodeModule && !DEP_VERSION_RE.test(resolved)) {\n      const versionHash = depsOptimizer.metadata.browserHash\n      if (versionHash && isOptimizable(resolved, depsOptimizer.options)) {\n        resolved = injectQuery(resolved, `v=${versionHash}`)\n      }\n    }\n  }\n  return resolved\n}\n\nexport function tryFsResolve(\n  fsPath: string,\n  options: InternalResolveOptions,\n  tryIndex = true,\n  skipPackageJson = false,\n): string | undefined {\n  // Dependencies like es5-ext use `#` in their paths. We don't support `#` in user\n  // source code so we only need to perform the check for dependencies.\n  // We don't support `?` in node_modules paths, so we only need to check in this branch.\n  const hashIndex = fsPath.indexOf('#')\n  if (hashIndex >= 0 && isInNodeModules(fsPath)) {\n    const queryIndex = fsPath.indexOf('?')\n    // We only need to check foo#bar?baz and foo#bar, ignore foo?bar#baz\n    if (queryIndex < 0 || queryIndex > hashIndex) {\n      const file = queryIndex > hashIndex ? fsPath.slice(0, queryIndex) : fsPath\n      const res = tryCleanFsResolve(file, options, tryIndex, skipPackageJson)\n      if (res) return res + fsPath.slice(file.length)\n    }\n  }\n\n  const { file, postfix } = splitFileAndPostfix(fsPath)\n  const res = tryCleanFsResolve(file, options, tryIndex, skipPackageJson)\n  if (res) return res + postfix\n}\n\nconst knownTsOutputRE = /\\.(?:js|mjs|cjs|jsx)$/\nconst isPossibleTsOutput = (url: string): boolean => knownTsOutputRE.test(url)\n\nfunction tryCleanFsResolve(\n  file: string,\n  options: InternalResolveOptions,\n  tryIndex = true,\n  skipPackageJson = false,\n): string | undefined {\n  const { tryPrefix, extensions, preserveSymlinks } = options\n\n  // Optimization to get the real type or file type (directory, file, other)\n  const fileResult = tryResolveRealFileOrType(file, options.preserveSymlinks)\n\n  if (fileResult?.path) return fileResult.path\n\n  let res: string | undefined\n\n  // If path.dirname is a valid directory, try extensions and ts resolution logic\n  const possibleJsToTs = isPossibleTsOutput(file)\n  if (possibleJsToTs || options.extensions.length || tryPrefix) {\n    const dirPath = path.dirname(file)\n    if (isDirectory(dirPath)) {\n      if (possibleJsToTs) {\n        // try resolve .js, .mjs, .cjs or .jsx import to typescript file\n        const fileExt = path.extname(file)\n        const fileName = file.slice(0, -fileExt.length)\n        if (\n          (res = tryResolveRealFile(\n            fileName + fileExt.replace('js', 'ts'),\n            preserveSymlinks,\n          ))\n        )\n          return res\n        // for .js, also try .tsx\n        if (\n          fileExt === '.js' &&\n          (res = tryResolveRealFile(fileName + '.tsx', preserveSymlinks))\n        )\n          return res\n      }\n\n      if (\n        (res = tryResolveRealFileWithExtensions(\n          file,\n          extensions,\n          preserveSymlinks,\n        ))\n      )\n        return res\n\n      if (tryPrefix) {\n        const prefixed = `${dirPath}/${options.tryPrefix}${path.basename(file)}`\n\n        if ((res = tryResolveRealFile(prefixed, preserveSymlinks))) return res\n\n        if (\n          (res = tryResolveRealFileWithExtensions(\n            prefixed,\n            extensions,\n            preserveSymlinks,\n          ))\n        )\n          return res\n      }\n    }\n  }\n\n  if (tryIndex && fileResult?.type === 'directory') {\n    // Path points to a directory, check for package.json and entry and /index file\n    const dirPath = file\n\n    if (!skipPackageJson) {\n      let pkgPath = `${dirPath}/package.json`\n      try {\n        if (fs.existsSync(pkgPath)) {\n          if (!options.preserveSymlinks) {\n            pkgPath = safeRealpathSync(pkgPath)\n          }\n          // path points to a node package\n          const pkg = loadPackageData(pkgPath)\n          return resolvePackageEntry(dirPath, pkg, options)\n        }\n      } catch (e) {\n        // This check is best effort, so if an entry is not found, skip error for now\n        if (e.code !== ERR_RESOLVE_PACKAGE_ENTRY_FAIL && e.code !== 'ENOENT')\n          throw e\n      }\n    }\n\n    if (\n      (res = tryResolveRealFileWithExtensions(\n        `${dirPath}/index`,\n        extensions,\n        preserveSymlinks,\n      ))\n    )\n      return res\n\n    if (tryPrefix) {\n      if (\n        (res = tryResolveRealFileWithExtensions(\n          `${dirPath}/${options.tryPrefix}index`,\n          extensions,\n          preserveSymlinks,\n        ))\n      )\n        return res\n    }\n  }\n}\n\nexport function tryNodeResolve(\n  id: string,\n  importer: string | null | undefined,\n  options: InternalResolveOptions,\n  depsOptimizer?: DepsOptimizer,\n  externalize?: boolean,\n): PartialResolvedId | undefined {\n  const { root, dedupe, isBuild, preserveSymlinks, packageCache } = options\n\n  // check for deep import, e.g. \"my-lib/foo\"\n  const deepMatch = deepImportRE.exec(id)\n  // package name doesn't include postfixes\n  // trim them to support importing package with queries (e.g. `import css from 'normalize.css?inline'`)\n  const pkgId = deepMatch ? deepMatch[1] || deepMatch[2] : cleanUrl(id)\n\n  let basedir: string\n  if (dedupe.includes(pkgId)) {\n    basedir = root\n  } else if (\n    importer &&\n    path.isAbsolute(importer) &&\n    // css processing appends `*` for importer\n    (importer.endsWith('*') || fs.existsSync(cleanUrl(importer)))\n  ) {\n    basedir = path.dirname(importer)\n  } else {\n    basedir = root\n  }\n\n  const isModuleBuiltin = (id: string) => isBuiltin(options.builtins, id)\n\n  let selfPkg = null\n  if (!isModuleBuiltin(id) && !id.includes('\\0') && bareImportRE.test(id)) {\n    // check if it's a self reference dep.\n    const selfPackageData = findNearestPackageData(basedir, packageCache)\n    selfPkg =\n      selfPackageData?.data.exports && selfPackageData.data.name === pkgId\n        ? selfPackageData\n        : null\n  }\n\n  const pkg =\n    selfPkg ||\n    resolvePackageData(pkgId, basedir, preserveSymlinks, packageCache)\n  if (!pkg) {\n    // if import can't be found, check if it's an optional peer dep.\n    // if so, we can resolve to a special id that errors only when imported.\n    if (\n      !options.disableOptionalPeerDepHandling &&\n      basedir !== root && // root has no peer dep\n      !isModuleBuiltin(id) &&\n      !id.includes('\\0') &&\n      bareImportRE.test(id)\n    ) {\n      const mainPkg = findNearestMainPackageData(basedir, packageCache)?.data\n      if (mainPkg) {\n        const pkgName = getNpmPackageName(id)\n        if (\n          pkgName != null &&\n          mainPkg.peerDependencies?.[pkgName] &&\n          mainPkg.peerDependenciesMeta?.[pkgName]?.optional\n        ) {\n          return {\n            id: `${optionalPeerDepId}:${id}:${mainPkg.name}`,\n          }\n        }\n      }\n    }\n    return\n  }\n\n  const resolveId = deepMatch ? resolveDeepImport : resolvePackageEntry\n  const unresolvedId = deepMatch ? '.' + id.slice(pkgId.length) : id\n\n  let resolved = resolveId(unresolvedId, pkg, options, externalize)\n  if (!resolved) {\n    return\n  }\n\n  const processResult = (resolved: PartialResolvedId) => {\n    if (!externalize) {\n      return resolved\n    }\n    if (!canExternalizeFile(resolved.id)) {\n      return resolved\n    }\n\n    let resolvedId = id\n    if (\n      deepMatch &&\n      !pkg.data.exports &&\n      path.extname(id) !== path.extname(resolved.id)\n    ) {\n      // id date-fns/locale\n      // resolve.id ...date-fns/esm/locale/index.js\n      const index = resolved.id.indexOf(id)\n      if (index > -1) {\n        resolvedId = resolved.id.slice(index)\n        debug?.(\n          `[processResult] ${colors.cyan(id)} -> ${colors.dim(resolvedId)}`,\n        )\n      }\n    }\n    return { ...resolved, id: resolvedId, external: true }\n  }\n\n  if (!options.idOnly && ((!options.scan && isBuild) || externalize)) {\n    // Resolve package side effects for build so that rollup can better\n    // perform tree-shaking\n    return processResult({\n      id: resolved,\n      moduleSideEffects: pkg.hasSideEffects(resolved),\n      packageJsonPath: findNearestPackagePath(\n        resolved,\n        options.legacyInconsistentCjsInterop,\n        options.packageCache,\n        isBuild,\n      ),\n    })\n  }\n\n  if (\n    !isInNodeModules(resolved) || // linked\n    !depsOptimizer || // resolving before listening to the server\n    options.scan // initial esbuild scan phase\n  ) {\n    return { id: resolved }\n  }\n\n  // if we reach here, it's a valid dep import that hasn't been optimized.\n  const isJsType = isOptimizable(resolved, depsOptimizer.options)\n  const exclude = depsOptimizer.options.exclude\n\n  const skipOptimization =\n    depsOptimizer.options.noDiscovery ||\n    !isJsType ||\n    (importer && isInNodeModules(importer)) ||\n    exclude?.includes(pkgId) ||\n    exclude?.includes(id) ||\n    SPECIAL_QUERY_RE.test(resolved)\n\n  if (skipOptimization) {\n    // excluded from optimization\n    // Inject a version query to npm deps so that the browser\n    // can cache it without re-validation, but only do so for known js types.\n    // otherwise we may introduce duplicated modules for externalized files\n    // from pre-bundled deps.\n    const versionHash = depsOptimizer.metadata.browserHash\n    if (versionHash && isJsType) {\n      resolved = injectQuery(resolved, `v=${versionHash}`)\n    }\n  } else {\n    // this is a missing import, queue optimize-deps re-run and\n    // get a resolved its optimized info\n    const optimizedInfo = depsOptimizer.registerMissingImport(id, resolved)\n    resolved = depsOptimizer.getOptimizedDepId(optimizedInfo)\n  }\n\n  return { id: resolved }\n}\n\nexport async function tryOptimizedResolve(\n  depsOptimizer: DepsOptimizer,\n  id: string,\n  importer?: string,\n  preserveSymlinks?: boolean,\n  packageCache?: PackageCache,\n): Promise<string | undefined> {\n  // TODO: we need to wait until scanning is done here as this function\n  // is used in the preAliasPlugin to decide if an aliased dep is optimized,\n  // and avoid replacing the bare import with the resolved path.\n  // We should be able to remove this in the future\n  await depsOptimizer.scanProcessing\n\n  const metadata = depsOptimizer.metadata\n\n  const depInfo = optimizedDepInfoFromId(metadata, id)\n  if (depInfo) {\n    return depsOptimizer.getOptimizedDepId(depInfo)\n  }\n\n  if (!importer) return\n\n  // further check if id is imported by nested dependency\n  let idPkgDir: string | undefined\n  const nestedIdMatch = `> ${id}`\n\n  for (const optimizedData of metadata.depInfoList) {\n    if (!optimizedData.src) continue // Ignore chunks\n\n    // check where \"foo\" is nested in \"my-lib > foo\"\n    if (!optimizedData.id.endsWith(nestedIdMatch)) continue\n\n    // lazily initialize idPkgDir\n    if (idPkgDir == null) {\n      const pkgName = getNpmPackageName(id)\n      if (!pkgName) break\n      idPkgDir = resolvePackageData(\n        pkgName,\n        importer,\n        preserveSymlinks,\n        packageCache,\n      )?.dir\n      // if still null, it likely means that this id isn't a dep for importer.\n      // break to bail early\n      if (idPkgDir == null) break\n      idPkgDir = normalizePath(idPkgDir)\n    }\n\n    // match by src to correctly identify if id belongs to nested dependency\n    if (optimizedData.src.startsWith(withTrailingSlash(idPkgDir))) {\n      return depsOptimizer.getOptimizedDepId(optimizedData)\n    }\n  }\n}\n\nexport function resolvePackageEntry(\n  id: string,\n  { dir, data, setResolvedCache, getResolvedCache }: PackageData,\n  options: InternalResolveOptions,\n  externalize?: boolean,\n): string | undefined {\n  const { file: idWithoutPostfix, postfix } = splitFileAndPostfix(id)\n\n  const cached = getResolvedCache('.', options)\n  if (cached) {\n    return cached + postfix\n  }\n\n  try {\n    let entryPoint: string | undefined\n\n    // resolve exports field with highest priority\n    // using https://github.com/lukeed/resolve.exports\n    if (data.exports) {\n      entryPoint = resolveExportsOrImports(\n        data,\n        '.',\n        options,\n        'exports',\n        externalize,\n      )\n    }\n\n    // fallback to mainFields if still not resolved\n    if (!entryPoint) {\n      for (const field of options.mainFields) {\n        if (field === 'browser') {\n          entryPoint = tryResolveBrowserEntry(dir, data, options)\n          if (entryPoint) {\n            break\n          }\n        } else if (typeof data[field] === 'string') {\n          entryPoint = data[field]\n          break\n        }\n      }\n    }\n    entryPoint ||= data.main\n\n    // try default entry when entry is not define\n    // https://nodejs.org/api/modules.html#all-together\n    const entryPoints = entryPoint\n      ? [entryPoint]\n      : ['index.js', 'index.json', 'index.node']\n\n    for (let entry of entryPoints) {\n      // make sure we don't get scripts when looking for sass\n      let skipPackageJson = false\n      if (\n        options.mainFields[0] === 'sass' &&\n        !options.extensions.includes(path.extname(entry))\n      ) {\n        entry = ''\n        skipPackageJson = true\n      } else {\n        // resolve object browser field in package.json\n        const { browser: browserField } = data\n        if (options.mainFields.includes('browser') && isObject(browserField)) {\n          entry = mapWithBrowserField(entry, browserField) || entry\n        }\n      }\n\n      const entryPointPath = path.join(dir, entry)\n      const resolvedEntryPoint = tryFsResolve(\n        entryPointPath,\n        options,\n        true,\n        skipPackageJson,\n      )\n      if (resolvedEntryPoint) {\n        debug?.(\n          `[package entry] ${colors.cyan(idWithoutPostfix)} -> ${colors.dim(\n            resolvedEntryPoint,\n          )}${postfix !== '' ? ` (postfix: ${postfix})` : ''}`,\n        )\n        setResolvedCache('.', resolvedEntryPoint, options)\n        return resolvedEntryPoint + postfix\n      }\n    }\n  } catch (e) {\n    packageEntryFailure(id, e.message)\n  }\n  packageEntryFailure(id)\n}\n\nfunction packageEntryFailure(id: string, details?: string) {\n  const err: any = new Error(\n    `Failed to resolve entry for package \"${id}\". ` +\n      `The package may have incorrect main/module/exports specified in its package.json` +\n      (details ? ': ' + details : '.'),\n  )\n  err.code = ERR_RESOLVE_PACKAGE_ENTRY_FAIL\n  throw err\n}\n\nfunction getConditions(\n  conditions: string[],\n  isProduction: boolean,\n  isRequire: boolean | undefined,\n) {\n  const resolvedConditions = conditions.map((condition) => {\n    if (condition === DEV_PROD_CONDITION) {\n      return isProduction ? 'production' : 'development'\n    }\n    return condition\n  })\n\n  if (isRequire) {\n    resolvedConditions.push('require')\n  } else {\n    resolvedConditions.push('import')\n  }\n\n  return resolvedConditions\n}\n\nfunction resolveExportsOrImports(\n  pkg: PackageData['data'],\n  key: string,\n  options: InternalResolveOptions,\n  type: 'imports' | 'exports',\n  externalize?: boolean,\n) {\n  const conditions = getConditions(\n    externalize ? options.externalConditions : options.conditions,\n    options.isProduction,\n    options.isRequire,\n  )\n\n  const fn = type === 'imports' ? imports : exports\n  const result = fn(pkg, key, { conditions, unsafe: true })\n  return result ? result[0] : undefined\n}\n\nfunction resolveDeepImport(\n  id: string,\n  { setResolvedCache, getResolvedCache, dir, data }: PackageData,\n  options: InternalResolveOptions,\n  externalize?: boolean,\n): string | undefined {\n  const cache = getResolvedCache(id, options)\n  if (cache) {\n    return cache\n  }\n\n  let relativeId: string | undefined | void = id\n  const { exports: exportsField, browser: browserField } = data\n\n  // map relative based on exports data\n  if (exportsField) {\n    if (isObject(exportsField) && !Array.isArray(exportsField)) {\n      // resolve without postfix (see #7098)\n      const { file, postfix } = splitFileAndPostfix(relativeId)\n      const exportsId = resolveExportsOrImports(\n        data,\n        file,\n        options,\n        'exports',\n        externalize,\n      )\n      if (exportsId !== undefined) {\n        relativeId = exportsId + postfix\n      } else {\n        relativeId = undefined\n      }\n    } else {\n      // not exposed\n      relativeId = undefined\n    }\n    if (!relativeId) {\n      throw new Error(\n        `Package subpath '${relativeId}' is not defined by \"exports\" in ` +\n          `${path.join(dir, 'package.json')}.`,\n      )\n    }\n  } else if (options.mainFields.includes('browser') && isObject(browserField)) {\n    // resolve without postfix (see #7098)\n    const { file, postfix } = splitFileAndPostfix(relativeId)\n    const mapped = mapWithBrowserField(file, browserField)\n    if (mapped) {\n      relativeId = mapped + postfix\n    } else if (mapped === false) {\n      setResolvedCache(id, browserExternalId, options)\n      return browserExternalId\n    }\n  }\n\n  if (relativeId) {\n    const resolved = tryFsResolve(\n      path.join(dir, relativeId),\n      options,\n      !exportsField, // try index only if no exports field\n    )\n    if (resolved) {\n      debug?.(\n        `[node/deep-import] ${colors.cyan(id)} -> ${colors.dim(resolved)}`,\n      )\n      setResolvedCache(id, resolved, options)\n      return resolved\n    }\n  }\n}\n\nfunction tryResolveBrowserEntry(\n  dir: string,\n  data: PackageData['data'],\n  options: InternalResolveOptions,\n) {\n  // handle edge case with browser and module field semantics\n\n  // check browser field\n  // https://github.com/defunctzombie/package-browser-field-spec\n  const browserEntry =\n    typeof data.browser === 'string'\n      ? data.browser\n      : isObject(data.browser) && data.browser['.']\n  if (browserEntry) {\n    // check if the package also has a \"module\" field.\n    if (\n      !options.isRequire &&\n      options.mainFields.includes('module') &&\n      typeof data.module === 'string' &&\n      data.module !== browserEntry\n    ) {\n      // if both are present, we may have a problem: some package points both\n      // to ESM, with \"module\" targeting Node.js, while some packages points\n      // \"module\" to browser ESM and \"browser\" to UMD/IIFE.\n      // the heuristics here is to actually read the browser entry when\n      // possible and check for hints of ESM. If it is not ESM, prefer \"module\"\n      // instead; Otherwise, assume it's ESM and use it.\n      const resolvedBrowserEntry = tryFsResolve(\n        path.join(dir, browserEntry),\n        options,\n      )\n      if (resolvedBrowserEntry) {\n        const content = fs.readFileSync(resolvedBrowserEntry, 'utf-8')\n        if (hasESMSyntax(content)) {\n          // likely ESM, prefer browser\n          return browserEntry\n        } else {\n          // non-ESM, UMD or IIFE or CJS(!!! e.g. firebase 7.x), prefer module\n          return data.module\n        }\n      }\n    } else {\n      return browserEntry\n    }\n  }\n}\n\n/**\n * given a relative path in pkg dir,\n * return a relative path in pkg dir,\n * mapped with the \"map\" object\n *\n * - Returning `undefined` means there is no browser mapping for this id\n * - Returning `false` means this id is explicitly externalized for browser\n */\nfunction mapWithBrowserField(\n  relativePathInPkgDir: string,\n  map: Record<string, string | false>,\n): string | false | undefined {\n  const normalizedPath = path.posix.normalize(relativePathInPkgDir)\n\n  for (const key in map) {\n    const normalizedKey = path.posix.normalize(key)\n    if (\n      normalizedPath === normalizedKey ||\n      equalWithoutSuffix(normalizedPath, normalizedKey, '.js') ||\n      equalWithoutSuffix(normalizedPath, normalizedKey, '/index.js')\n    ) {\n      return map[key]\n    }\n  }\n}\n\nfunction equalWithoutSuffix(path: string, key: string, suffix: string) {\n  return key.endsWith(suffix) && key.slice(0, -suffix.length) === path\n}\n\nfunction tryResolveRealFile(\n  file: string,\n  preserveSymlinks?: boolean,\n): string | undefined {\n  const stat = tryStatSync(file)\n  if (stat?.isFile()) return getRealPath(file, preserveSymlinks)\n}\n\nfunction tryResolveRealFileWithExtensions(\n  filePath: string,\n  extensions: string[],\n  preserveSymlinks?: boolean,\n): string | undefined {\n  for (const ext of extensions) {\n    const res = tryResolveRealFile(filePath + ext, preserveSymlinks)\n    if (res) return res\n  }\n}\n\nfunction tryResolveRealFileOrType(\n  file: string,\n  preserveSymlinks?: boolean,\n): { path?: string; type: 'directory' | 'file' } | undefined {\n  const fileStat = tryStatSync(file)\n  if (fileStat?.isFile()) {\n    return { path: getRealPath(file, preserveSymlinks), type: 'file' }\n  }\n  if (fileStat?.isDirectory()) {\n    return { type: 'directory' }\n  }\n  return\n}\n\nfunction getRealPath(resolved: string, preserveSymlinks?: boolean): string {\n  if (!preserveSymlinks) {\n    resolved = safeRealpathSync(resolved)\n  }\n  return normalizePath(resolved)\n}\n\nfunction isDirectory(path: string): boolean {\n  const stat = tryStatSync(path)\n  return stat?.isDirectory() ?? false\n}\n\nfunction findNearestPackagePath(\n  file: string,\n  legacyInconsistentCjsInterop: boolean | undefined,\n  packageCache: PackageCache | undefined,\n  isBuild: boolean,\n) {\n  if (!isBuild || legacyInconsistentCjsInterop) return\n  const pkgData = findNearestPackageData(file, packageCache)\n  return pkgData ? path.join(pkgData.dir, 'package.json') : null\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/terser.ts",
    "content": "import { pathToFileURL } from 'node:url'\nimport { WorkerWithFallback } from 'artichokie'\nimport type {\n  TerserMinifyOptions,\n  TerserMinifyOutput,\n} from '#types/internal/terserOptions'\nimport type { Plugin } from '../plugin'\nimport type { ResolvedConfig } from '..'\nimport { _dirname, generateCodeFrame } from '../utils'\nimport { nodeResolveWithVite } from '../nodeResolve'\n\nexport interface TerserOptions extends TerserMinifyOptions {\n  /**\n   * Vite-specific option to specify the max number of workers to spawn\n   * when minifying files with terser.\n   *\n   * @default number of CPUs minus 1\n   */\n  maxWorkers?: number\n}\n\nlet terserPath: string | undefined\nfunction loadTerserPath(root: string) {\n  if (terserPath) return terserPath\n\n  // Try resolve from project root first, then the current vite installation path\n  const resolved =\n    nodeResolveWithVite('terser', undefined, { root }) ??\n    nodeResolveWithVite('terser', _dirname, { root })\n  if (resolved) return (terserPath = resolved)\n\n  // Error if we can't find the package\n  throw new Error(\n    'terser not found. Since Vite v3, terser has become an optional dependency. You need to install it.',\n  )\n}\n\nexport function terserPlugin(config: ResolvedConfig): Plugin {\n  const { maxWorkers, ...terserOptions } = config.build.terserOptions\n\n  const makeWorker = () =>\n    new WorkerWithFallback(\n      () =>\n        async (\n          terserPath: string,\n          code: string,\n          options: TerserMinifyOptions,\n        ) => {\n          const terser: typeof import('terser') = await import(terserPath)\n          try {\n            return (await terser.minify(code, options)) as TerserMinifyOutput\n          } catch (e) {\n            // convert to a plain object as additional properties of Error instances are not\n            // sent back to the main thread\n            throw { stack: e.stack /* stack is non-enumerable */, ...e }\n          }\n        },\n      {\n        shouldUseFake(_terserPath, _code, options) {\n          return !!(\n            (typeof options.mangle === 'object' &&\n              (options.mangle.nth_identifier?.get ||\n                (typeof options.mangle.properties === 'object' &&\n                  options.mangle.properties.nth_identifier?.get))) ||\n            typeof options.format?.comments === 'function' ||\n            typeof options.output?.comments === 'function' ||\n            options.nameCache\n          )\n        },\n        max: maxWorkers,\n      },\n    )\n\n  let worker: ReturnType<typeof makeWorker>\n\n  return {\n    name: 'vite:terser',\n\n    applyToEnvironment(environment) {\n      // We also need the plugin even if minify isn't 'terser' as we force\n      // terser in plugin-legacy\n      return !!environment.config.build.minify\n    },\n\n    async renderChunk(code, chunk, outputOptions) {\n      // This plugin is included for any non-false value of config.build.minify,\n      // so that normal chunks can use the preferred minifier, and legacy chunks\n      // can use terser.\n      if (\n        config.build.minify !== 'terser' &&\n        !this.environment.config.isOutputOptionsForLegacyChunks?.(outputOptions)\n      ) {\n        return null\n      }\n\n      // Lazy load worker.\n      worker ||= makeWorker()\n\n      const terserPath = pathToFileURL(loadTerserPath(config.root)).href\n      try {\n        const res = await worker.run(terserPath, code, {\n          safari10: true,\n          ...terserOptions,\n          format: {\n            ...terserOptions.format,\n            // For ES lib mode, preserve comments to keep pure annotations for tree-shaking\n            preserve_annotations:\n              config.build.lib && outputOptions.format === 'es'\n                ? true\n                : terserOptions.format?.preserve_annotations,\n          },\n          sourceMap: !!outputOptions.sourcemap,\n          module: outputOptions.format.startsWith('es'),\n          toplevel: outputOptions.format === 'cjs',\n        })\n        return {\n          code: res.code!,\n          map: res.map as any,\n        }\n      } catch (e) {\n        if (e.line !== undefined && e.col !== undefined) {\n          e.loc = {\n            file: chunk.fileName,\n            line: e.line,\n            column: e.col,\n          }\n        }\n        if (e.pos !== undefined) {\n          e.frame = generateCodeFrame(code, e.pos)\n        }\n        throw e\n      }\n    },\n\n    closeBundle() {\n      worker?.stop()\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/wasm.ts",
    "content": "import MagicString from 'magic-string'\nimport { exactRegex } from 'rolldown/filter'\nimport type { RolldownMagicString } from 'rolldown'\nimport { createToImportMetaURLBasedRelativeRuntime } from '../build'\nimport { type Plugin, perEnvironmentPlugin } from '../plugin'\nimport { cleanUrl } from '../../shared/utils'\nimport { assetUrlRE, fileToUrl } from './asset'\n\nconst wasmHelperId = '\\0vite/wasm-helper.js'\n\nconst wasmInitRE = /(?<![?#].*)\\.wasm\\?init/\n\nconst wasmInitUrlRE: RegExp = /__VITE_WASM_INIT__([\\w$]+)__/g\n\nconst wasmHelper = async (opts = {}, url: string) => {\n  let result\n  if (url.startsWith('data:')) {\n    const urlContent = url.replace(/^data:.*?base64,/, '')\n    let bytes\n    if (typeof Buffer === 'function' && typeof Buffer.from === 'function') {\n      bytes = Buffer.from(urlContent, 'base64')\n    } else if (typeof atob === 'function') {\n      const binaryString = atob(urlContent)\n      bytes = new Uint8Array(binaryString.length)\n      for (let i = 0; i < binaryString.length; i++) {\n        bytes[i] = binaryString.charCodeAt(i)\n      }\n    } else {\n      throw new Error(\n        'Failed to decode base64-encoded data URL, Buffer and atob are not supported',\n      )\n    }\n    result = await WebAssembly.instantiate(bytes, opts)\n  } else {\n    result = await instantiateFromUrl(url, opts)\n  }\n  return result.instance\n}\n\nconst wasmHelperCode = wasmHelper.toString()\n\nconst instantiateFromUrl = async (url: string, opts?: WebAssembly.Imports) => {\n  // https://github.com/mdn/webassembly-examples/issues/5\n  // WebAssembly.instantiateStreaming requires the server to provide the\n  // correct MIME type for .wasm files, which unfortunately doesn't work for\n  // a lot of static file servers, so we just work around it by getting the\n  // raw buffer.\n  const response = await fetch(url)\n  const contentType = response.headers.get('Content-Type') || ''\n  if (\n    'instantiateStreaming' in WebAssembly &&\n    contentType.startsWith('application/wasm')\n  ) {\n    return WebAssembly.instantiateStreaming(response, opts)\n  } else {\n    const buffer = await response.arrayBuffer()\n    return WebAssembly.instantiate(buffer, opts)\n  }\n}\n\nconst instantiateFromUrlCode = instantiateFromUrl.toString()\n\nconst instantiateFromFile = async (\n  fileUrlString: string,\n  opts?: WebAssembly.Imports,\n) => {\n  const { readFile } = await import('node:fs/promises')\n  const fileUrl = new URL(fileUrlString, /** #__KEEP__ */ import.meta.url)\n  const buffer = await readFile(fileUrl)\n  return WebAssembly.instantiate(buffer, opts)\n}\n\nconst instantiateFromFileCode = instantiateFromFile.toString()\n\nexport const wasmHelperPlugin = (): Plugin => {\n  return perEnvironmentPlugin('vite:wasm-helper', (env) => {\n    return {\n      name: 'vite:wasm-helper',\n\n      resolveId: {\n        filter: { id: exactRegex(wasmHelperId) },\n        handler(id) {\n          return id\n        },\n      },\n\n      load: {\n        filter: { id: [exactRegex(wasmHelperId), wasmInitRE] },\n        async handler(id) {\n          const ssr = this.environment.config.consumer === 'server'\n\n          if (id === wasmHelperId) {\n            return `\nconst instantiateFromUrl = ${ssr ? instantiateFromFileCode : instantiateFromUrlCode}\nexport default ${wasmHelperCode}\n`\n          }\n\n          id = id.split('?')[0]\n          let url = await fileToUrl(this, id, ssr)\n          assetUrlRE.lastIndex = 0\n          if (ssr && assetUrlRE.test(url)) {\n            url = url.replace('__VITE_ASSET__', '__VITE_WASM_INIT__')\n          }\n          return `\n  import initWasm from \"${wasmHelperId}\"\n  export default opts => initWasm(opts, ${JSON.stringify(url)})\n  `\n        },\n      },\n\n      renderChunk:\n        env.config.consumer === 'server'\n          ? {\n              filter: { code: wasmInitUrlRE },\n              async handler(code, chunk, opts, meta) {\n                const toRelativeRuntime =\n                  createToImportMetaURLBasedRelativeRuntime(\n                    opts.format,\n                    this.environment.config.isWorker,\n                  )\n\n                let match: RegExpExecArray | null\n                let s: RolldownMagicString | MagicString | undefined\n\n                wasmInitUrlRE.lastIndex = 0\n                while ((match = wasmInitUrlRE.exec(code))) {\n                  const [full, referenceId] = match\n                  const file = this.getFileName(referenceId)\n                  chunk.viteMetadata!.importedAssets.add(cleanUrl(file))\n                  const { runtime } = toRelativeRuntime(file, chunk.fileName)\n\n                  s ??= meta.magicString ?? new MagicString(code)\n\n                  s.update(\n                    match.index,\n                    match.index + full.length,\n                    `\"+${runtime}+\"`,\n                  )\n                }\n\n                if (!s) return null\n\n                return meta.magicString\n                  ? {\n                      code: s as RolldownMagicString,\n                    }\n                  : {\n                      code: s.toString(),\n                      map: this.environment.config.build.sourcemap\n                        ? (s as MagicString).generateMap({\n                            hires: 'boundary',\n                          })\n                        : null,\n                    }\n              },\n            }\n          : undefined,\n    }\n  })\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/worker.ts",
    "content": "import path from 'node:path'\nimport MagicString from 'magic-string'\nimport type { RolldownOutput, RollupError } from 'rolldown'\nimport colors from 'picocolors'\nimport { type ImportSpecifier, init, parse } from 'es-module-lexer'\nimport { viteWebWorkerPostPlugin as nativeWebWorkerPostPlugin } from 'rolldown/experimental'\nimport type { ResolvedConfig } from '../config'\nimport { type Plugin, perEnvironmentPlugin } from '../plugin'\nimport { ENV_ENTRY, ENV_PUBLIC_PATH } from '../constants'\nimport {\n  encodeURIPath,\n  getHash,\n  injectQuery,\n  normalizePath,\n  prettifyUrl,\n  urlRE,\n} from '../utils'\nimport {\n  BuildEnvironment,\n  ChunkMetadataMap,\n  createToImportMetaURLBasedRelativeRuntime,\n  injectEnvironmentToHooks,\n  onRollupLog,\n  toOutputFilePathInJS,\n} from '../build'\nimport { cleanUrl } from '../../shared/utils'\nimport type { Logger } from '../logger'\nimport { fileToUrl, toOutputFilePathInJSForBundledDev } from './asset'\n\ntype WorkerBundle = {\n  entryFilename: string\n  entryCode: string\n  entryUrlPlaceholder: string\n  referencedAssets: Set<string>\n  watchedFiles: string[]\n}\n\ntype WorkerBundleAsset = {\n  fileName: string\n  /** @deprecated */\n  originalFileName: string | null\n  originalFileNames: string[]\n  source: string | Uint8Array\n}\n\nclass WorkerOutputCache {\n  /**\n   * worker bundle information for each input id\n   * used to bundle the same worker file only once\n   */\n  private bundles = new Map</* inputId */ string, WorkerBundle>()\n  /** list of assets emitted for the worker bundles */\n  private assets = new Map<string, WorkerBundleAsset>()\n  private fileNameHash = new Map<\n    /* hash */ string,\n    /* entryFilename */ string\n  >()\n  private invalidatedBundles = new Set</* inputId */ string>()\n\n  saveWorkerBundle(\n    file: string,\n    watchedFiles: string[],\n    outputEntryFilename: string,\n    outputEntryCode: string,\n    outputAssets: WorkerBundleAsset[],\n    logger: Logger,\n  ): WorkerBundle {\n    for (const asset of outputAssets) {\n      this.saveAsset(asset, logger)\n    }\n    const bundle: WorkerBundle = {\n      entryFilename: outputEntryFilename,\n      entryCode: outputEntryCode,\n      entryUrlPlaceholder:\n        this.generateEntryUrlPlaceholder(outputEntryFilename),\n      referencedAssets: new Set(outputAssets.map((asset) => asset.fileName)),\n      watchedFiles,\n    }\n    this.bundles.set(file, bundle)\n    return bundle\n  }\n\n  saveAsset(asset: WorkerBundleAsset, logger: Logger) {\n    const duplicateAsset = this.assets.get(asset.fileName)\n    if (duplicateAsset) {\n      if (!isSameContent(duplicateAsset.source, asset.source)) {\n        logger.warn(\n          `\\n` +\n            colors.yellow(\n              `The emitted file ${JSON.stringify(asset.fileName)} overwrites a previously emitted file of the same name.`,\n            ),\n        )\n      }\n    }\n    this.assets.set(asset.fileName, asset)\n  }\n\n  invalidateAffectedBundles(file: string) {\n    for (const [bundleInputFile, bundle] of this.bundles.entries()) {\n      if (bundle.watchedFiles.includes(file)) {\n        this.invalidatedBundles.add(bundleInputFile)\n      }\n    }\n  }\n\n  removeBundleIfInvalidated(file: string) {\n    if (this.invalidatedBundles.has(file)) {\n      this.invalidatedBundles.delete(file)\n      this.removeBundle(file)\n    }\n  }\n\n  private removeBundle(file: string) {\n    const bundle = this.bundles.get(file)\n    if (!bundle) return\n\n    this.bundles.delete(file)\n    this.fileNameHash.delete(getHash(bundle.entryFilename))\n\n    this.assets.delete(bundle.entryFilename)\n\n    const keptBundles = [...this.bundles.values()]\n    // remove assets that are only referenced by this bundle\n    for (const asset of bundle.referencedAssets) {\n      if (keptBundles.every((b) => !b.referencedAssets.has(asset))) {\n        this.assets.delete(asset)\n      }\n    }\n  }\n\n  getWorkerBundle(file: string) {\n    return this.bundles.get(file)\n  }\n\n  getAssets() {\n    return this.assets.values()\n  }\n\n  getEntryFilenameFromHash(hash: string) {\n    return this.fileNameHash.get(hash)\n  }\n\n  private generateEntryUrlPlaceholder(entryFilename: string): string {\n    const hash = getHash(entryFilename)\n    if (!this.fileNameHash.has(hash)) {\n      this.fileNameHash.set(hash, entryFilename)\n    }\n    return `__VITE_WORKER_ASSET__${hash}__`\n  }\n}\n\nexport type WorkerType = 'classic' | 'module' | 'ignore'\n\nexport const workerOrSharedWorkerRE: RegExp =\n  /(?:\\?|&)(worker|sharedworker)(?:&|$)/\nconst workerFileRE = /(?:\\?|&)worker_file&type=(\\w+)(?:&|$)/\nconst inlineRE = /[?&]inline\\b/\n\nexport const WORKER_FILE_ID = 'worker_file'\nconst workerOutputCaches = new WeakMap<ResolvedConfig, WorkerOutputCache>()\n\nasync function bundleWorkerEntry(\n  config: ResolvedConfig,\n  id: string,\n): Promise<WorkerBundle> {\n  const input = cleanUrl(id)\n\n  const workerOutput = workerOutputCaches.get(config.mainConfig || config)!\n  workerOutput.removeBundleIfInvalidated(input)\n\n  const bundleInfo = workerOutput.getWorkerBundle(input)\n  if (bundleInfo) {\n    return bundleInfo\n  }\n\n  const newBundleChain = [...config.bundleChain, input]\n  if (config.bundleChain.includes(input)) {\n    throw new Error(\n      'Circular worker imports detected. Vite does not support it. ' +\n        `Import chain: ${newBundleChain.map((id) => prettifyUrl(id, config.root)).join(' -> ')}`,\n    )\n  }\n\n  // bundle the file as entry to support imports\n  const { rolldown } = await import('rolldown')\n  const { plugins, rollupOptions, format } = config.worker\n  const workerConfig = await plugins(newBundleChain)\n  const workerEnvironment = new BuildEnvironment('client', workerConfig) // TODO: should this be 'worker'?\n  await workerEnvironment.init()\n\n  const chunkMetadataMap = new ChunkMetadataMap()\n  const bundle = await rolldown({\n    ...rollupOptions,\n    input,\n    plugins: workerEnvironment.plugins.map((p) =>\n      injectEnvironmentToHooks(workerEnvironment, chunkMetadataMap, p),\n    ),\n    onLog(level, log) {\n      onRollupLog(level, log, workerEnvironment)\n    },\n    // TODO: remove this and enable rolldown's CSS support later\n    moduleTypes: {\n      '.css': 'js',\n      ...rollupOptions.moduleTypes,\n    },\n    preserveEntrySignatures: false,\n    experimental: {\n      ...rollupOptions.experimental,\n      viteMode: true,\n    },\n  })\n  let result: RolldownOutput\n  let watchedFiles: string[] | undefined\n  try {\n    const workerOutputConfig = config.worker.rollupOptions.output\n    const workerConfig = workerOutputConfig\n      ? Array.isArray(workerOutputConfig)\n        ? workerOutputConfig[0] || {}\n        : workerOutputConfig\n      : {}\n    result = await bundle.generate({\n      entryFileNames: path.posix.join(\n        config.build.assetsDir,\n        '[name]-[hash].js',\n      ),\n      chunkFileNames: path.posix.join(\n        config.build.assetsDir,\n        '[name]-[hash].js',\n      ),\n      assetFileNames: path.posix.join(\n        config.build.assetsDir,\n        '[name]-[hash].[ext]',\n      ),\n      minify:\n        workerEnvironment.config.build.minify === 'oxc'\n          ? true\n          : workerEnvironment.config.build.minify === false\n            ? 'dce-only'\n            : undefined,\n      ...workerConfig,\n      format,\n      sourcemap: workerEnvironment.config.build.sourcemap,\n    })\n    watchedFiles = (await bundle.watchFiles).map((f) => normalizePath(f))\n  } catch (e) {\n    // adjust rollup format error\n    if (\n      e instanceof Error &&\n      e.name === 'RollupError' &&\n      (e as RollupError).code === 'INVALID_OPTION' &&\n      e.message.includes('\"output.format\"')\n    ) {\n      e.message = e.message.replace('output.format', 'worker.format')\n    }\n    throw e\n  } finally {\n    await bundle.close()\n  }\n\n  const {\n    output: [outputChunk, ...outputChunks],\n  } = result\n  const assets = outputChunks.map((outputChunk) =>\n    outputChunk.type === 'asset'\n      ? outputChunk\n      : {\n          fileName: outputChunk.fileName,\n          originalFileName: null,\n          originalFileNames: [],\n          source: outputChunk.code,\n        },\n  )\n  if (\n    (config.build.sourcemap === 'hidden' || config.build.sourcemap === true) &&\n    outputChunk.map\n  ) {\n    assets.push({\n      fileName: outputChunk.fileName + '.map',\n      originalFileName: null,\n      originalFileNames: [],\n      source: outputChunk.map.toString(),\n    })\n  }\n\n  const newBundleInfo = workerOutputCaches\n    .get(config.mainConfig || config)!\n    .saveWorkerBundle(\n      input,\n      watchedFiles,\n      outputChunk.fileName,\n      outputChunk.code,\n      assets,\n      config.logger,\n    )\n  return newBundleInfo\n}\n\nexport const workerAssetUrlRE: RegExp = /__VITE_WORKER_ASSET__([a-z\\d]{8})__/g\n\nexport async function workerFileToUrl(\n  config: ResolvedConfig,\n  id: string,\n): Promise<WorkerBundle> {\n  const workerOutput = workerOutputCaches.get(config.mainConfig || config)!\n  const bundle = await bundleWorkerEntry(config, id)\n  workerOutput.saveAsset(\n    {\n      fileName: bundle.entryFilename,\n      originalFileName: null,\n      originalFileNames: [],\n      source: bundle.entryCode,\n    },\n    config.logger,\n  )\n  return bundle\n}\n\nexport function webWorkerPostPlugin(config: ResolvedConfig): Plugin {\n  if (config.isBundled) {\n    return perEnvironmentPlugin(\n      'native:web-worker-post-plugin',\n      (environment) => {\n        if (environment.config.worker.format === 'iife') {\n          return nativeWebWorkerPostPlugin()\n        }\n      },\n    )\n  }\n\n  return {\n    name: 'vite:worker-post',\n    transform: {\n      filter: {\n        code: 'import.meta',\n      },\n      order: 'post',\n      async handler(code, id) {\n        // import.meta is unavailable in the IIFE worker, so we need to replace it\n        if (this.environment.config.worker.format === 'iife') {\n          await init\n\n          let imports: readonly ImportSpecifier[]\n          try {\n            imports = parse(code)[0]\n          } catch {\n            // ignore if parse fails\n            return\n          }\n\n          let injectedImportMeta = false\n          let s: MagicString | undefined\n          for (const { s: start, e: end, d: dynamicIndex } of imports) {\n            // is import.meta\n            if (dynamicIndex === -2) {\n              const prop = code.slice(end, end + 4)\n              if (prop === '.url') {\n                s ||= new MagicString(code)\n                s.overwrite(start, end + 4, 'self.location.href')\n              } else {\n                s ||= new MagicString(code)\n                if (!injectedImportMeta) {\n                  s.prepend(\n                    'const _vite_importMeta = { url: self.location.href };\\n',\n                  )\n                  injectedImportMeta = true\n                }\n                s.overwrite(start, end, '_vite_importMeta')\n              }\n            }\n          }\n\n          if (!s) return\n\n          return {\n            code: s.toString(),\n            map: s.generateMap({ hires: 'boundary', source: id }),\n          }\n        }\n      },\n    },\n  }\n}\n\nexport function webWorkerPlugin(config: ResolvedConfig): Plugin {\n  const isBuild = config.command === 'build'\n  const isWorker = config.isWorker\n\n  workerOutputCaches.set(config, new WorkerOutputCache())\n  const emittedAssets = new Set<string>()\n\n  return {\n    name: 'vite:worker',\n\n    buildStart() {\n      if (isWorker) return\n      emittedAssets.clear()\n    },\n\n    load: {\n      filter: { id: workerOrSharedWorkerRE },\n      async handler(id) {\n        const workerMatch = workerOrSharedWorkerRE.exec(id)\n        if (!workerMatch) return\n\n        const { format } = config.worker\n        const workerConstructor =\n          workerMatch[1] === 'sharedworker' ? 'SharedWorker' : 'Worker'\n        const workerType = config.isBundled\n          ? format === 'es'\n            ? 'module'\n            : 'classic'\n          : 'module'\n        const workerTypeOption = `{\n          ${workerType === 'module' ? `type: \"module\",` : ''}\n          name: options?.name\n        }`\n\n        let urlCode: string\n        if (config.isBundled) {\n          if (isWorker && config.bundleChain.at(-1) === cleanUrl(id)) {\n            urlCode = 'self.location.href'\n          } else if (inlineRE.test(id)) {\n            const result = await bundleWorkerEntry(config, id)\n            for (const file of result.watchedFiles) {\n              this.addWatchFile(file)\n            }\n\n            const jsContent = `const jsContent = ${JSON.stringify(result.entryCode)};`\n\n            const code =\n              // Using blob URL for SharedWorker results in multiple instances of a same worker\n              workerConstructor === 'Worker'\n                ? `${jsContent}\n            const blob = typeof self !== \"undefined\" && self.Blob && new Blob([${\n              // NOTE: Revoke the objURL after creating the worker, otherwise it breaks WebKit-based browsers\n              workerType === 'classic'\n                ? `'(self.URL || self.webkitURL).revokeObjectURL(self.location.href);',`\n                : // `URL` is always available, in `Worker[type=\"module\"]`\n                  `'URL.revokeObjectURL(import.meta.url);',`\n            }jsContent], { type: \"text/javascript;charset=utf-8\" });\n            export default function WorkerWrapper(options) {\n              let objURL;\n              try {\n                objURL = blob && (self.URL || self.webkitURL).createObjectURL(blob);\n                if (!objURL) throw ''\n                const worker = new ${workerConstructor}(objURL, ${workerTypeOption});\n                worker.addEventListener(\"error\", () => {\n                  (self.URL || self.webkitURL).revokeObjectURL(objURL);\n                });\n                return worker;\n              } catch(e) {\n                return new ${workerConstructor}(\n                  'data:text/javascript;charset=utf-8,' + encodeURIComponent(jsContent),\n                  ${workerTypeOption}\n                );\n              }\n            }`\n                : `${jsContent}\n            export default function WorkerWrapper(options) {\n              return new ${workerConstructor}(\n                'data:text/javascript;charset=utf-8,' + encodeURIComponent(jsContent),\n                ${workerTypeOption}\n              );\n            }\n            `\n\n            return {\n              code,\n              // Empty sourcemap to suppress Rollup warning\n              map: { mappings: '' },\n            }\n          } else {\n            const result = await workerFileToUrl(config, id)\n            let url: string\n            if (\n              this.environment.config.command === 'serve' &&\n              this.environment.config.experimental.bundledDev\n            ) {\n              url = toOutputFilePathInJSForBundledDev(\n                this.environment,\n                result.entryFilename,\n              )\n            } else {\n              url = result.entryUrlPlaceholder\n            }\n            urlCode = JSON.stringify(url)\n            for (const file of result.watchedFiles) {\n              this.addWatchFile(file)\n            }\n          }\n        } else {\n          let url = await fileToUrl(this, cleanUrl(id))\n          url = injectQuery(url, `${WORKER_FILE_ID}&type=${workerType}`)\n          urlCode = JSON.stringify(url)\n        }\n\n        if (urlRE.test(id)) {\n          return {\n            code: `export default ${urlCode}`,\n            map: { mappings: '' }, // Empty sourcemap to suppress Rollup warning\n          }\n        }\n\n        return {\n          code: `export default function WorkerWrapper(options) {\n            return new ${workerConstructor}(\n              ${urlCode},\n              ${workerTypeOption}\n            );\n          }`,\n          map: { mappings: '' }, // Empty sourcemap to suppress Rollup warning\n        }\n      },\n    },\n\n    transform: {\n      filter: { id: workerFileRE },\n      async handler(raw, id) {\n        const workerFileMatch = workerFileRE.exec(id)\n        if (workerFileMatch) {\n          // if import worker by worker constructor will have query.type\n          // other type will be import worker by esm\n          const workerType = workerFileMatch[1] as WorkerType\n          let injectEnv = ''\n\n          if (workerType === 'classic') {\n            // base needs to be joined as the base is not injected to `importScripts` automatically\n            const scriptPath = JSON.stringify(\n              path.posix.join(config.base, ENV_PUBLIC_PATH),\n            )\n            injectEnv = `importScripts(${scriptPath})\\n`\n          } else if (workerType === 'module') {\n            const scriptPath = JSON.stringify(ENV_PUBLIC_PATH)\n            injectEnv = `import ${scriptPath}\\n`\n          } else if (workerType === 'ignore') {\n            if (config.isBundled) {\n              injectEnv = ''\n            } else {\n              // dynamic worker type we can't know how import the env\n              // so we copy /@vite/env code of server transform result into file header\n              const environment = this.environment\n              const moduleGraph =\n                environment.mode === 'dev' ? environment.moduleGraph : undefined\n              const module = moduleGraph?.getModuleById(ENV_ENTRY)\n              injectEnv = module?.transformResult?.code || ''\n            }\n          }\n          if (injectEnv) {\n            const s = new MagicString(raw)\n            s.prepend(injectEnv + ';\\n')\n            return {\n              code: s.toString(),\n              map: s.generateMap({ hires: 'boundary' }),\n            }\n          }\n        }\n      },\n    },\n\n    ...(isBuild\n      ? {\n          renderChunk(code, chunk, outputOptions) {\n            let s: MagicString\n            const result = () => {\n              return (\n                s && {\n                  code: s.toString(),\n                  map: this.environment.config.build.sourcemap\n                    ? s.generateMap({ hires: 'boundary' })\n                    : null,\n                }\n              )\n            }\n            workerAssetUrlRE.lastIndex = 0\n            if (workerAssetUrlRE.test(code)) {\n              const toRelativeRuntime =\n                createToImportMetaURLBasedRelativeRuntime(\n                  outputOptions.format,\n                  this.environment.config.isWorker,\n                )\n\n              let match: RegExpExecArray | null\n              s = new MagicString(code)\n              workerAssetUrlRE.lastIndex = 0\n\n              // Replace \"__VITE_WORKER_ASSET__5aa0ddc0__\" using relative paths\n              const workerOutputCache = workerOutputCaches.get(\n                config.mainConfig || config,\n              )!\n\n              while ((match = workerAssetUrlRE.exec(code))) {\n                const [full, hash] = match\n                const filename =\n                  workerOutputCache.getEntryFilenameFromHash(hash)\n                if (!filename) {\n                  this.warn(`Could not find worker asset for hash: ${hash}`)\n                  continue\n                }\n                const replacement = toOutputFilePathInJS(\n                  this.environment,\n                  filename,\n                  'asset',\n                  chunk.fileName,\n                  'js',\n                  toRelativeRuntime,\n                )\n                const replacementString =\n                  typeof replacement === 'string'\n                    ? JSON.stringify(encodeURIPath(replacement)).slice(1, -1)\n                    : `\"+${replacement.runtime}+\"`\n                s.update(\n                  match.index,\n                  match.index + full.length,\n                  replacementString,\n                )\n              }\n            }\n            return result()\n          },\n        }\n      : {}),\n\n    generateBundle(opts, bundle) {\n      // to avoid emitting duplicate assets for modern build and legacy build\n      if (\n        this.environment.config.isOutputOptionsForLegacyChunks?.(opts) ||\n        isWorker\n      ) {\n        return\n      }\n      for (const asset of workerOutputCaches.get(config)!.getAssets()) {\n        if (emittedAssets.has(asset.fileName)) continue\n        emittedAssets.add(asset.fileName)\n\n        const duplicateAsset = bundle[asset.fileName]\n        if (duplicateAsset) {\n          const content =\n            duplicateAsset.type === 'asset'\n              ? duplicateAsset.source\n              : duplicateAsset.code\n          // don't emit if the file name and the content is same\n          if (isSameContent(content, asset.source)) {\n            continue\n          }\n        }\n\n        this.emitFile({\n          type: 'asset',\n          fileName: asset.fileName,\n          source: asset.source,\n          // NOTE: fileName is already generated when bundling the worker\n          //       so no need to pass originalFileNames/names\n        })\n      }\n    },\n\n    watchChange(file) {\n      if (isWorker) return\n      workerOutputCaches\n        .get(config)!\n        .invalidateAffectedBundles(normalizePath(file))\n    },\n  }\n}\n\nfunction isSameContent(a: string | Uint8Array, b: string | Uint8Array) {\n  if (typeof a === 'string') {\n    if (typeof b === 'string') {\n      return a === b\n    }\n    return Buffer.from(a).equals(b)\n  }\n  return Buffer.from(b).equals(a)\n}\n"
  },
  {
    "path": "packages/vite/src/node/plugins/workerImportMetaUrl.ts",
    "content": "import path from 'node:path'\nimport MagicString from 'magic-string'\nimport type { RollupError } from 'rolldown'\nimport { parseAstAsync } from 'rolldown/parseAst'\nimport { stripLiteral } from 'strip-literal'\nimport type { ESTree } from 'rolldown/utils'\nimport type { ResolvedConfig } from '../config'\nimport type { Plugin } from '../plugin'\nimport { evalValue, injectQuery, transformStableResult } from '../utils'\nimport { createBackCompatIdResolver } from '../idResolver'\nimport type { ResolveIdFn } from '../idResolver'\nimport { cleanUrl, slash } from '../../shared/utils'\nimport type { WorkerType } from './worker'\nimport { WORKER_FILE_ID, workerFileToUrl } from './worker'\nimport { fileToUrl, toOutputFilePathInJSForBundledDev } from './asset'\nimport type { InternalResolveOptions } from './resolve'\nimport { tryFsResolve } from './resolve'\nimport { hasViteIgnoreRE } from './importAnalysis'\n\ninterface WorkerOptions {\n  type?: WorkerType\n}\n\nfunction err(e: string, pos: number) {\n  const error = new Error(e) as RollupError\n  error.pos = pos\n  return error\n}\n\nfunction findClosingParen(input: string, fromIndex: number) {\n  let count = 1\n\n  for (let i = fromIndex; i < input.length; i++) {\n    if (input[i] === '(') count++\n    if (input[i] === ')') count--\n    if (count === 0) return i\n  }\n\n  return -1\n}\n\nfunction extractWorkerTypeFromAst(\n  expression: ESTree.Expression,\n  optsStartIndex: number,\n): 'classic' | 'module' | undefined {\n  if (expression.type !== 'ObjectExpression') {\n    return\n  }\n\n  let lastSpreadElementIndex = -1\n  let typeProperty = null\n  let typePropertyIndex = -1\n\n  for (let i = 0; i < expression.properties.length; i++) {\n    const property = expression.properties[i]\n\n    if (property.type === 'SpreadElement') {\n      lastSpreadElementIndex = i\n      continue\n    }\n\n    if (\n      property.type === 'Property' &&\n      ((property.key.type === 'Identifier' && property.key.name === 'type') ||\n        (property.key.type === 'Literal' && property.key.value === 'type'))\n    ) {\n      typeProperty = property\n      typePropertyIndex = i\n    }\n  }\n\n  if (typePropertyIndex === -1 && lastSpreadElementIndex === -1) {\n    // No type property or spread element in use. Assume safe usage and default to classic\n    return 'classic'\n  }\n\n  if (typePropertyIndex < lastSpreadElementIndex) {\n    throw err(\n      'Expected object spread to be used before the definition of the type property. ' +\n        'Vite needs a static value for the type property to correctly infer it.',\n      optsStartIndex,\n    )\n  }\n\n  if (typeProperty?.value.type !== 'Literal') {\n    throw err(\n      'Expected worker options type property to be a literal value.',\n      optsStartIndex,\n    )\n  }\n\n  // Silently default to classic type like the getWorkerType method\n  return typeProperty?.value.value === 'module' ? 'module' : 'classic'\n}\n\nasync function parseWorkerOptions(\n  rawOpts: string,\n  optsStartIndex: number,\n): Promise<WorkerOptions> {\n  let opts: WorkerOptions = {}\n  try {\n    opts = evalValue<WorkerOptions>(rawOpts)\n  } catch {\n    const optsNode = (\n      (await parseAstAsync(`(${rawOpts})`))\n        .body[0] as ESTree.ExpressionStatement\n    ).expression\n\n    const type = extractWorkerTypeFromAst(optsNode, optsStartIndex)\n    if (type) {\n      return { type }\n    }\n\n    throw err(\n      'Vite is unable to parse the worker options as the value is not static. ' +\n        'To ignore this error, please use /* @vite-ignore */ in the worker options.',\n      optsStartIndex,\n    )\n  }\n\n  if (opts == null) {\n    return {}\n  }\n\n  if (typeof opts !== 'object') {\n    throw err(\n      `Expected worker options to be an object, got ${typeof opts}`,\n      optsStartIndex,\n    )\n  }\n\n  return opts\n}\n\nasync function getWorkerType(\n  raw: string,\n  clean: string,\n  i: number,\n): Promise<WorkerType> {\n  const commaIndex = clean.indexOf(',', i)\n  if (commaIndex === -1) {\n    return 'classic'\n  }\n  const endIndex = findClosingParen(clean, i)\n\n  // case: ') ... ,' mean no worker options params\n  if (commaIndex > endIndex) {\n    return 'classic'\n  }\n\n  // need to find in comment code\n  let workerOptString = raw.substring(commaIndex + 1, endIndex)\n  const hasViteIgnore = hasViteIgnoreRE.test(workerOptString)\n  if (hasViteIgnore) {\n    return 'ignore'\n  }\n\n  // need to find in no comment code\n  const cleanWorkerOptString = clean.substring(commaIndex + 1, endIndex)\n  const trimmedCleanWorkerOptString = cleanWorkerOptString.trim()\n  if (!trimmedCleanWorkerOptString.length) {\n    return 'classic'\n  }\n\n  // strip trailing comma for evalValue\n  if (trimmedCleanWorkerOptString.endsWith(',')) {\n    workerOptString = workerOptString.slice(\n      0,\n      cleanWorkerOptString.lastIndexOf(','),\n    )\n  }\n\n  const workerOpts = await parseWorkerOptions(workerOptString, commaIndex + 1)\n  if (\n    workerOpts.type &&\n    (workerOpts.type === 'module' || workerOpts.type === 'classic')\n  ) {\n    return workerOpts.type\n  }\n\n  return 'classic'\n}\n\nexport const workerImportMetaUrlRE: RegExp =\n  /\\bnew\\s+(?:Worker|SharedWorker)\\s*\\(\\s*(new\\s+URL\\s*\\(\\s*('[^']+'|\"[^\"]+\"|`[^`]+`)\\s*,\\s*import\\.meta\\.url\\s*(?:,\\s*)?\\))/dg\n\nexport function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {\n  const isBundled = config.isBundled\n  let workerResolver: ResolveIdFn\n\n  const fsResolveOptions: InternalResolveOptions = {\n    ...config.resolve,\n    root: config.root,\n    isProduction: config.isProduction,\n    isBuild: config.command === 'build',\n    packageCache: config.packageCache,\n    asSrc: true,\n  }\n\n  return {\n    name: 'vite:worker-import-meta-url',\n\n    applyToEnvironment(environment) {\n      return environment.config.consumer === 'client'\n    },\n\n    transform: {\n      filter: { code: workerImportMetaUrlRE },\n      async handler(code, id) {\n        let s: MagicString | undefined\n        const cleanString = stripLiteral(code)\n        const re = new RegExp(workerImportMetaUrlRE)\n\n        let match: RegExpExecArray | null\n        while ((match = re.exec(cleanString))) {\n          const [[, endIndex], [expStart, expEnd], [urlStart, urlEnd]] =\n            match.indices!\n\n          const rawUrl = code.slice(urlStart, urlEnd)\n\n          // potential dynamic template string\n          if (rawUrl[0] === '`' && rawUrl.includes('${')) {\n            this.error(\n              `\\`new URL(url, import.meta.url)\\` is not supported in dynamic template string.`,\n              expStart,\n            )\n          }\n\n          s ||= new MagicString(code)\n          const workerType = await getWorkerType(code, cleanString, endIndex)\n          const url = rawUrl.slice(1, -1)\n          let file: string | undefined\n          if (url[0] === '.') {\n            file = path.resolve(path.dirname(id), url)\n            file = slash(tryFsResolve(file, fsResolveOptions) ?? file)\n          } else {\n            workerResolver ??= createBackCompatIdResolver(config, {\n              extensions: [],\n              tryIndex: false,\n              preferRelative: true,\n            })\n            file = await workerResolver(this.environment, url, id)\n            file ??=\n              url[0] === '/'\n                ? slash(path.join(config.publicDir, url))\n                : slash(path.resolve(path.dirname(id), url))\n          }\n\n          if (\n            isBundled &&\n            config.isWorker &&\n            config.bundleChain.at(-1) === cleanUrl(file)\n          ) {\n            s.update(expStart, expEnd, 'self.location.href')\n          } else {\n            let builtUrl: string\n            if (isBundled) {\n              const result = await workerFileToUrl(config, file)\n              if (\n                this.environment.config.command === 'serve' &&\n                this.environment.config.experimental.bundledDev\n              ) {\n                builtUrl = toOutputFilePathInJSForBundledDev(\n                  this.environment,\n                  result.entryFilename,\n                )\n              } else {\n                builtUrl = result.entryUrlPlaceholder\n              }\n              for (const file of result.watchedFiles) {\n                this.addWatchFile(file)\n              }\n            } else {\n              builtUrl = await fileToUrl(this, cleanUrl(file))\n              builtUrl = injectQuery(\n                builtUrl,\n                `${WORKER_FILE_ID}&type=${workerType}`,\n              )\n            }\n            s.update(\n              expStart,\n              expEnd,\n              // NOTE: add `'' +` to opt-out rolldown's transform: https://github.com/rolldown/rolldown/issues/2745\n              `new URL(/* @vite-ignore */ ${JSON.stringify(builtUrl)}, '' + import.meta.url)`,\n            )\n          }\n        }\n\n        if (s) {\n          return transformStableResult(s, id, config)\n        }\n\n        return null\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/preview.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport sirv from 'sirv'\nimport compression from '@polka/compression'\nimport connect from 'connect'\nimport corsMiddleware from 'cors'\nimport type { Connect } from '#dep-types/connect'\nimport type {\n  HttpServer,\n  ResolvedServerOptions,\n  ResolvedServerUrls,\n} from './server'\nimport { createServerCloseFn } from './server'\nimport type { CommonServerOptions } from './http'\nimport {\n  httpServerStart,\n  resolveHttpServer,\n  resolveHttpsConfig,\n  setClientErrorHandler,\n} from './http'\nimport { openBrowser } from './server/openBrowser'\nimport { baseMiddleware } from './server/middlewares/base'\nimport { htmlFallbackMiddleware } from './server/middlewares/htmlFallback'\nimport { indexHtmlMiddleware } from './server/middlewares/indexHtml'\nimport { notFoundMiddleware } from './server/middlewares/notFound'\nimport { proxyMiddleware } from './server/middlewares/proxy'\nimport {\n  getServerUrlByHost,\n  normalizePath,\n  resolveHostname,\n  resolveServerUrls,\n  setupSIGTERMListener,\n  shouldServeFile,\n  teardownSIGTERMListener,\n} from './utils'\nimport { printServerUrls } from './logger'\nimport { bindCLIShortcuts } from './shortcuts'\nimport type { BindCLIShortcutsOptions, ShortcutsState } from './shortcuts'\nimport { resolveConfig } from './config'\nimport type { InlineConfig, ResolvedConfig } from './config'\nimport { DEFAULT_PREVIEW_PORT } from './constants'\nimport type { RequiredExceptFor } from './typeUtils'\nimport { hostValidationMiddleware } from './server/middlewares/hostCheck'\nimport {\n  BasicMinimalPluginContext,\n  basePluginContextMeta,\n} from './server/pluginContainer'\nimport type { MinimalPluginContextWithoutEnvironment } from './plugin'\n\nexport interface PreviewOptions extends CommonServerOptions {}\n\nexport interface ResolvedPreviewOptions extends RequiredExceptFor<\n  PreviewOptions,\n  'host' | 'https' | 'proxy'\n> {}\n\nexport function resolvePreviewOptions(\n  preview: PreviewOptions | undefined,\n  server: ResolvedServerOptions,\n): ResolvedPreviewOptions {\n  // The preview server inherits every CommonServerOption from the `server` config\n  // except for the port to enable having both the dev and preview servers running\n  // at the same time without extra configuration\n  return {\n    port: preview?.port ?? DEFAULT_PREVIEW_PORT,\n    strictPort: preview?.strictPort ?? server.strictPort,\n    host: preview?.host ?? server.host,\n    allowedHosts: preview?.allowedHosts ?? server.allowedHosts,\n    https: preview?.https ?? server.https,\n    open: preview?.open ?? server.open,\n    proxy: preview?.proxy ?? server.proxy,\n    cors: preview?.cors ?? server.cors,\n    headers: preview?.headers ?? server.headers,\n  }\n}\n\nexport interface PreviewServer {\n  /**\n   * The resolved vite config object\n   */\n  config: ResolvedConfig\n  /**\n   * Stop the server.\n   */\n  close(): Promise<void>\n  /**\n   * A connect app instance.\n   * - Can be used to attach custom middlewares to the preview server.\n   * - Can also be used as the handler function of a custom http server\n   *   or as a middleware in any connect-style Node.js frameworks\n   *\n   * https://github.com/senchalabs/connect#use-middleware\n   */\n  middlewares: Connect.Server\n  /**\n   * native Node http server instance\n   */\n  httpServer: HttpServer\n  /**\n   * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null`\n   * if the server is not listening on any port.\n   */\n  resolvedUrls: ResolvedServerUrls | null\n  /**\n   * Print server urls\n   */\n  printUrls(): void\n  /**\n   * Bind CLI shortcuts\n   */\n  bindCLIShortcuts(options?: BindCLIShortcutsOptions<PreviewServer>): void\n  /**\n   * @internal\n   */\n  _shortcutsState?: ShortcutsState<PreviewServer>\n}\n\nexport type PreviewServerHook = (\n  this: MinimalPluginContextWithoutEnvironment,\n  server: PreviewServer,\n) => (() => void) | void | Promise<(() => void) | void>\n\n/**\n * Starts the Vite server in preview mode, to simulate a production deployment\n */\nexport async function preview(\n  inlineConfig: InlineConfig = {},\n): Promise<PreviewServer> {\n  const config = await resolveConfig(\n    inlineConfig,\n    'serve',\n    'production',\n    'production',\n    true,\n  )\n\n  const clientOutDir = config.environments.client.build.outDir\n  const distDir = path.resolve(config.root, clientOutDir)\n  if (\n    !fs.existsSync(distDir) &&\n    // error if no plugins implement `configurePreviewServer`\n    config.plugins.every((plugin) => !plugin.configurePreviewServer) &&\n    // error if called in CLI only. programmatic usage could access `httpServer`\n    // and affect file serving\n    process.argv[1]?.endsWith(path.normalize('bin/vite.js')) &&\n    process.argv[2] === 'preview'\n  ) {\n    throw new Error(\n      `The directory \"${clientOutDir}\" does not exist. Did you build your project?`,\n    )\n  }\n\n  const httpsOptions = await resolveHttpsConfig(config.preview.https)\n  const app = connect() as Connect.Server\n  const httpServer = await resolveHttpServer(app, httpsOptions)\n  setClientErrorHandler(httpServer, config.logger)\n\n  const options = config.preview\n  const logger = config.logger\n\n  const closeHttpServer = createServerCloseFn(httpServer)\n\n  // Promise used by `server.close()` to ensure `closeServer()` is only called once\n  let closeServerPromise: Promise<void> | undefined\n  const closeServer = async () => {\n    teardownSIGTERMListener(closeServerAndExit)\n    await closeHttpServer()\n    server.resolvedUrls = null\n  }\n\n  const server: PreviewServer = {\n    config,\n    middlewares: app,\n    httpServer,\n    async close() {\n      if (!closeServerPromise) {\n        closeServerPromise = closeServer()\n      }\n      return closeServerPromise\n    },\n    resolvedUrls: null,\n    printUrls() {\n      if (server.resolvedUrls) {\n        printServerUrls(server.resolvedUrls, options.host, logger.info)\n      } else {\n        throw new Error('cannot print server URLs before server is listening.')\n      }\n    },\n    bindCLIShortcuts(options) {\n      bindCLIShortcuts(server as PreviewServer, options)\n    },\n  }\n\n  const closeServerAndExit = async (_: unknown, exitCode?: number) => {\n    try {\n      await server.close()\n    } finally {\n      process.exitCode ??= exitCode ? 128 + exitCode : undefined\n      process.exit()\n    }\n  }\n\n  setupSIGTERMListener(closeServerAndExit)\n\n  // cors\n  const { cors } = config.preview\n  if (cors !== false) {\n    app.use(corsMiddleware(typeof cors === 'boolean' ? {} : cors))\n  }\n\n  // host check (to prevent DNS rebinding attacks)\n  const { allowedHosts } = config.preview\n  // no need to check for HTTPS as HTTPS is not vulnerable to DNS rebinding attacks\n  if (allowedHosts !== true && !config.preview.https) {\n    app.use(hostValidationMiddleware(allowedHosts, true))\n  }\n\n  // apply server hooks from plugins\n  const configurePreviewServerContext = new BasicMinimalPluginContext(\n    { ...basePluginContextMeta, watchMode: false },\n    config.logger,\n  )\n  const postHooks: ((() => void) | void)[] = []\n  for (const hook of config.getSortedPluginHooks('configurePreviewServer')) {\n    postHooks.push(await hook.call(configurePreviewServerContext, server))\n  }\n\n  // proxy\n  const { proxy } = config.preview\n  if (proxy) {\n    app.use(proxyMiddleware(httpServer, proxy, config))\n  }\n\n  app.use(compression())\n\n  // base\n  if (config.base !== '/') {\n    app.use(baseMiddleware(config.rawBase, false))\n  }\n\n  // static assets\n  const headers = config.preview.headers\n  const viteAssetMiddleware = (...args: readonly [any, any?, any?]) =>\n    sirv(distDir, {\n      etag: true,\n      dev: true,\n      extensions: [],\n      ignores: false,\n      setHeaders(res) {\n        if (headers) {\n          for (const name in headers) {\n            res.setHeader(name, headers[name]!)\n          }\n        }\n      },\n      shouldServe(filePath) {\n        return shouldServeFile(filePath, distDir)\n      },\n    })(...args)\n\n  app.use(viteAssetMiddleware)\n\n  // html fallback\n  if (config.appType === 'spa' || config.appType === 'mpa') {\n    app.use(htmlFallbackMiddleware(distDir, config.appType === 'spa'))\n  }\n\n  // apply post server hooks from plugins\n  postHooks.forEach((fn) => fn && fn())\n\n  if (config.appType === 'spa' || config.appType === 'mpa') {\n    // transform index.html\n    const normalizedDistDir = normalizePath(distDir)\n    app.use(indexHtmlMiddleware(normalizedDistDir, server))\n\n    // handle 404s\n    app.use(notFoundMiddleware())\n  }\n\n  const hostname = await resolveHostname(options.host)\n\n  await httpServerStart(httpServer, {\n    port: options.port,\n    strictPort: options.strictPort,\n    host: hostname.host,\n    logger,\n  })\n\n  server.resolvedUrls = resolveServerUrls(\n    httpServer,\n    config.preview,\n    hostname,\n    httpsOptions,\n    config,\n  )\n\n  if (options.open) {\n    const url = getServerUrlByHost(server.resolvedUrls, options.host)\n    if (url) {\n      const path =\n        typeof options.open === 'string' ? new URL(options.open, url).href : url\n      openBrowser(path, true, logger)\n    }\n  }\n\n  return server as PreviewServer\n}\n"
  },
  {
    "path": "packages/vite/src/node/publicDir.ts",
    "content": "import path from 'node:path'\nimport { cleanUrl, withTrailingSlash } from '../shared/utils'\nimport type { ResolvedConfig } from './config'\nimport {\n  ERR_SYMLINK_IN_RECURSIVE_READDIR,\n  normalizePath,\n  recursiveReaddir,\n  tryStatSync,\n} from './utils'\n\nconst publicFilesMap = new WeakMap<ResolvedConfig, Set<string>>()\n\nexport async function initPublicFiles(\n  config: ResolvedConfig,\n): Promise<Set<string> | undefined> {\n  let fileNames: string[]\n  try {\n    fileNames = await recursiveReaddir(config.publicDir)\n  } catch (e) {\n    if (e.code === ERR_SYMLINK_IN_RECURSIVE_READDIR) {\n      return\n    }\n    throw e\n  }\n  const publicFiles = new Set(\n    fileNames.map((fileName) => fileName.slice(config.publicDir.length)),\n  )\n  publicFilesMap.set(config, publicFiles)\n  return publicFiles\n}\n\nfunction getPublicFiles(config: ResolvedConfig): Set<string> | undefined {\n  return publicFilesMap.get(config)\n}\n\nexport function checkPublicFile(\n  url: string,\n  config: ResolvedConfig,\n): string | undefined {\n  // note if the file is in /public, the resolver would have returned it\n  // as-is so it's not going to be a fully resolved path.\n  const { publicDir } = config\n  if (!publicDir || url[0] !== '/') {\n    return\n  }\n\n  const fileName = cleanUrl(url)\n\n  // short-circuit if we have an in-memory publicFiles cache\n  const publicFiles = getPublicFiles(config)\n  if (publicFiles) {\n    return publicFiles.has(fileName)\n      ? normalizePath(path.join(publicDir, fileName))\n      : undefined\n  }\n\n  const publicFile = normalizePath(path.join(publicDir, fileName))\n  if (!publicFile.startsWith(withTrailingSlash(publicDir))) {\n    // can happen if URL starts with '../'\n    return\n  }\n\n  return tryStatSync(publicFile)?.isFile() ? publicFile : undefined\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/lerna/lerna.json",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/lerna/nested/package.json",
    "content": "{\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/none/nested/package.json",
    "content": "{\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/pnpm/nested/package.json",
    "content": "{\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/pnpm/package.json",
    "content": "{\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/pnpm/pnpm-workspace.yaml",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/watcher/config-deps/foo.js",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/watcher/custom-public/foo.txt",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/watcher/nested-root/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport '../config-deps/foo.js'\n\nexport default defineConfig({\n  envDir: '../custom-env',\n  publicDir: '../custom-public',\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/watcher/package.json",
    "content": "{\n  \"private\": true,\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/yarn/nested/package.json",
    "content": "{\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/fixtures/yarn/package.json",
    "content": "{\n  \"private\": true,\n  \"workspaces\": [\n    \"nested\"\n  ]\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/moduleGraph.spec.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { EnvironmentModuleGraph } from '../moduleGraph'\nimport type { ModuleNode } from '../mixedModuleGraph'\nimport { ModuleGraph } from '../mixedModuleGraph'\n\ndescribe('moduleGraph', () => {\n  describe('invalidateModule', () => {\n    it('removes an ssr error', async () => {\n      const moduleGraph = new EnvironmentModuleGraph('ssr', async (url) => ({\n        id: url,\n      }))\n      const entryUrl = '/x.js'\n\n      const entryModule = await moduleGraph.ensureEntryFromUrl(entryUrl, false)\n      entryModule.ssrError = new Error(`unable to execute module`)\n\n      expect(entryModule.ssrError).to.be.a('error')\n      moduleGraph.invalidateModule(entryModule)\n      expect(entryModule.ssrError).toBe(null)\n    })\n\n    it('ensureEntryFromUrl should based on resolvedId', async () => {\n      const moduleGraph = new EnvironmentModuleGraph('client', async (url) => {\n        if (url === '/xx.js') {\n          return { id: '/x.js' }\n        } else {\n          return { id: url }\n        }\n      })\n      const meta = { vite: 'test' }\n\n      const mod1 = await moduleGraph.ensureEntryFromUrl('/x.js', false)\n      mod1.meta = meta\n      const mod2 = await moduleGraph.ensureEntryFromUrl('/xx.js', false)\n      expect(mod2.meta).to.equal(meta)\n    })\n\n    it('ensure backward compatibility', async () => {\n      const clientModuleGraph = new EnvironmentModuleGraph(\n        'client',\n        async (url) => ({ id: url }),\n      )\n      const ssrModuleGraph = new EnvironmentModuleGraph('ssr', async (url) => ({\n        id: url,\n      }))\n      const moduleGraph = new ModuleGraph({\n        client: () => clientModuleGraph,\n        ssr: () => ssrModuleGraph,\n      })\n\n      const addBrowserModule = (url: string) =>\n        clientModuleGraph.ensureEntryFromUrl(url)\n      const getBrowserModule = (url: string) =>\n        clientModuleGraph.getModuleById(url)\n\n      const addServerModule = (url: string) =>\n        ssrModuleGraph.ensureEntryFromUrl(url)\n      const getServerModule = (url: string) => ssrModuleGraph.getModuleById(url)\n\n      const clientModule1 = await addBrowserModule('/1.js')\n      const ssrModule1 = await addServerModule('/1.js')\n      const module1 = moduleGraph.getModuleById('/1.js')!\n      expect(module1._clientModule).toBe(clientModule1)\n      expect(module1._ssrModule).toBe(ssrModule1)\n\n      const module2b = await moduleGraph.ensureEntryFromUrl('/b/2.js')\n      const module2s = await moduleGraph.ensureEntryFromUrl('/s/2.js')\n      expect(module2b._clientModule).toBe(getBrowserModule('/b/2.js'))\n      expect(module2s._ssrModule).toBe(getServerModule('/s/2.js'))\n\n      const importersUrls = ['/1/a.js', '/1/b.js', '/1/c.js']\n      ;(await Promise.all(importersUrls.map(addBrowserModule))).forEach((mod) =>\n        clientModule1.importers.add(mod),\n      )\n      ;(await Promise.all(importersUrls.map(addServerModule))).forEach((mod) =>\n        ssrModule1.importers.add(mod),\n      )\n\n      expect(module1.importers.size).toBe(importersUrls.length)\n\n      const clientModule1importersValues = [...clientModule1.importers]\n      const ssrModule1importersValues = [...ssrModule1.importers]\n\n      const module1importers = module1.importers\n      const module1importersValues = [...module1importers.values()]\n      expect(module1importersValues.length).toBe(importersUrls.length)\n      expect(module1importersValues[1]._clientModule).toBe(\n        clientModule1importersValues[1],\n      )\n      expect(module1importersValues[1]._ssrModule).toBe(\n        ssrModule1importersValues[1],\n      )\n\n      const module1importersFromForEach: ModuleNode[] = []\n      module1.importers.forEach((imp) => {\n        moduleGraph.invalidateModule(imp)\n        module1importersFromForEach.push(imp)\n      })\n      expect(module1importersFromForEach.length).toBe(importersUrls.length)\n      expect(module1importersFromForEach[1]._clientModule).toBe(\n        clientModule1importersValues[1],\n      )\n      expect(module1importersFromForEach[1]._ssrModule).toBe(\n        ssrModule1importersValues[1],\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/pluginContainer.spec.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\nimport { describe, expect, it, vi } from 'vitest'\nimport type { UserConfig } from '../../config'\nimport { resolveConfig } from '../../config'\nimport type { Plugin } from '../../plugin'\nimport { DevEnvironment } from '../environment'\nimport { createLogger } from '../../logger'\n\ndescribe('plugin container', () => {\n  describe('getModuleInfo', () => {\n    it('can pass metadata between hooks', async () => {\n      const entryUrl = '/x.js'\n\n      const metaArray: any[] = []\n      const plugin: Plugin = {\n        name: 'p1',\n        resolveId(id) {\n          if (id === entryUrl) {\n            // The module hasn't been resolved yet, so its info is null.\n            const moduleInfo = this.getModuleInfo(entryUrl)\n            expect(moduleInfo).toEqual(null)\n\n            return { id, meta: { x: 1 } }\n          }\n        },\n        load(id) {\n          if (id === entryUrl) {\n            const { meta } = this.getModuleInfo(entryUrl) ?? {}\n            metaArray.push(meta)\n\n            return { code: 'export {}', meta: { x: 2 } }\n          }\n        },\n        transform(_code, id) {\n          if (id === entryUrl) {\n            const { meta } = this.getModuleInfo(entryUrl) ?? {}\n            metaArray.push(meta)\n\n            return { meta: { x: 3 } }\n          }\n        },\n        buildEnd() {\n          const { meta } = this.getModuleInfo(entryUrl) ?? {}\n          metaArray.push(meta)\n        },\n      }\n\n      const environment = await getDevEnvironment({\n        plugins: [plugin],\n      })\n\n      const entryModule = await environment.moduleGraph.ensureEntryFromUrl(\n        entryUrl,\n        false,\n      )\n      expect(entryModule.meta).toEqual({ x: 1 })\n\n      const loadResult: any = await environment.pluginContainer.load(entryUrl)\n      expect(loadResult?.meta).toEqual({ x: 2 })\n\n      await environment.pluginContainer.transform(loadResult.code, entryUrl)\n      await environment.pluginContainer.close()\n\n      expect(metaArray).toEqual([{ x: 1 }, { x: 2 }, { x: 3 }])\n    })\n\n    it('can pass metadata between plugins', async () => {\n      const entryUrl = '/x.js'\n\n      const plugin1: Plugin = {\n        name: 'p1',\n        resolveId(id) {\n          if (id === entryUrl) {\n            return { id, meta: { x: 1 } }\n          }\n        },\n      }\n\n      const plugin2: Plugin = {\n        name: 'p2',\n        load(id) {\n          if (id === entryUrl) {\n            const { meta } = this.getModuleInfo(entryUrl) ?? {}\n            expect(meta).toEqual({ x: 1 })\n            return null\n          }\n        },\n      }\n\n      const environment = await getDevEnvironment({\n        plugins: [plugin1, plugin2],\n      })\n\n      await environment.moduleGraph.ensureEntryFromUrl(entryUrl, false)\n      await environment.pluginContainer.load(entryUrl)\n\n      expect.assertions(1)\n    })\n\n    it('can pass custom resolve opts between plugins', async () => {\n      const entryUrl = '/x.js'\n\n      const plugin1: Plugin = {\n        name: 'p1',\n        resolveId(id) {\n          if (id === entryUrl) {\n            return this.resolve('foobar', 'notreal', {\n              custom: { p1: 'success' },\n              isEntry: true,\n            } as any)\n          }\n        },\n      }\n\n      const plugin2: Plugin = {\n        name: 'p2',\n        resolveId(id, importer, opts) {\n          if (id === 'foobar') {\n            expect(importer).toBe('notreal')\n            expect(opts).toEqual(\n              expect.objectContaining({\n                custom: { p1: 'success' },\n                isEntry: true,\n              }),\n            )\n            return entryUrl\n          }\n        },\n        load(id) {\n          if (id === entryUrl) {\n            return null\n          }\n        },\n      }\n\n      const environment = await getDevEnvironment({\n        plugins: [plugin1, plugin2],\n      })\n\n      await environment.moduleGraph.ensureEntryFromUrl(entryUrl, false)\n      await environment.pluginContainer.load(entryUrl)\n\n      expect.assertions(2)\n    })\n  })\n\n  describe('options', () => {\n    it('should not throw errors when this.debug is called', async () => {\n      const plugin: Plugin = {\n        name: 'p1',\n        options() {\n          this.debug('test')\n        },\n      }\n      await getDevEnvironment({\n        plugins: [plugin],\n      })\n    })\n\n    const logFunctions = ['info', 'warn'] as const\n    for (const logFunction of logFunctions) {\n      it(`should support this.${logFunction}`, async () => {\n        const logger = createLogger()\n        const mockedFn = vi\n          .spyOn(logger, logFunction)\n          .mockImplementation(() => {})\n        const plugin: Plugin = {\n          name: 'p1',\n          options() {\n            this[logFunction]('test')\n          },\n        }\n        await getDevEnvironment({\n          plugins: [plugin],\n          customLogger: logger,\n        })\n        expect(mockedFn).toHaveBeenCalledOnce()\n      })\n    }\n\n    it('should support this.error', async () => {\n      const plugin: Plugin = {\n        name: 'p1',\n        options() {\n          this.error('test')\n        },\n      }\n      await expect(() =>\n        getDevEnvironment({\n          plugins: [plugin],\n        }),\n      ).rejects.toThrowError('test')\n    })\n  })\n\n  describe('load', () => {\n    it('can resolve a secondary module', async () => {\n      const entryUrl = '/x.js'\n\n      const plugin: Plugin = {\n        name: 'p1',\n        resolveId(id) {\n          return id\n        },\n        load(id) {\n          if (id === entryUrl) return { code: '1', meta: { x: 1 } }\n          else return { code: '2', meta: { x: 2 } }\n        },\n        async transform(code, id) {\n          if (id === entryUrl)\n            return {\n              code: `${\n                (await this.load({ id: '/secondary.js' })).meta.x || undefined\n              }`,\n            }\n          return { code }\n        },\n      }\n\n      const environment = await getDevEnvironment({\n        plugins: [plugin],\n      })\n      await environment.moduleGraph.ensureEntryFromUrl(entryUrl, false)\n      const loadResult: any = await environment.pluginContainer.load(entryUrl)\n      const result: any = await environment.pluginContainer.transform(\n        loadResult.code,\n        entryUrl,\n      )\n      expect(result.code).equals('2')\n    })\n\n    it('will load and transform the module', async () => {\n      const entryUrl = '/x.js'\n      const otherUrl = '/y.js'\n\n      const plugin: Plugin = {\n        name: 'p1',\n        resolveId(id) {\n          return id\n        },\n        load(id) {\n          if (id === entryUrl) return { code: '1' }\n          else if (id === otherUrl) return { code: '2', meta: { code: '2' } }\n        },\n        async transform(_code, id) {\n          if (id === entryUrl) {\n            // NOTE: ModuleInfo.code not implemented, used `.meta.code` for now\n            return (await this.load({ id: otherUrl }))?.meta.code\n          } else if (id === otherUrl) {\n            return { code: '3', meta: { code: '3' } }\n          }\n        },\n      }\n\n      const environment = await getDevEnvironment({\n        plugins: [plugin],\n      })\n      await environment.moduleGraph.ensureEntryFromUrl(entryUrl, false)\n      const loadResult: any = await environment.pluginContainer.load(entryUrl)\n      const result: any = await environment.pluginContainer.transform(\n        loadResult.code,\n        entryUrl,\n      )\n      expect(result.code).equals('3')\n    })\n\n    it('should not throw errors when this.debug is called', async () => {\n      const plugin: Plugin = {\n        name: 'p1',\n        load() {\n          this.debug({ message: 'test', pos: 12 })\n        },\n      }\n      const environment = await getDevEnvironment({\n        plugins: [plugin],\n      })\n      await environment.pluginContainer.load('foo')\n    })\n\n    const logFunctions = ['info', 'warn'] as const\n    for (const logFunction of logFunctions) {\n      it(`should support this.${logFunction}`, async () => {\n        const logger = createLogger()\n        const mockedFn = vi\n          .spyOn(logger, logFunction)\n          .mockImplementation(() => {})\n        const plugin: Plugin = {\n          name: 'p1',\n          load() {\n            this[logFunction]({ message: 'test', pos: 12 })\n          },\n        }\n        const environment = await getDevEnvironment({\n          plugins: [plugin],\n          customLogger: logger,\n        })\n        await environment.pluginContainer.load('foo')\n        expect(mockedFn).toHaveBeenCalledOnce()\n        expect(stripVTControlCharacters(mockedFn.mock.calls[0][0])).toBe(\n          `${logFunction === 'warn' ? 'warning' : logFunction}: test\\n` +\n            '  Plugin: p1',\n        )\n      })\n    }\n\n    it('should support this.error', async () => {\n      const plugin: Plugin = {\n        name: 'p1',\n        load() {\n          this.error({ message: 'test', pos: 12 })\n        },\n      }\n      const environment = await getDevEnvironment({\n        plugins: [plugin],\n      })\n      await expect(() => environment.pluginContainer.load('foo')).rejects\n        .toThrowErrorMatchingInlineSnapshot(`\n        {\n          \"message\": \"test\",\n          \"plugin\": \"p1\",\n          \"pos\": 12,\n        }\n      `)\n    })\n  })\n\n  describe('resolveId', () => {\n    describe('skipSelf', () => {\n      it('should skip the plugin itself when skipSelf is true', async () => {\n        let calledCount = 0\n        const plugin: Plugin = {\n          name: 'p1',\n          async resolveId(id, importer) {\n            calledCount++\n            if (calledCount <= 1) {\n              return await this.resolve(id, importer, { skipSelf: true })\n            }\n            return id\n          },\n        }\n\n        const environment = await getDevEnvironment({ plugins: [plugin] })\n        await environment.pluginContainer.resolveId('/x.js')\n        expect(calledCount).toBe(1)\n      })\n\n      it('should skip the plugin only when id and importer is same', async () => {\n        const p1: Plugin = {\n          name: 'p1',\n          async resolveId(id, importer) {\n            if (id === 'foo/modified') {\n              return 'success'\n            }\n            return await this.resolve(id, importer, { skipSelf: true })\n          },\n        }\n        const p2: Plugin = {\n          name: 'p2',\n          async resolveId(id, importer) {\n            const resolved = await this.resolve(id + '/modified', importer, {\n              skipSelf: true,\n            })\n            return resolved ?? 'failed'\n          },\n        }\n\n        const environment = await getDevEnvironment({ plugins: [p1, p2] })\n        const result = await environment.pluginContainer.resolveId('foo')\n        expect(result).toStrictEqual({ id: 'success' })\n      })\n\n      it('should skip the plugin if it has been called before with the same id and importer (1)', async () => {\n        const p1: Plugin = {\n          name: 'p1',\n          async resolveId(id, importer) {\n            return (\n              (await this.resolve(id.replace(/\\/modified$/, ''), importer, {\n                skipSelf: true,\n              })) ?? 'success'\n            )\n          },\n        }\n        const p2: Plugin = {\n          name: 'p2',\n          async resolveId(id, importer) {\n            return await this.resolve(id + '/modified', importer, {\n              skipSelf: true,\n            })\n          },\n        }\n        const environment = await getDevEnvironment({ plugins: [p1, p2] })\n        const result = await environment.pluginContainer.resolveId('foo')\n        expect(result).toStrictEqual({ id: 'success' })\n      })\n\n      it('should skip the plugin if it has been called before with the same id and importer (2)', async () => {\n        const p1: Plugin = {\n          name: 'p1',\n          async resolveId(id, importer) {\n            return (\n              (await this.resolve(id.replace(/\\/modified$/, ''), importer, {\n                skipSelf: true,\n              })) ?? 'failure1'\n            )\n          },\n        }\n        const p2: Plugin = {\n          name: 'p2',\n          async resolveId(id, importer) {\n            return await this.resolve(id + '/modified', importer, {\n              skipSelf: true,\n            })\n          },\n        }\n        const p3: Plugin = {\n          name: 'p3',\n          resolveId(id) {\n            if (id.endsWith('/modified')) {\n              return 'success'\n            }\n            return 'failure2'\n          },\n        }\n        const environment = await getDevEnvironment({ plugins: [p1, p2, p3] })\n        const result = await environment.pluginContainer.resolveId('foo')\n        expect(result).toStrictEqual({ id: 'success' })\n      })\n    })\n  })\n})\n\nasync function getDevEnvironment(\n  inlineConfig?: UserConfig,\n): Promise<DevEnvironment> {\n  const config = await resolveConfig(\n    { configFile: false, ...inlineConfig },\n    'serve',\n  )\n\n  // @ts-expect-error This plugin requires a ViteDevServer instance.\n  config.plugins = config.plugins.filter((p) => !p.name.includes('pre-alias'))\n\n  const environment = new DevEnvironment('client', config, { hot: true })\n  await environment.init()\n\n  return environment\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/search-root.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { searchForWorkspaceRoot } from '../searchRoot'\n\nconst dirname = import.meta.dirname\n\ndescribe('searchForWorkspaceRoot', () => {\n  test('lerna', () => {\n    const resolved = searchForWorkspaceRoot(\n      resolve(dirname, 'fixtures/lerna/nested'),\n    )\n    expect(resolved).toBe(resolve(dirname, 'fixtures/lerna'))\n  })\n\n  test('pnpm', () => {\n    const resolved = searchForWorkspaceRoot(\n      resolve(dirname, 'fixtures/pnpm/nested'),\n    )\n    expect(resolved).toBe(resolve(dirname, 'fixtures/pnpm'))\n  })\n\n  test('yarn', () => {\n    const resolved = searchForWorkspaceRoot(\n      resolve(dirname, 'fixtures/yarn/nested'),\n    )\n    expect(resolved).toBe(resolve(dirname, 'fixtures/yarn'))\n  })\n\n  test('yarn at root', () => {\n    const resolved = searchForWorkspaceRoot(resolve(dirname, 'fixtures/yarn'))\n    expect(resolved).toBe(resolve(dirname, 'fixtures/yarn'))\n  })\n\n  test('none', () => {\n    const resolved = searchForWorkspaceRoot(\n      resolve(dirname, 'fixtures/none/nested'),\n    )\n    // resolved to vite repo's root\n    expect(resolved).toBe(resolve(dirname, '../../../../../..'))\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/transformRequest.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { getModuleTypeFromId } from '../transformRequest'\n\ndescribe('getModuleTypeFromId', () => {\n  const testCases = [\n    { id: 'foo.js', expected: 'js' },\n    { id: 'foo.ts', expected: 'ts' },\n    { id: 'foo.a.js', expected: 'js' },\n    { id: '', expected: undefined },\n  ]\n\n  for (const { id, expected } of testCases) {\n    test(`should return ${expected} for id: ${id}`, () => {\n      const result = getModuleTypeFromId(id)\n      expect(result).toBe(expected)\n    })\n  }\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/__tests__/watcher.spec.ts",
    "content": "import { resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { afterEach, describe, expect, it, vi } from 'vitest'\nimport { type ViteDevServer, createServer } from '../index'\n\nconst stubGetWatchedCode = /\\(\\)\\s*\\{\\s*return this;\\s*\\}/\n\ndescribe('watcher configuration', () => {\n  let server: ViteDevServer | undefined\n\n  afterEach(async () => {\n    if (server) {\n      await server.close()\n      server = undefined\n    }\n  })\n\n  it('when watcher is disabled, return noop watcher', async () => {\n    server = await createServer({\n      server: {\n        watch: null,\n      },\n    })\n    expect(server.watcher.add.toString()).toMatch(stubGetWatchedCode)\n  })\n\n  it('when watcher is not disabled, return chokidar watcher', async () => {\n    server = await createServer({\n      server: {\n        watch: {},\n      },\n    })\n    expect(server.watcher.add.toString()).not.toMatch(stubGetWatchedCode)\n  })\n\n  it('should watch the root directory, config file dependencies, dotenv files, and the public directory', async () => {\n    const root = fileURLToPath(\n      new URL('./fixtures/watcher/nested-root', import.meta.url),\n    )\n    server = await createServer({ root })\n    await new Promise((resolve) => server!.watcher.once('ready', resolve))\n    // Perform retries here as chokidar may still not be completely watching all directories\n    // after the `ready` event\n    await vi.waitFor(() => {\n      const watchedDirs = Object.keys(server!.watcher.getWatched())\n      expect(watchedDirs).toEqual(\n        expect.arrayContaining([\n          root,\n          resolve(root, '../config-deps'),\n          resolve(root, '../custom-env'),\n          resolve(root, '../custom-public'),\n        ]),\n      )\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/environment.ts",
    "content": "import colors from 'picocolors'\nimport type { FetchFunctionOptions, FetchResult } from 'vite/module-runner'\nimport type { FSWatcher } from '#dep-types/chokidar'\nimport { BaseEnvironment } from '../baseEnvironment'\nimport type {\n  EnvironmentOptions,\n  ResolvedConfig,\n  ResolvedEnvironmentOptions,\n} from '../config'\nimport { mergeConfig, monotonicDateNow } from '../utils'\nimport { fetchModule } from '../ssr/fetchModule'\nimport type { DepsOptimizer } from '../optimizer'\nimport { isDepOptimizationDisabled } from '../optimizer'\nimport {\n  createDepsOptimizer,\n  createExplicitDepsOptimizer,\n} from '../optimizer/optimizer'\nimport { ERR_OUTDATED_OPTIMIZED_DEP } from '../../shared/constants'\nimport { promiseWithResolvers } from '../../shared/utils'\nimport type { ViteDevServer } from '../server'\nimport { EnvironmentModuleGraph } from './moduleGraph'\nimport type { EnvironmentModuleNode } from './moduleGraph'\nimport type {\n  HotChannel,\n  NormalizedHotChannel,\n  NormalizedHotChannelClient,\n} from './hmr'\nimport { getShortName, normalizeHotChannel, updateModules } from './hmr'\nimport type {\n  TransformOptionsInternal,\n  TransformResult,\n} from './transformRequest'\nimport { transformRequest } from './transformRequest'\nimport type { EnvironmentPluginContainer } from './pluginContainer'\nimport {\n  ERR_CLOSED_SERVER,\n  createEnvironmentPluginContainer,\n} from './pluginContainer'\nimport { type WebSocketServer, isWebSocketServer } from './ws'\nimport { warmupFiles } from './warmup'\nimport { buildErrorMessage } from './middlewares/error'\n\nexport interface DevEnvironmentContext {\n  hot: boolean\n  transport?: HotChannel | WebSocketServer\n  options?: EnvironmentOptions\n  remoteRunner?: {\n    inlineSourceMap?: boolean\n  }\n  depsOptimizer?: DepsOptimizer\n  /** @internal used for full bundle mode */\n  disableDepsOptimizer?: boolean\n}\n\nexport class DevEnvironment extends BaseEnvironment {\n  mode = 'dev' as const\n  moduleGraph: EnvironmentModuleGraph\n\n  depsOptimizer?: DepsOptimizer\n  /**\n   * @internal\n   */\n  _remoteRunnerOptions: DevEnvironmentContext['remoteRunner']\n\n  get pluginContainer(): EnvironmentPluginContainer<DevEnvironment> {\n    if (!this._pluginContainer)\n      throw new Error(\n        `${this.name} environment.pluginContainer called before initialized`,\n      )\n    return this._pluginContainer\n  }\n  /**\n   * @internal\n   */\n  _pluginContainer: EnvironmentPluginContainer<DevEnvironment> | undefined\n\n  /**\n   * @internal\n   */\n  _closing: boolean = false\n  /**\n   * @internal\n   */\n  _pendingRequests: Map<\n    string,\n    {\n      request: Promise<TransformResult | null>\n      timestamp: number\n      abort: () => void\n    }\n  >\n  /**\n   * @internal\n   */\n  _crawlEndFinder: CrawlEndFinder\n\n  /**\n   * Hot channel for this environment. If not provided or disabled,\n   * it will be a noop channel that does nothing.\n   *\n   * @example\n   * environment.hot.send({ type: 'full-reload' })\n   */\n  hot: NormalizedHotChannel\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    context: DevEnvironmentContext,\n  ) {\n    let options = config.environments[name]\n    if (!options) {\n      throw new Error(`Environment \"${name}\" is not defined in the config.`)\n    }\n    if (context.options) {\n      options = mergeConfig(\n        options,\n        context.options,\n      ) as ResolvedEnvironmentOptions\n    }\n    super(name, config, options)\n\n    this._pendingRequests = new Map()\n\n    this.moduleGraph = new EnvironmentModuleGraph(name, (url: string) =>\n      this.pluginContainer!.resolveId(url, undefined),\n    )\n\n    this._crawlEndFinder = setupOnCrawlEnd()\n\n    this._remoteRunnerOptions = context.remoteRunner ?? {}\n\n    this.hot = context.transport\n      ? isWebSocketServer in context.transport\n        ? context.transport\n        : normalizeHotChannel(context.transport, context.hot)\n      : normalizeHotChannel({}, context.hot)\n\n    this.hot.setInvokeHandler({\n      fetchModule: (id, importer, options) => {\n        return this.fetchModule(id, importer, options)\n      },\n      getBuiltins: async () => {\n        return this.config.resolve.builtins.map((builtin) =>\n          typeof builtin === 'string'\n            ? { type: 'string', value: builtin }\n            : { type: 'RegExp', source: builtin.source, flags: builtin.flags },\n        )\n      },\n    })\n\n    this.hot.on(\n      'vite:invalidate',\n      async ({ path, message, firstInvalidatedBy }, client) => {\n        this.invalidateModule(\n          {\n            path,\n            message,\n            firstInvalidatedBy,\n          },\n          client,\n        )\n      },\n    )\n\n    if (!context.disableDepsOptimizer) {\n      const { optimizeDeps } = this.config\n      if (context.depsOptimizer) {\n        this.depsOptimizer = context.depsOptimizer\n      } else if (isDepOptimizationDisabled(optimizeDeps)) {\n        this.depsOptimizer = undefined\n      } else {\n        this.depsOptimizer = (\n          optimizeDeps.noDiscovery\n            ? createExplicitDepsOptimizer\n            : createDepsOptimizer\n        )(this)\n      }\n    }\n  }\n\n  async init(options?: {\n    watcher?: FSWatcher\n    /**\n     * the previous instance used for the environment with the same name\n     *\n     * when using, the consumer should check if it's an instance generated from the same class or factory function\n     */\n    previousInstance?: DevEnvironment\n  }): Promise<void> {\n    if (this._initiated) {\n      return\n    }\n    this._initiated = true\n    this._pluginContainer = await createEnvironmentPluginContainer(\n      this,\n      this.config.plugins,\n      options?.watcher,\n    )\n  }\n\n  /**\n   * When the dev server is restarted, the methods are called in the following order:\n   * - new instance `init`\n   * - previous instance `close`\n   * - new instance `listen`\n   */\n  async listen(server: ViteDevServer): Promise<void> {\n    this.hot.listen()\n    await this.depsOptimizer?.init()\n    warmupFiles(server, this)\n  }\n\n  fetchModule(\n    id: string,\n    importer?: string,\n    options?: FetchFunctionOptions,\n  ): Promise<FetchResult> {\n    return fetchModule(this, id, importer, {\n      ...this._remoteRunnerOptions,\n      ...options,\n    })\n  }\n\n  async reloadModule(module: EnvironmentModuleNode): Promise<void> {\n    if (this.config.server.hmr !== false && module.file) {\n      updateModules(this, module.file, [module], monotonicDateNow())\n    }\n  }\n\n  transformRequest(\n    url: string,\n    /** @internal */\n    options?: TransformOptionsInternal,\n  ): Promise<TransformResult | null> {\n    return transformRequest(this, url, options)\n  }\n\n  async warmupRequest(url: string): Promise<void> {\n    try {\n      await this.transformRequest(url)\n    } catch (e) {\n      if (\n        e?.code === ERR_OUTDATED_OPTIMIZED_DEP ||\n        e?.code === ERR_CLOSED_SERVER\n      ) {\n        // these are expected errors\n        return\n      }\n      // Unexpected error, log the issue but avoid an unhandled exception\n      this.logger.error(\n        buildErrorMessage(e, [`Pre-transform error: ${e.message}`], false),\n        {\n          error: e,\n          timestamp: true,\n        },\n      )\n    }\n  }\n\n  protected invalidateModule(\n    m: {\n      path: string\n      message?: string\n      firstInvalidatedBy: string\n    },\n    _client: NormalizedHotChannelClient,\n  ): void {\n    const mod = this.moduleGraph.urlToModuleMap.get(m.path)\n    if (\n      mod &&\n      mod.isSelfAccepting &&\n      mod.lastHMRTimestamp > 0 &&\n      !mod.lastHMRInvalidationReceived\n    ) {\n      mod.lastHMRInvalidationReceived = true\n      this.logger.info(\n        colors.yellow(`hmr invalidate `) +\n          colors.dim(m.path) +\n          (m.message ? ` ${m.message}` : ''),\n        { timestamp: true },\n      )\n      const file = getShortName(mod.file!, this.config.root)\n      updateModules(\n        this,\n        file,\n        [...mod.importers].filter((imp) => imp !== mod), // ignore self-imports\n        mod.lastHMRTimestamp,\n        m.firstInvalidatedBy,\n      )\n    }\n  }\n\n  async close(): Promise<void> {\n    this._closing = true\n\n    this._crawlEndFinder.cancel()\n    await Promise.allSettled([\n      this.pluginContainer.close(),\n      this.depsOptimizer?.close(),\n      // WebSocketServer is independent of HotChannel and should not be closed on environment close\n      isWebSocketServer in this.hot ? Promise.resolve() : this.hot.close(),\n      (async () => {\n        while (this._pendingRequests.size > 0) {\n          await Promise.allSettled(\n            [...this._pendingRequests.values()].map(\n              (pending) => pending.request,\n            ),\n          )\n        }\n      })(),\n    ])\n  }\n\n  /**\n   * Calling `await environment.waitForRequestsIdle(id)` will wait until all static imports\n   * are processed after the first transformRequest call. If called from a load or transform\n   * plugin hook, the id needs to be passed as a parameter to avoid deadlocks.\n   * Calling this function after the first static imports section of the module graph has been\n   * processed will resolve immediately.\n   * @experimental\n   */\n  waitForRequestsIdle(ignoredId?: string): Promise<void> {\n    return this._crawlEndFinder.waitForRequestsIdle(ignoredId)\n  }\n\n  /**\n   * @internal\n   */\n  _registerRequestProcessing(id: string, done: () => Promise<unknown>): void {\n    this._crawlEndFinder.registerRequestProcessing(id, done)\n  }\n}\n\nconst callCrawlEndIfIdleAfterMs = 50\n\ninterface CrawlEndFinder {\n  registerRequestProcessing: (id: string, done: () => Promise<any>) => void\n  waitForRequestsIdle: (ignoredId?: string) => Promise<void>\n  cancel: () => void\n}\n\nfunction setupOnCrawlEnd(): CrawlEndFinder {\n  const registeredIds = new Set<string>()\n  const seenIds = new Set<string>()\n  const onCrawlEndPromiseWithResolvers = promiseWithResolvers<void>()\n\n  let timeoutHandle: NodeJS.Timeout | undefined\n\n  let cancelled = false\n  function cancel() {\n    cancelled = true\n  }\n\n  function registerRequestProcessing(\n    id: string,\n    done: () => Promise<any>,\n  ): void {\n    if (!seenIds.has(id)) {\n      seenIds.add(id)\n      registeredIds.add(id)\n      done()\n        .catch(() => {})\n        .finally(() => markIdAsDone(id))\n    }\n  }\n\n  function waitForRequestsIdle(ignoredId?: string): Promise<void> {\n    if (ignoredId) {\n      seenIds.add(ignoredId)\n      markIdAsDone(ignoredId)\n    } else {\n      checkIfCrawlEndAfterTimeout()\n    }\n    return onCrawlEndPromiseWithResolvers.promise\n  }\n\n  function markIdAsDone(id: string): void {\n    registeredIds.delete(id)\n    checkIfCrawlEndAfterTimeout()\n  }\n\n  function checkIfCrawlEndAfterTimeout() {\n    if (cancelled || registeredIds.size > 0) return\n\n    if (timeoutHandle) clearTimeout(timeoutHandle)\n    timeoutHandle = setTimeout(\n      callOnCrawlEndWhenIdle,\n      callCrawlEndIfIdleAfterMs,\n    )\n  }\n  async function callOnCrawlEndWhenIdle() {\n    if (cancelled || registeredIds.size > 0) return\n    onCrawlEndPromiseWithResolvers.resolve()\n  }\n\n  return {\n    registerRequestProcessing,\n    waitForRequestsIdle,\n    cancel,\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/environments/fetchableEnvironments.ts",
    "content": "import type { ResolvedConfig } from '../../config'\nimport type { DevEnvironmentContext } from '../environment'\nimport { DevEnvironment } from '../environment'\nimport type { Environment } from '../../environment'\n\nexport interface FetchableDevEnvironmentContext extends DevEnvironmentContext {\n  handleRequest(request: Request): Promise<Response> | Response\n}\n\nexport function createFetchableDevEnvironment(\n  name: string,\n  config: ResolvedConfig,\n  context: FetchableDevEnvironmentContext,\n): FetchableDevEnvironment {\n  if (typeof Request === 'undefined' || typeof Response === 'undefined') {\n    throw new TypeError(\n      'FetchableDevEnvironment requires a global `Request` and `Response` object.',\n    )\n  }\n\n  if (!context.handleRequest) {\n    throw new TypeError(\n      'FetchableDevEnvironment requires a `handleRequest` method during initialisation.',\n    )\n  }\n\n  return new FetchableDevEnvironment(name, config, context)\n}\n\nexport function isFetchableDevEnvironment(\n  environment: Environment,\n): environment is FetchableDevEnvironment {\n  return environment instanceof FetchableDevEnvironment\n}\n\nclass FetchableDevEnvironment extends DevEnvironment {\n  private _handleRequest: (request: Request) => Promise<Response> | Response\n\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    context: FetchableDevEnvironmentContext,\n  ) {\n    super(name, config, context)\n    this._handleRequest = context.handleRequest\n  }\n\n  public async dispatchFetch(request: Request): Promise<Response> {\n    if (!(request instanceof Request)) {\n      throw new TypeError(\n        'FetchableDevEnvironment `dispatchFetch` must receive a `Request` object.',\n      )\n    }\n    const response = await this._handleRequest(request)\n    if (!(response instanceof Response)) {\n      throw new TypeError(\n        'FetchableDevEnvironment `context.handleRequest` must return a `Response` object.',\n      )\n    }\n    return response\n  }\n}\n\nexport type { FetchableDevEnvironment }\n"
  },
  {
    "path": "packages/vite/src/node/server/environments/fullBundleEnvironment.ts",
    "content": "import { randomUUID } from 'node:crypto'\nimport { setTimeout } from 'node:timers/promises'\nimport {\n  type BindingClientHmrUpdate,\n  type DevEngine,\n  dev,\n} from 'rolldown/experimental'\nimport colors from 'picocolors'\nimport getEtag from 'etag'\nimport type { Update } from '#types/hmrPayload'\nimport { ChunkMetadataMap, resolveRolldownOptions } from '../../build'\nimport { getHmrImplementation } from '../../plugins/clientInjections'\nimport { DevEnvironment, type DevEnvironmentContext } from '../environment'\nimport type { ResolvedConfig } from '../../config'\nimport type { ViteDevServer } from '../../server'\nimport { createDebugger } from '../../utils'\nimport { type NormalizedHotChannelClient, getShortName } from '../hmr'\nimport { prepareError } from '../middlewares/error'\n\nconst debug = createDebugger('vite:full-bundle-mode')\n\ntype HmrOutput = BindingClientHmrUpdate['update']\n\ntype MemoryFile = {\n  source: string | Uint8Array\n  etag?: string\n}\n\nexport class MemoryFiles {\n  private files = new Map<string, MemoryFile | (() => MemoryFile)>()\n\n  get size(): number {\n    return this.files.size\n  }\n\n  get(file: string): MemoryFile | undefined {\n    const result = this.files.get(file)\n    if (result === undefined) {\n      return undefined\n    }\n    if (typeof result === 'function') {\n      const content = result()\n      this.files.set(file, content)\n      return content\n    }\n    return result\n  }\n\n  set(file: string, content: MemoryFile | (() => MemoryFile)): void {\n    this.files.set(file, content)\n  }\n\n  has(file: string): boolean {\n    return this.files.has(file)\n  }\n\n  clear(): void {\n    this.files.clear()\n  }\n}\n\nexport class FullBundleDevEnvironment extends DevEnvironment {\n  private devEngine!: DevEngine\n  private clients = new Clients()\n  private invalidateCalledModules = new Map<\n    NormalizedHotChannelClient,\n    Set<string>\n  >()\n  private debouncedFullReload = debounce(20, () => {\n    this.hot.send({ type: 'full-reload', path: '*' })\n    this.logger.info(colors.green(`page reload`), { timestamp: true })\n  })\n\n  memoryFiles: MemoryFiles = new MemoryFiles()\n\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    context: DevEnvironmentContext,\n  ) {\n    if (name !== 'client') {\n      throw new Error(\n        'currently full bundle mode is only available for client environment',\n      )\n    }\n\n    super(name, config, { ...context, disableDepsOptimizer: true })\n  }\n\n  override async listen(_server: ViteDevServer): Promise<void> {\n    this.hot.listen()\n\n    debug?.('INITIAL: setup bundle options')\n    const rollupOptions = await this.getRolldownOptions()\n    // NOTE: only single outputOptions is supported here\n    if (\n      Array.isArray(rollupOptions.output) &&\n      rollupOptions.output.length > 1\n    ) {\n      throw new Error('multiple output options are not supported in dev mode')\n    }\n    const outputOptions = (\n      Array.isArray(rollupOptions.output)\n        ? rollupOptions.output[0]\n        : rollupOptions.output\n    )!\n\n    this.hot.on('vite:module-loaded', (payload, client) => {\n      const clientId = this.clients.setupIfNeeded(client)\n      this.devEngine.registerModules(clientId, payload.modules)\n    })\n    this.hot.on('vite:client:disconnect', (_payload, client) => {\n      const clientId = this.clients.delete(client)\n      if (clientId) {\n        this.devEngine.removeClient(clientId)\n      }\n    })\n\n    this.devEngine = await dev(rollupOptions, outputOptions, {\n      onHmrUpdates: (result) => {\n        if (result instanceof Error) {\n          // TODO: send to the specific client\n          for (const client of this.clients.getAll()) {\n            client.send({\n              type: 'error',\n              err: prepareError(result),\n            })\n          }\n          return\n        }\n        const { updates, changedFiles } = result\n        if (changedFiles.length === 0) {\n          return\n        }\n        if (updates.every((update) => update.update.type === 'Noop')) {\n          debug?.(`ignored file change for ${changedFiles.join(', ')}`)\n          return\n        }\n        for (const { clientId, update } of updates) {\n          const client = this.clients.get(clientId)\n          if (client) {\n            this.invalidateCalledModules.get(client)?.clear()\n            this.handleHmrOutput(client, changedFiles, update)\n          }\n        }\n      },\n      onOutput: (result) => {\n        if (result instanceof Error) {\n          this.logger.error(colors.red(`✘ Build error: ${result.message}`), {\n            error: result,\n          })\n          this.hot.send({\n            type: 'error',\n            err: prepareError(result),\n          })\n          return\n        }\n\n        // NOTE: don't clear memoryFiles here as incremental build re-uses the files\n        for (const outputFile of result.output) {\n          this.memoryFiles.set(outputFile.fileName, () => {\n            const source =\n              outputFile.type === 'chunk' ? outputFile.code : outputFile.source\n            return {\n              source,\n              etag: getEtag(Buffer.from(source), { weak: true }),\n            }\n          })\n        }\n      },\n      watch: {\n        skipWrite: true,\n      },\n    })\n    debug?.('INITIAL: setup dev engine')\n    this.devEngine.run().then(\n      () => {\n        debug?.('INITIAL: run done')\n      },\n      (e) => {\n        debug?.('INITIAL: run error', e)\n      },\n    )\n    this.waitForInitialBuildFinish().then(() => {\n      debug?.('INITIAL: build done')\n      this.hot.send({ type: 'full-reload', path: '*' })\n    })\n  }\n\n  private async waitForInitialBuildFinish(): Promise<void> {\n    await this.devEngine.ensureCurrentBuildFinish()\n    while (this.memoryFiles.size === 0) {\n      await setTimeout(10)\n      await this.devEngine.ensureCurrentBuildFinish()\n    }\n  }\n\n  override async warmupRequest(_url: string): Promise<void> {\n    // no-op\n  }\n\n  protected override invalidateModule(\n    m: {\n      path: string\n      message?: string\n      firstInvalidatedBy: string\n    },\n    client: NormalizedHotChannelClient,\n  ): void {\n    ;(async () => {\n      const invalidateCalledModules = this.invalidateCalledModules.get(client)\n      if (invalidateCalledModules?.has(m.path)) {\n        debug?.(\n          `INVALIDATE: invalidate received from ${m.path}, but ignored because it was already invalidated`,\n        )\n        return\n      }\n\n      debug?.(\n        `INVALIDATE: invalidate received from ${m.path}, re-triggering HMR`,\n      )\n      if (!invalidateCalledModules) {\n        this.invalidateCalledModules.set(client, new Set([]))\n      }\n      this.invalidateCalledModules.get(client)!.add(m.path)\n\n      let update: BindingClientHmrUpdate['update'] | undefined\n      try {\n        const _update = await this.devEngine.invalidate(\n          m.path,\n          m.firstInvalidatedBy,\n        )\n        update = _update.find(\n          (u) => this.clients.get(u.clientId) === client,\n        )?.update\n      } catch (e) {\n        client.send({\n          type: 'error',\n          err: prepareError(e as Error),\n        })\n        return\n      }\n      if (!update) return\n\n      if (update.type === 'Patch') {\n        this.logger.info(\n          colors.yellow(`hmr invalidate `) +\n            colors.dim(m.path) +\n            (m.message ? ` ${m.message}` : ''),\n          { timestamp: true },\n        )\n      }\n\n      this.handleHmrOutput(client, [m.path], update, {\n        firstInvalidatedBy: m.firstInvalidatedBy,\n      })\n    })()\n  }\n\n  async triggerBundleRegenerationIfStale(): Promise<boolean> {\n    const bundleState = await this.devEngine.getBundleState()\n    const shouldTrigger =\n      bundleState.hasStaleOutput && !bundleState.lastFullBuildFailed\n    if (shouldTrigger) {\n      this.devEngine.ensureLatestBuildOutput().then(() => {\n        this.debouncedFullReload()\n      })\n      debug?.(`TRIGGER: access to stale bundle, triggered bundle re-generation`)\n    }\n    return shouldTrigger\n  }\n\n  override async close(): Promise<void> {\n    this.memoryFiles.clear()\n    await Promise.all([super.close(), this.devEngine.close()])\n  }\n\n  private async getRolldownOptions() {\n    const chunkMetadataMap = new ChunkMetadataMap()\n    const rolldownOptions = resolveRolldownOptions(this, chunkMetadataMap)\n    rolldownOptions.experimental ??= {}\n    rolldownOptions.experimental.devMode = {\n      implement: await getHmrImplementation(this.getTopLevelConfig()),\n    }\n\n    // disable inlineConst optimization due to a bug in Rolldown\n    // https://github.com/vitejs/vite/issues/21843\n    rolldownOptions.optimization ??= {}\n    rolldownOptions.optimization.inlineConst = false\n\n    // set filenames to make output paths predictable so that `renderChunk` hook does not need to be used\n    if (Array.isArray(rolldownOptions.output)) {\n      for (const output of rolldownOptions.output) {\n        output.entryFileNames = 'assets/[name].js'\n        output.chunkFileNames = 'assets/[name]-[hash].js'\n        output.assetFileNames = 'assets/[name]-[hash][extname]'\n        output.minify = false\n        output.sourcemap = true\n      }\n    } else {\n      rolldownOptions.output ??= {}\n      rolldownOptions.output.entryFileNames = 'assets/[name].js'\n      rolldownOptions.output.chunkFileNames = 'assets/[name]-[hash].js'\n      rolldownOptions.output.assetFileNames = 'assets/[name]-[hash][extname]'\n      rolldownOptions.output.minify = false\n      rolldownOptions.output.sourcemap = true\n    }\n\n    return rolldownOptions\n  }\n\n  private handleHmrOutput(\n    client: NormalizedHotChannelClient,\n    files: string[],\n    hmrOutput: HmrOutput,\n    invalidateInformation?: { firstInvalidatedBy: string },\n  ) {\n    if (hmrOutput.type === 'Noop') return\n\n    const shortFile = files\n      .map((file) => getShortName(file, this.config.root))\n      .join(', ')\n    if (hmrOutput.type === 'FullReload') {\n      const reason = hmrOutput.reason\n        ? colors.dim(` (${hmrOutput.reason})`)\n        : ''\n      this.logger.info(\n        colors.green(`trigger page reload `) + colors.dim(shortFile) + reason,\n        { clear: !invalidateInformation, timestamp: true },\n      )\n      this.devEngine.ensureLatestBuildOutput().then(() => {\n        this.debouncedFullReload()\n      })\n      return\n    }\n\n    debug?.(`handle hmr output for ${shortFile}`, {\n      ...hmrOutput,\n      code: typeof hmrOutput.code === 'string' ? '[code]' : hmrOutput.code,\n    })\n\n    this.memoryFiles.set(hmrOutput.filename, { source: hmrOutput.code })\n    if (hmrOutput.sourcemapFilename && hmrOutput.sourcemap) {\n      this.memoryFiles.set(hmrOutput.sourcemapFilename, {\n        source: hmrOutput.sourcemap,\n      })\n    }\n    const updates: Update[] = hmrOutput.hmrBoundaries.map((boundary: any) => {\n      return {\n        type: 'js-update',\n        url: hmrOutput.filename,\n        path: boundary.boundary,\n        acceptedPath: boundary.acceptedVia,\n        firstInvalidatedBy: invalidateInformation?.firstInvalidatedBy,\n        timestamp: Date.now(),\n      }\n    })\n    client.send({\n      type: 'update',\n      updates,\n    })\n    this.logger.info(\n      colors.green(`hmr update `) +\n        colors.dim([...new Set(updates.map((u) => u.path))].join(', ')),\n      { clear: !invalidateInformation, timestamp: true },\n    )\n  }\n}\n\nclass Clients {\n  private clientToId = new Map<NormalizedHotChannelClient, string>()\n  private idToClient = new Map<string, NormalizedHotChannelClient>()\n\n  setupIfNeeded(client: NormalizedHotChannelClient): string {\n    const id = this.clientToId.get(client)\n    if (id) return id\n\n    const newId = randomUUID()\n    this.clientToId.set(client, newId)\n    this.idToClient.set(newId, client)\n    return newId\n  }\n\n  get(id: string): NormalizedHotChannelClient | undefined {\n    return this.idToClient.get(id)\n  }\n\n  getAll(): NormalizedHotChannelClient[] {\n    return Array.from(this.idToClient.values())\n  }\n\n  delete(client: NormalizedHotChannelClient): string | undefined {\n    const id = this.clientToId.get(client)\n    if (id) {\n      this.clientToId.delete(client)\n      this.idToClient.delete(id)\n      return id\n    }\n  }\n}\n\nfunction debounce(time: number, cb: () => void) {\n  let timer: ReturnType<typeof globalThis.setTimeout> | null\n  return () => {\n    if (timer) {\n      globalThis.clearTimeout(timer)\n      timer = null\n    }\n    timer = globalThis.setTimeout(cb, time)\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/environments/runnableEnvironment.ts",
    "content": "import type { ModuleRunner } from 'vite/module-runner'\nimport type { ResolvedConfig } from '../../config'\nimport type { DevEnvironmentContext } from '../environment'\nimport { DevEnvironment } from '../environment'\nimport type { ServerModuleRunnerOptions } from '../../ssr/runtime/serverModuleRunner'\nimport { createServerModuleRunner } from '../../ssr/runtime/serverModuleRunner'\nimport { createServerHotChannel } from '../hmr'\nimport type { Environment } from '../../environment'\n\nexport function createRunnableDevEnvironment(\n  name: string,\n  config: ResolvedConfig,\n  context: RunnableDevEnvironmentContext = {},\n): RunnableDevEnvironment {\n  if (context.transport == null) {\n    context.transport = createServerHotChannel()\n  }\n  if (context.hot == null) {\n    context.hot = true\n  }\n\n  return new RunnableDevEnvironment(name, config, context)\n}\n\nexport interface RunnableDevEnvironmentContext extends Omit<\n  DevEnvironmentContext,\n  'hot'\n> {\n  runner?: (\n    environment: RunnableDevEnvironment,\n    options?: ServerModuleRunnerOptions,\n  ) => ModuleRunner\n  runnerOptions?: ServerModuleRunnerOptions\n  hot?: boolean\n}\n\nexport function isRunnableDevEnvironment(\n  environment: Environment,\n): environment is RunnableDevEnvironment {\n  return environment instanceof RunnableDevEnvironment\n}\n\nclass RunnableDevEnvironment extends DevEnvironment {\n  private _runner: ModuleRunner | undefined\n  private _runnerFactory:\n    | ((\n        environment: RunnableDevEnvironment,\n        options?: ServerModuleRunnerOptions,\n      ) => ModuleRunner)\n    | undefined\n  private _runnerOptions: ServerModuleRunnerOptions | undefined\n\n  constructor(\n    name: string,\n    config: ResolvedConfig,\n    context: RunnableDevEnvironmentContext,\n  ) {\n    super(name, config, context as DevEnvironmentContext)\n    this._runnerFactory = context.runner\n    this._runnerOptions = context.runnerOptions\n  }\n\n  get runner(): ModuleRunner {\n    if (this._runner) {\n      return this._runner\n    }\n    const factory = this._runnerFactory || createServerModuleRunner\n    this._runner = factory(this, this._runnerOptions)\n    return this._runner\n  }\n\n  override async close(): Promise<void> {\n    await super.close()\n    if (this._runner) {\n      await this._runner.close()\n    }\n  }\n}\n\nexport type { RunnableDevEnvironment }\n"
  },
  {
    "path": "packages/vite/src/node/server/hmr.ts",
    "content": "import fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport { EventEmitter } from 'node:events'\nimport colors from 'picocolors'\nimport type { RollupError } from 'rolldown'\nimport type { CustomPayload, HotPayload, Update } from '#types/hmrPayload'\nimport type {\n  InvokeMethods,\n  InvokeResponseData,\n  InvokeSendData,\n} from '../../shared/invokeMethods'\nimport { CLIENT_DIR } from '../constants'\nimport { createDebugger, monotonicDateNow, normalizePath } from '../utils'\nimport type { InferCustomEventPayload, ViteDevServer } from '..'\nimport { getHookHandler } from '../plugins'\nimport { isExplicitImportRequired } from '../plugins/importAnalysis'\nimport { getEnvFilesForMode } from '../env'\nimport type { Environment } from '../environment'\nimport { withTrailingSlash, wrapId } from '../../shared/utils'\nimport type { Plugin } from '../plugin'\nimport {\n  ignoreDeprecationWarnings,\n  warnFutureDeprecation,\n} from '../deprecations'\nimport type { EnvironmentModuleNode } from './moduleGraph'\nimport type { ModuleNode } from './mixedModuleGraph'\nimport type { DevEnvironment } from './environment'\nimport { prepareError } from './middlewares/error'\nimport {\n  BasicMinimalPluginContext,\n  basePluginContextMeta,\n} from './pluginContainer'\nimport type { HttpServer } from '.'\nimport { restartServerWithUrls } from '.'\n\nexport const debugHmr: ((...args: any[]) => any) | undefined =\n  createDebugger('vite:hmr')\n\nconst whitespaceRE = /\\s/\n\nconst normalizedClientDir = normalizePath(CLIENT_DIR)\n\nexport interface HmrOptions {\n  protocol?: string\n  host?: string\n  port?: number\n  clientPort?: number\n  path?: string\n  timeout?: number\n  overlay?: boolean\n  server?: HttpServer\n}\n\nexport interface HotUpdateOptions {\n  type: 'create' | 'update' | 'delete'\n  file: string\n  timestamp: number\n  modules: Array<EnvironmentModuleNode>\n  read: () => string | Promise<string>\n  server: ViteDevServer\n}\n\nexport interface HmrContext {\n  file: string\n  timestamp: number\n  modules: Array<ModuleNode>\n  read: () => string | Promise<string>\n  server: ViteDevServer\n}\n\ninterface PropagationBoundary {\n  boundary: EnvironmentModuleNode & { type: 'js' | 'css' }\n  acceptedVia: EnvironmentModuleNode\n  isWithinCircularImport: boolean\n}\n\nexport interface HotChannelClient {\n  send(payload: HotPayload): void\n}\n\nexport type HotChannelListener<T extends string = string> = (\n  data: InferCustomEventPayload<T>,\n  client: HotChannelClient,\n) => void\n\nexport interface HotChannel<Api = any> {\n  /**\n   * Broadcast events to all clients\n   */\n  send?(payload: HotPayload): void\n  /**\n   * Handle custom event emitted by `import.meta.hot.send`\n   */\n  on?<T extends string>(event: T, listener: HotChannelListener<T>): void\n  on?(event: 'connection', listener: () => void): void\n  /**\n   * Unregister event listener\n   */\n  off?(event: string, listener: Function): void\n  /**\n   * Start listening for messages\n   */\n  listen?(): void\n  /**\n   * Disconnect all clients, called when server is closed or restarted.\n   */\n  close?(): Promise<unknown> | void\n\n  api?: Api\n}\n\nexport function getShortName(file: string, root: string): string {\n  return file.startsWith(withTrailingSlash(root))\n    ? path.posix.relative(root, file)\n    : file\n}\n\nexport interface NormalizedHotChannelClient {\n  /**\n   * Send event to the client\n   */\n  send(payload: HotPayload): void\n  /**\n   * Send custom event\n   */\n  send(event: string, payload?: CustomPayload['data']): void\n}\n\nexport interface NormalizedHotChannel<Api = any> {\n  /**\n   * Broadcast events to all clients\n   */\n  send(payload: HotPayload): void\n  /**\n   * Send custom event\n   */\n  send<T extends string>(event: T, payload?: InferCustomEventPayload<T>): void\n  /**\n   * Handle custom event emitted by `import.meta.hot.send`\n   */\n  on<T extends string>(\n    event: T,\n    listener: (\n      data: InferCustomEventPayload<T>,\n      client: NormalizedHotChannelClient,\n    ) => void,\n  ): void\n  /**\n   * @deprecated use `vite:client:connect` event instead\n   */\n  on(event: 'connection', listener: () => void): void\n  /**\n   * Unregister event listener\n   */\n  off(event: string, listener: Function): void\n  /** @internal */\n  setInvokeHandler(invokeHandlers: InvokeMethods | undefined): void\n  handleInvoke(payload: HotPayload): Promise<{ result: any } | { error: any }>\n  /**\n   * Start listening for messages\n   */\n  listen(): void\n  /**\n   * Disconnect all clients, called when server is closed or restarted.\n   */\n  close(): Promise<unknown> | void\n\n  api?: Api\n}\n\nexport const normalizeHotChannel = (\n  channel: HotChannel,\n  enableHmr: boolean,\n  normalizeClient = true,\n): NormalizedHotChannel => {\n  const normalizedListenerMap = new WeakMap<\n    (data: any, client: NormalizedHotChannelClient) => void | Promise<void>,\n    (data: any, client: HotChannelClient) => void | Promise<void>\n  >()\n  const normalizedClients = new WeakMap<\n    HotChannelClient,\n    NormalizedHotChannelClient\n  >()\n\n  let invokeHandlers: InvokeMethods | undefined\n  let listenerForInvokeHandler:\n    | ((data: InvokeSendData, client: HotChannelClient) => void)\n    | undefined\n  const handleInvoke = async <T extends keyof InvokeMethods>(\n    payload: HotPayload,\n  ) => {\n    if (!invokeHandlers) {\n      return {\n        error: {\n          name: 'TransportError',\n          message: 'invokeHandlers is not set',\n          stack: new Error().stack,\n        },\n      }\n    }\n\n    const data: InvokeSendData<T> = (payload as CustomPayload).data\n    const { name, data: args } = data\n    try {\n      const invokeHandler = invokeHandlers[name]\n      // @ts-expect-error `invokeHandler` is `InvokeMethods[T]`, so passing the args is fine\n      const result = await invokeHandler(...args)\n      return { result }\n    } catch (error) {\n      return {\n        error: {\n          name: error.name,\n          message: error.message,\n          stack: error.stack,\n          ...error, // preserve enumerable properties such as RollupError.loc, frame, plugin\n        },\n      }\n    }\n  }\n\n  return {\n    ...channel,\n    on: (\n      event: string,\n      fn: (data: any, client: NormalizedHotChannelClient) => void,\n    ) => {\n      if (event === 'connection' || !normalizeClient) {\n        channel.on?.(event, fn as () => void)\n        return\n      }\n\n      const listenerWithNormalizedClient = (\n        data: any,\n        client: HotChannelClient,\n      ) => {\n        if (!normalizedClients.has(client)) {\n          normalizedClients.set(client, {\n            send: (...args) => {\n              let payload: HotPayload\n              if (typeof args[0] === 'string') {\n                payload = {\n                  type: 'custom',\n                  event: args[0],\n                  data: args[1],\n                }\n              } else {\n                payload = args[0]\n              }\n              client.send(payload)\n            },\n          })\n        }\n        fn(data, normalizedClients.get(client)!)\n      }\n      normalizedListenerMap.set(fn, listenerWithNormalizedClient)\n\n      channel.on?.(event, listenerWithNormalizedClient)\n    },\n    off: (event: string, fn: () => void) => {\n      if (event === 'connection' || !normalizeClient) {\n        channel.off?.(event, fn as () => void)\n        return\n      }\n\n      const normalizedListener = normalizedListenerMap.get(fn)\n      if (normalizedListener) {\n        channel.off?.(event, normalizedListener)\n      }\n    },\n    setInvokeHandler(_invokeHandlers) {\n      invokeHandlers = _invokeHandlers\n      if (!_invokeHandlers) {\n        if (listenerForInvokeHandler) {\n          channel.off?.('vite:invoke', listenerForInvokeHandler)\n        }\n        return\n      }\n\n      listenerForInvokeHandler = async (payload, client) => {\n        const responseInvoke = payload.id.replace('send', 'response') as\n          | 'response'\n          | `response:${string}`\n        client.send({\n          type: 'custom',\n          event: 'vite:invoke',\n          data: {\n            name: payload.name,\n            id: responseInvoke,\n            data: (await handleInvoke({\n              type: 'custom',\n              event: 'vite:invoke',\n              data: payload,\n            }))!,\n          } satisfies InvokeResponseData,\n        })\n      }\n      channel.on?.('vite:invoke', listenerForInvokeHandler)\n    },\n    handleInvoke,\n    send: (...args: any[]) => {\n      let payload: HotPayload\n      if (typeof args[0] === 'string') {\n        payload = {\n          type: 'custom',\n          event: args[0],\n          data: args[1],\n        }\n      } else {\n        payload = args[0]\n      }\n\n      if (\n        enableHmr ||\n        payload.type === 'connected' ||\n        payload.type === 'ping' ||\n        payload.type === 'custom' ||\n        payload.type === 'error'\n      ) {\n        channel.send?.(payload)\n      }\n    },\n    listen() {\n      return channel.listen?.()\n    },\n    close() {\n      return channel.close?.()\n    },\n  }\n}\n\nexport function getSortedPluginsByHotUpdateHook(\n  plugins: readonly Plugin[],\n): Plugin[] {\n  const sortedPlugins: Plugin[] = []\n  // Use indexes to track and insert the ordered plugins directly in the\n  // resulting array to avoid creating 3 extra temporary arrays per hook\n  let pre = 0,\n    normal = 0,\n    post = 0\n  for (const plugin of plugins) {\n    const hook = plugin['hotUpdate'] ?? plugin['handleHotUpdate']\n    if (hook) {\n      if (typeof hook === 'object') {\n        if (hook.order === 'pre') {\n          sortedPlugins.splice(pre++, 0, plugin)\n          continue\n        }\n        if (hook.order === 'post') {\n          sortedPlugins.splice(pre + normal + post++, 0, plugin)\n          continue\n        }\n      }\n      sortedPlugins.splice(pre + normal++, 0, plugin)\n    }\n  }\n\n  return sortedPlugins\n}\n\nconst sortedHotUpdatePluginsCache = new WeakMap<Environment, Plugin[]>()\nfunction getSortedHotUpdatePlugins(environment: Environment): Plugin[] {\n  let sortedPlugins = sortedHotUpdatePluginsCache.get(environment)\n  if (!sortedPlugins) {\n    sortedPlugins = getSortedPluginsByHotUpdateHook(environment.plugins)\n    sortedHotUpdatePluginsCache.set(environment, sortedPlugins)\n  }\n  return sortedPlugins\n}\n\nexport async function handleHMRUpdate(\n  type: 'create' | 'delete' | 'update',\n  file: string,\n  server: ViteDevServer,\n): Promise<void> {\n  const { config } = server\n  const mixedModuleGraph = ignoreDeprecationWarnings(() => server.moduleGraph)\n\n  const environments = Object.values(server.environments)\n  const shortFile = getShortName(file, config.root)\n\n  const isConfig = file === config.configFile\n  const isConfigDependency = config.configFileDependencies.some(\n    (name) => file === name,\n  )\n\n  const isEnv =\n    config.envDir !== false &&\n    getEnvFilesForMode(config.mode, config.envDir).includes(file)\n  if (isConfig || isConfigDependency || isEnv) {\n    // auto restart server\n    debugHmr?.(`[config change] ${colors.dim(shortFile)}`)\n    config.logger.info(\n      colors.green(\n        `${normalizePath(\n          path.relative(process.cwd(), file),\n        )} changed, restarting server...`,\n      ),\n      { clear: true, timestamp: true },\n    )\n    try {\n      await restartServerWithUrls(server)\n    } catch (e) {\n      config.logger.error(colors.red(e))\n    }\n    return\n  }\n\n  debugHmr?.(`[file change] ${colors.dim(shortFile)}`)\n\n  // (dev only) the client itself cannot be hot updated.\n  if (file.startsWith(withTrailingSlash(normalizedClientDir))) {\n    environments.forEach(({ hot }) =>\n      hot.send({\n        type: 'full-reload',\n        path: '*',\n        triggeredBy: path.resolve(config.root, file),\n      }),\n    )\n    return\n  }\n\n  if (config.experimental.bundledDev) {\n    // TODO: support handleHotUpdate / hotUpdate\n    return\n  }\n\n  const timestamp = monotonicDateNow()\n  const contextMeta = {\n    type,\n    file,\n    timestamp,\n    read: () => readModifiedFile(file),\n    server,\n  }\n  const hotMap = new Map<\n    Environment,\n    { options: HotUpdateOptions; error?: Error }\n  >()\n\n  for (const environment of Object.values(server.environments)) {\n    const mods = new Set(environment.moduleGraph.getModulesByFile(file))\n    if (type === 'create') {\n      for (const mod of environment.moduleGraph._hasResolveFailedErrorModules) {\n        mods.add(mod)\n      }\n    }\n    const options = {\n      ...contextMeta,\n      modules: [...mods],\n    }\n    hotMap.set(environment, { options })\n  }\n\n  const mixedMods = new Set(mixedModuleGraph.getModulesByFile(file))\n\n  const mixedHmrContext: HmrContext = {\n    ...contextMeta,\n    modules: [...mixedMods],\n  }\n\n  const contextForHandleHotUpdate = new BasicMinimalPluginContext(\n    { ...basePluginContextMeta, watchMode: true },\n    config.logger,\n  )\n  const clientEnvironment = server.environments.client\n  const ssrEnvironment = server.environments.ssr\n  const clientContext = clientEnvironment.pluginContainer.minimalContext\n  const clientHotUpdateOptions = hotMap.get(clientEnvironment)!.options\n  const ssrHotUpdateOptions = hotMap.get(ssrEnvironment)?.options\n  try {\n    for (const plugin of getSortedHotUpdatePlugins(\n      server.environments.client,\n    )) {\n      if (plugin.hotUpdate) {\n        const filteredModules = await getHookHandler(plugin.hotUpdate).call(\n          clientContext,\n          clientHotUpdateOptions,\n        )\n        if (filteredModules) {\n          clientHotUpdateOptions.modules = filteredModules\n          // Invalidate the hmrContext to force compat modules to be updated\n          mixedHmrContext.modules = mixedHmrContext.modules.filter(\n            (mixedMod) =>\n              filteredModules.some((mod) => mixedMod.id === mod.id) ||\n              ssrHotUpdateOptions?.modules.some(\n                (ssrMod) => ssrMod.id === mixedMod.id,\n              ),\n          )\n          mixedHmrContext.modules.push(\n            ...filteredModules\n              .filter(\n                (mod) =>\n                  !mixedHmrContext.modules.some(\n                    (mixedMod) => mixedMod.id === mod.id,\n                  ),\n              )\n              .map((mod) =>\n                mixedModuleGraph.getBackwardCompatibleModuleNode(mod),\n              ),\n          )\n        }\n      } else if (type === 'update') {\n        warnFutureDeprecation(\n          config,\n          'removePluginHookHandleHotUpdate',\n          `Used in plugin \"${plugin.name}\".`,\n          false,\n        )\n        // later on, we'll need: if (runtime === 'client')\n        // Backward compatibility with mixed client and ssr moduleGraph\n        const filteredModules = await getHookHandler(\n          plugin.handleHotUpdate!,\n        ).call(contextForHandleHotUpdate, mixedHmrContext)\n        if (filteredModules) {\n          mixedHmrContext.modules = filteredModules\n          clientHotUpdateOptions.modules =\n            clientHotUpdateOptions.modules.filter((mod) =>\n              filteredModules.some((mixedMod) => mod.id === mixedMod.id),\n            )\n          clientHotUpdateOptions.modules.push(\n            ...(filteredModules\n              .filter(\n                (mixedMod) =>\n                  !clientHotUpdateOptions.modules.some(\n                    (mod) => mod.id === mixedMod.id,\n                  ),\n              )\n              .map((mixedMod) => mixedMod._clientModule)\n              .filter(Boolean) as EnvironmentModuleNode[]),\n          )\n          if (ssrHotUpdateOptions) {\n            ssrHotUpdateOptions.modules = ssrHotUpdateOptions.modules.filter(\n              (mod) =>\n                filteredModules.some((mixedMod) => mod.id === mixedMod.id),\n            )\n            ssrHotUpdateOptions.modules.push(\n              ...(filteredModules\n                .filter(\n                  (mixedMod) =>\n                    !ssrHotUpdateOptions.modules.some(\n                      (mod) => mod.id === mixedMod.id,\n                    ),\n                )\n                .map((mixedMod) => mixedMod._ssrModule)\n                .filter(Boolean) as EnvironmentModuleNode[]),\n            )\n          }\n        }\n      }\n    }\n  } catch (error) {\n    hotMap.get(server.environments.client)!.error = error\n  }\n\n  for (const environment of Object.values(server.environments)) {\n    if (environment.name === 'client') continue\n    const hot = hotMap.get(environment)!\n    const context = environment.pluginContainer.minimalContext\n    try {\n      for (const plugin of getSortedHotUpdatePlugins(environment)) {\n        if (plugin.hotUpdate) {\n          const filteredModules = await getHookHandler(plugin.hotUpdate).call(\n            context,\n            hot.options,\n          )\n          if (filteredModules) {\n            hot.options.modules = filteredModules\n          }\n        }\n      }\n    } catch (error) {\n      hot.error = error\n    }\n  }\n\n  async function hmr(environment: DevEnvironment) {\n    try {\n      const { options, error } = hotMap.get(environment)!\n      if (error) {\n        throw error\n      }\n      if (!options.modules.length) {\n        // html file cannot be hot updated\n        if (file.endsWith('.html') && environment.name === 'client') {\n          environment.logger.info(\n            colors.green(`page reload `) + colors.dim(shortFile),\n            {\n              clear: true,\n              timestamp: true,\n            },\n          )\n          environment.hot.send({\n            type: 'full-reload',\n            path: config.server.middlewareMode\n              ? '*'\n              : '/' + normalizePath(path.relative(config.root, file)),\n          })\n        } else {\n          // loaded but not in the module graph, probably not js\n          debugHmr?.(\n            `(${environment.name}) [no modules matched] ${colors.dim(shortFile)}`,\n          )\n        }\n        return\n      }\n\n      updateModules(environment, shortFile, options.modules, timestamp)\n    } catch (err) {\n      environment.hot.send({\n        type: 'error',\n        err: prepareError(err),\n      })\n    }\n  }\n\n  const hotUpdateEnvironments =\n    server.config.server.hotUpdateEnvironments ??\n    ((server, hmr) => {\n      // Run HMR in parallel for all environments by default\n      return Promise.all(\n        Object.values(server.environments).map((environment) =>\n          hmr(environment),\n        ),\n      )\n    })\n\n  await hotUpdateEnvironments(server, hmr)\n}\n\ntype HasDeadEnd = string | boolean\n\nexport function updateModules(\n  environment: DevEnvironment,\n  file: string,\n  modules: EnvironmentModuleNode[],\n  timestamp: number,\n  firstInvalidatedBy?: string,\n): void {\n  const { hot } = environment\n  const updates: Update[] = []\n  const invalidatedModules = new Set<EnvironmentModuleNode>()\n  const traversedModules = new Set<EnvironmentModuleNode>()\n  // Modules could be empty if a root module is invalidated via import.meta.hot.invalidate()\n  let needFullReload: HasDeadEnd = modules.length === 0\n\n  for (const mod of modules) {\n    const boundaries: PropagationBoundary[] = []\n    const hasDeadEnd = propagateUpdate(mod, traversedModules, boundaries)\n\n    environment.moduleGraph.invalidateModule(\n      mod,\n      invalidatedModules,\n      timestamp,\n      true,\n    )\n\n    if (needFullReload) {\n      continue\n    }\n\n    if (hasDeadEnd) {\n      needFullReload = hasDeadEnd\n      continue\n    }\n\n    // If import.meta.hot.invalidate was called already on that module for the same update,\n    // it means any importer of that module can't hot update. We should fallback to full reload.\n    if (\n      firstInvalidatedBy &&\n      boundaries.some(\n        ({ acceptedVia }) =>\n          normalizeHmrUrl(acceptedVia.url) === firstInvalidatedBy,\n      )\n    ) {\n      needFullReload = 'circular import invalidate'\n      continue\n    }\n\n    updates.push(\n      ...boundaries.map(\n        ({ boundary, acceptedVia, isWithinCircularImport }) => ({\n          type: `${boundary.type}-update` as const,\n          timestamp,\n          path: normalizeHmrUrl(boundary.url),\n          acceptedPath: normalizeHmrUrl(acceptedVia.url),\n          explicitImportRequired:\n            boundary.type === 'js'\n              ? isExplicitImportRequired(acceptedVia.url)\n              : false,\n          isWithinCircularImport,\n          firstInvalidatedBy,\n        }),\n      ),\n    )\n  }\n\n  // html file cannot be hot updated because it may be used as the template for a top-level request response.\n  const isClientHtmlChange =\n    file.endsWith('.html') &&\n    environment.name === 'client' &&\n    // if the html file is imported as a module, we assume that this file is\n    // not used as the template for top-level request response\n    // (i.e. not used by the middleware).\n    modules.every((mod) => mod.type !== 'js')\n\n  if (needFullReload || isClientHtmlChange) {\n    const reason =\n      typeof needFullReload === 'string'\n        ? colors.dim(` (${needFullReload})`)\n        : ''\n    environment.logger.info(\n      colors.green(`page reload `) + colors.dim(file) + reason,\n      { clear: !firstInvalidatedBy, timestamp: true },\n    )\n    hot.send({\n      type: 'full-reload',\n      triggeredBy: path.resolve(environment.config.root, file),\n      path:\n        !isClientHtmlChange ||\n        environment.config.server.middlewareMode ||\n        updates.length > 0 // if there's an update, other URLs may be affected\n          ? '*'\n          : '/' + file,\n    })\n    return\n  }\n\n  if (updates.length === 0) {\n    debugHmr?.(colors.yellow(`no update happened `) + colors.dim(file))\n    return\n  }\n\n  environment.logger.info(\n    colors.green(`hmr update `) +\n      colors.dim([...new Set(updates.map((u) => u.path))].join(', ')),\n    { clear: !firstInvalidatedBy, timestamp: true },\n  )\n  hot.send({\n    type: 'update',\n    updates,\n  })\n}\n\nfunction areAllImportsAccepted(\n  importedBindings: Set<string>,\n  acceptedExports: Set<string>,\n) {\n  for (const binding of importedBindings) {\n    if (!acceptedExports.has(binding)) {\n      return false\n    }\n  }\n  return true\n}\n\nfunction propagateUpdate(\n  node: EnvironmentModuleNode,\n  traversedModules: Set<EnvironmentModuleNode>,\n  boundaries: PropagationBoundary[],\n  currentChain: EnvironmentModuleNode[] = [node],\n): HasDeadEnd {\n  if (traversedModules.has(node)) {\n    return false\n  }\n  traversedModules.add(node)\n\n  // #7561\n  // if the imports of `node` have not been analyzed, then `node` has not\n  // been loaded in the browser and we should stop propagation.\n  if (node.id && node.isSelfAccepting === undefined) {\n    debugHmr?.(\n      `[propagate update] stop propagation because not analyzed: ${colors.dim(\n        node.id,\n      )}`,\n    )\n    return false\n  }\n\n  if (node.isSelfAccepting) {\n    // isSelfAccepting is only true for js and css\n    const boundary = node as EnvironmentModuleNode & { type: 'js' | 'css' }\n    boundaries.push({\n      boundary,\n      acceptedVia: boundary,\n      isWithinCircularImport: isNodeWithinCircularImports(node, currentChain),\n    })\n    return false\n  }\n\n  // A partially accepted module with no importers is considered self accepting,\n  // because the deal is \"there are parts of myself I can't self accept if they\n  // are used outside of me\".\n  // Also, the imported module (this one) must be updated before the importers,\n  // so that they do get the fresh imported module when/if they are reloaded.\n  if (node.acceptedHmrExports) {\n    // acceptedHmrExports is only true for js and css\n    const boundary = node as EnvironmentModuleNode & { type: 'js' | 'css' }\n    boundaries.push({\n      boundary,\n      acceptedVia: boundary,\n      isWithinCircularImport: isNodeWithinCircularImports(node, currentChain),\n    })\n  } else {\n    if (!node.importers.size) {\n      return true\n    }\n  }\n\n  for (const importer of node.importers) {\n    const subChain = currentChain.concat(importer)\n\n    if (importer.acceptedHmrDeps.has(node)) {\n      // acceptedHmrDeps has value only for js and css\n      const boundary = importer as EnvironmentModuleNode & {\n        type: 'js' | 'css'\n      }\n      boundaries.push({\n        boundary,\n        acceptedVia: node,\n        isWithinCircularImport: isNodeWithinCircularImports(importer, subChain),\n      })\n      continue\n    }\n\n    if (node.id && node.acceptedHmrExports && importer.importedBindings) {\n      const importedBindingsFromNode = importer.importedBindings.get(node.id)\n      if (\n        importedBindingsFromNode &&\n        areAllImportsAccepted(importedBindingsFromNode, node.acceptedHmrExports)\n      ) {\n        continue\n      }\n    }\n\n    if (\n      !currentChain.includes(importer) &&\n      propagateUpdate(importer, traversedModules, boundaries, subChain)\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\n/**\n * Check importers recursively if it's an import loop. An accepted module within\n * an import loop cannot recover its execution order and should be reloaded.\n *\n * @param node The node that accepts HMR and is a boundary\n * @param nodeChain The chain of nodes/imports that lead to the node.\n *   (The last node in the chain imports the `node` parameter)\n * @param currentChain The current chain tracked from the `node` parameter\n * @param traversedModules The set of modules that have traversed\n */\nfunction isNodeWithinCircularImports(\n  node: EnvironmentModuleNode,\n  nodeChain: EnvironmentModuleNode[],\n  currentChain: EnvironmentModuleNode[] = [node],\n  traversedModules = new Set<EnvironmentModuleNode>(),\n): boolean {\n  // To help visualize how each parameter works, imagine this import graph:\n  //\n  // A -> B -> C -> ACCEPTED -> D -> E -> NODE\n  //      ^--------------------------|\n  //\n  // ACCEPTED: the node that accepts HMR. the `node` parameter.\n  // NODE    : the initial node that triggered this HMR.\n  //\n  // This function will return true in the above graph, which:\n  // `node`         : ACCEPTED\n  // `nodeChain`    : [NODE, E, D, ACCEPTED]\n  // `currentChain` : [ACCEPTED, C, B]\n  //\n  // It works by checking if any `node` importers are within `nodeChain`, which\n  // means there's an import loop with a HMR-accepted module in it.\n\n  if (traversedModules.has(node)) {\n    return false\n  }\n  traversedModules.add(node)\n\n  for (const importer of node.importers) {\n    // Node may import itself which is safe\n    if (importer === node) continue\n\n    // Check circular imports\n    const importerIndex = nodeChain.indexOf(importer)\n    if (importerIndex > -1) {\n      // Log extra debug information so users can fix and remove the circular imports\n      if (debugHmr) {\n        // Following explanation above:\n        // `importer`                    : E\n        // `currentChain` reversed       : [B, C, ACCEPTED]\n        // `nodeChain` sliced & reversed : [D, E]\n        // Combined                      : [E, B, C, ACCEPTED, D, E]\n        const importChain = [\n          importer,\n          ...[...currentChain].reverse(),\n          ...nodeChain.slice(importerIndex, -1).reverse(),\n        ]\n        debugHmr(\n          colors.yellow(`circular imports detected: `) +\n            importChain.map((m) => colors.dim(m.url)).join(' -> '),\n        )\n      }\n      return true\n    }\n\n    // Continue recursively\n    if (!currentChain.includes(importer)) {\n      const result = isNodeWithinCircularImports(\n        importer,\n        nodeChain,\n        currentChain.concat(importer),\n        traversedModules,\n      )\n      if (result) return result\n    }\n  }\n  return false\n}\n\nexport function handlePrunedModules(\n  mods: Set<EnvironmentModuleNode>,\n  { hot }: DevEnvironment,\n): void {\n  // update the disposed modules' hmr timestamp\n  // since if it's re-imported, it should re-apply side effects\n  // and without the timestamp the browser will not re-import it!\n  const t = monotonicDateNow()\n  mods.forEach((mod) => {\n    mod.lastHMRTimestamp = t\n    mod.lastHMRInvalidationReceived = false\n    debugHmr?.(`[dispose] ${colors.dim(mod.file)}`)\n  })\n  hot.send({\n    type: 'prune',\n    paths: [...mods].map((m) => m.url),\n  })\n}\n\nconst enum LexerState {\n  inCall,\n  inSingleQuoteString,\n  inDoubleQuoteString,\n  inTemplateString,\n  inArray,\n}\n\n/**\n * Lex import.meta.hot.accept() for accepted deps.\n * Since hot.accept() can only accept string literals or array of string\n * literals, we don't really need a heavy @babel/parse call on the entire source.\n *\n * @returns selfAccepts\n */\nexport function lexAcceptedHmrDeps(\n  code: string,\n  start: number,\n  urls: Set<{ url: string; start: number; end: number }>,\n): boolean {\n  let state: LexerState = LexerState.inCall\n  // the state can only be 2 levels deep so no need for a stack\n  let prevState: LexerState = LexerState.inCall\n  let currentDep: string = ''\n\n  function addDep(index: number) {\n    urls.add({\n      url: currentDep,\n      start: index - currentDep.length - 1,\n      end: index + 1,\n    })\n    currentDep = ''\n  }\n\n  for (let i = start; i < code.length; i++) {\n    const char = code.charAt(i)\n    switch (state) {\n      case LexerState.inCall:\n      case LexerState.inArray:\n        if (char === `'`) {\n          prevState = state\n          state = LexerState.inSingleQuoteString\n        } else if (char === `\"`) {\n          prevState = state\n          state = LexerState.inDoubleQuoteString\n        } else if (char === '`') {\n          prevState = state\n          state = LexerState.inTemplateString\n        } else if (whitespaceRE.test(char)) {\n          continue\n        } else {\n          if (state === LexerState.inCall) {\n            if (char === `[`) {\n              state = LexerState.inArray\n            } else {\n              // reaching here means the first arg is neither a string literal\n              // nor an Array literal (direct callback) or there is no arg\n              // in both case this indicates a self-accepting module\n              return true // done\n            }\n          } else {\n            if (char === `]`) {\n              return false // done\n            } else if (char === ',') {\n              continue\n            } else {\n              error(i)\n            }\n          }\n        }\n        break\n      case LexerState.inSingleQuoteString:\n        if (char === `'`) {\n          addDep(i)\n          if (prevState === LexerState.inCall) {\n            // accept('foo', ...)\n            return false\n          } else {\n            state = prevState\n          }\n        } else {\n          currentDep += char\n        }\n        break\n      case LexerState.inDoubleQuoteString:\n        if (char === `\"`) {\n          addDep(i)\n          if (prevState === LexerState.inCall) {\n            // accept('foo', ...)\n            return false\n          } else {\n            state = prevState\n          }\n        } else {\n          currentDep += char\n        }\n        break\n      case LexerState.inTemplateString:\n        if (char === '`') {\n          addDep(i)\n          if (prevState === LexerState.inCall) {\n            // accept('foo', ...)\n            return false\n          } else {\n            state = prevState\n          }\n        } else if (char === '$' && code.charAt(i + 1) === '{') {\n          error(i)\n        } else {\n          currentDep += char\n        }\n        break\n      default:\n        throw new Error('unknown import.meta.hot lexer state')\n    }\n  }\n  return false\n}\n\nexport function lexAcceptedHmrExports(\n  code: string,\n  start: number,\n  exportNames: Set<string>,\n): boolean {\n  const urls = new Set<{ url: string; start: number; end: number }>()\n  lexAcceptedHmrDeps(code, start, urls)\n  for (const { url } of urls) {\n    exportNames.add(url)\n  }\n  return urls.size > 0\n}\n\nexport function normalizeHmrUrl(url: string): string {\n  if (url[0] !== '.' && url[0] !== '/') {\n    url = wrapId(url)\n  }\n  return url\n}\n\nfunction error(pos: number) {\n  const err = new Error(\n    `import.meta.hot.accept() can only accept string literals or an ` +\n      `Array of string literals.`,\n  ) as RollupError\n  err.pos = pos\n  throw err\n}\n\n// vitejs/vite#610 when hot-reloading Vue files, we read immediately on file\n// change event and sometimes this can be too early and get an empty buffer.\n// Poll until the file's modified time has changed before reading again.\nasync function readModifiedFile(file: string): Promise<string> {\n  const content = await fsp.readFile(file, 'utf-8')\n  if (!content) {\n    const mtime = (await fsp.stat(file)).mtimeMs\n\n    for (let n = 0; n < 10; n++) {\n      await new Promise((r) => setTimeout(r, 10))\n      const newMtime = (await fsp.stat(file)).mtimeMs\n      if (newMtime !== mtime) {\n        break\n      }\n    }\n\n    return await fsp.readFile(file, 'utf-8')\n  } else {\n    return content\n  }\n}\n\nexport type ServerHotChannelApi = {\n  innerEmitter: EventEmitter\n  outsideEmitter: EventEmitter\n}\n\nexport type ServerHotChannel = HotChannel<ServerHotChannelApi>\nexport type NormalizedServerHotChannel =\n  NormalizedHotChannel<ServerHotChannelApi>\n\nexport function createServerHotChannel(): ServerHotChannel {\n  const innerEmitter = new EventEmitter()\n  const outsideEmitter = new EventEmitter()\n\n  return {\n    send(payload: HotPayload) {\n      outsideEmitter.emit('send', payload)\n    },\n    off(event, listener: () => void) {\n      innerEmitter.off(event, listener)\n    },\n    on: ((event: string, listener: () => unknown) => {\n      innerEmitter.on(event, listener)\n    }) as ServerHotChannel['on'],\n    close() {\n      innerEmitter.removeAllListeners()\n      outsideEmitter.removeAllListeners()\n    },\n    listen() {\n      innerEmitter.emit('connection')\n    },\n    api: {\n      innerEmitter,\n      outsideEmitter,\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/index.ts",
    "content": "import path from 'node:path'\nimport { execSync } from 'node:child_process'\nimport type * as net from 'node:net'\nimport { get as httpGet } from 'node:http'\nimport { get as httpsGet } from 'node:https'\nimport type * as http from 'node:http'\nimport { performance } from 'node:perf_hooks'\nimport type { Http2SecureServer } from 'node:http2'\nimport connect from 'connect'\nimport corsMiddleware from 'cors'\nimport colors from 'picocolors'\nimport chokidar from 'chokidar'\nimport launchEditorMiddleware from 'launch-editor-middleware'\nimport { determineAgent } from '@vercel/detect-agent'\nimport type { SourceMap } from 'rolldown'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { FSWatcher, WatchOptions } from '#dep-types/chokidar'\nimport type { Connect } from '#dep-types/connect'\nimport type { CommonServerOptions } from '../http'\nimport type {\n  ForwardConsoleOptions,\n  ResolvedForwardConsoleOptions,\n} from '../../shared/forwardConsole'\nimport {\n  httpServerStart,\n  resolveHttpServer,\n  resolveHttpsConfig,\n  setClientErrorHandler,\n} from '../http'\nimport type { InlineConfig, ResolvedConfig } from '../config'\nimport { isResolvedConfig, resolveConfig } from '../config'\nimport {\n  type Hostname,\n  diffDnsOrderChange,\n  getServerUrlByHost,\n  isInNodeModules,\n  isObject,\n  isParentDirectory,\n  mergeConfig,\n  mergeWithDefaults,\n  monotonicDateNow,\n  normalizePath,\n  resolveHostname,\n  resolveServerUrls,\n  setupSIGTERMListener,\n  teardownSIGTERMListener,\n} from '../utils'\nimport { ssrLoadModule } from '../ssr/ssrModuleLoader'\nimport { ssrFixStacktrace, ssrRewriteStacktrace } from '../ssr/ssrStacktrace'\nimport { ssrTransform } from '../ssr/ssrTransform'\nimport { reloadOnTsconfigChange } from '../plugins/esbuild'\nimport { bindCLIShortcuts } from '../shortcuts'\nimport type { BindCLIShortcutsOptions, ShortcutsState } from '../shortcuts'\nimport {\n  CLIENT_DIR,\n  DEFAULT_DEV_PORT,\n  defaultAllowedOrigins,\n} from '../constants'\nimport type { Logger } from '../logger'\nimport { printServerUrls } from '../logger'\nimport { warnFutureDeprecation } from '../deprecations'\nimport {\n  createNoopWatcher,\n  getResolvedOutDirs,\n  resolveChokidarOptions,\n  resolveEmptyOutDir,\n} from '../watch'\nimport { initPublicFiles } from '../publicDir'\nimport { getEnvFilesForMode } from '../env'\nimport type { RequiredExceptFor } from '../typeUtils'\nimport type { MinimalPluginContextWithoutEnvironment } from '../plugin'\nimport type { PluginContainer } from './pluginContainer'\nimport {\n  BasicMinimalPluginContext,\n  basePluginContextMeta,\n  createPluginContainer,\n} from './pluginContainer'\nimport type { WebSocketServer } from './ws'\nimport { createWebSocketServer } from './ws'\nimport { baseMiddleware } from './middlewares/base'\nimport { proxyMiddleware } from './middlewares/proxy'\nimport { htmlFallbackMiddleware } from './middlewares/htmlFallback'\nimport {\n  cachedTransformMiddleware,\n  transformMiddleware,\n} from './middlewares/transform'\nimport {\n  createDevHtmlTransformFn,\n  indexHtmlMiddleware,\n} from './middlewares/indexHtml'\nimport {\n  servePublicMiddleware,\n  serveRawFsMiddleware,\n  serveStaticMiddleware,\n} from './middlewares/static'\nimport { timeMiddleware } from './middlewares/time'\nimport { ModuleGraph } from './mixedModuleGraph'\nimport type { ModuleNode } from './mixedModuleGraph'\nimport { notFoundMiddleware } from './middlewares/notFound'\nimport { errorMiddleware } from './middlewares/error'\nimport type { HmrOptions, NormalizedHotChannel } from './hmr'\nimport { handleHMRUpdate, updateModules } from './hmr'\nimport { openBrowser as _openBrowser } from './openBrowser'\nimport type { TransformOptions, TransformResult } from './transformRequest'\nimport { searchForPackageRoot, searchForWorkspaceRoot } from './searchRoot'\nimport type { DevEnvironment } from './environment'\nimport { hostValidationMiddleware } from './middlewares/hostCheck'\nimport { rejectInvalidRequestMiddleware } from './middlewares/rejectInvalidRequest'\nimport { memoryFilesMiddleware } from './middlewares/memoryFiles'\nimport { rejectNoCorsRequestMiddleware } from './middlewares/rejectNoCorsRequest'\n\nconst usedConfigs = new WeakSet<ResolvedConfig>()\n\nexport interface ServerOptions extends CommonServerOptions {\n  /**\n   * Configure HMR-specific options (port, host, path & protocol)\n   */\n  hmr?: HmrOptions | boolean\n  /**\n   * Do not start the websocket connection.\n   * @experimental\n   */\n  ws?: false\n  /**\n   * Warm-up files to transform and cache the results in advance. This improves the\n   * initial page load during server starts and prevents transform waterfalls.\n   */\n  warmup?: {\n    /**\n     * The files to be transformed and used on the client-side. Supports glob patterns.\n     */\n    clientFiles?: string[]\n    /**\n     * The files to be transformed and used in SSR. Supports glob patterns.\n     */\n    ssrFiles?: string[]\n  }\n  /**\n   * chokidar watch options or null to disable FS watching\n   * https://github.com/paulmillr/chokidar/tree/3.6.0#api\n   */\n  watch?: WatchOptions | null\n  /**\n   * Create Vite dev server to be used as a middleware in an existing server\n   * @default false\n   */\n  middlewareMode?:\n    | boolean\n    | {\n        /**\n         * Parent server instance to attach to\n         *\n         * This is needed to proxy WebSocket connections to the parent server.\n         */\n        server: HttpServer\n      }\n  /**\n   * Options for files served via '/\\@fs/'.\n   */\n  fs?: FileSystemServeOptions\n  /**\n   * Origin for the generated asset URLs.\n   *\n   * @example `http://127.0.0.1:8080`\n   */\n  origin?: string\n  /**\n   * Pre-transform known direct imports\n   * @default true\n   */\n  preTransformRequests?: boolean\n  /**\n   * Whether or not to ignore-list source files in the dev server sourcemap, used to populate\n   * the [`x_google_ignoreList` source map extension](https://developer.chrome.com/blog/devtools-better-angular-debugging/#the-x_google_ignorelist-source-map-extension).\n   *\n   * By default, it excludes all paths containing `node_modules`. You can pass `false` to\n   * disable this behavior, or, for full control, a function that takes the source path and\n   * sourcemap path and returns whether to ignore the source path.\n   */\n  sourcemapIgnoreList?:\n    | false\n    | ((sourcePath: string, sourcemapPath: string) => boolean)\n  /**\n   * Backward compatibility. The buildStart and buildEnd hooks were called only once for\n   * the client environment. This option enables per-environment buildStart and buildEnd hooks.\n   * @default false\n   * @experimental\n   */\n  perEnvironmentStartEndDuringDev?: boolean\n  /**\n   * Backward compatibility. The watchChange hook was called only once for the client environment.\n   * This option enables per-environment watchChange hooks.\n   * @default false\n   * @experimental\n   */\n  perEnvironmentWatchChangeDuringDev?: boolean\n  /**\n   * Run HMR tasks, by default the HMR propagation is done in parallel for all environments\n   * @experimental\n   */\n  hotUpdateEnvironments?: (\n    server: ViteDevServer,\n    hmr: (environment: DevEnvironment) => Promise<void>,\n  ) => Promise<void>\n\n  forwardConsole?: boolean | ForwardConsoleOptions\n}\n\nexport interface ResolvedServerOptions extends Omit<\n  RequiredExceptFor<\n    ServerOptions,\n    | 'host'\n    | 'https'\n    | 'proxy'\n    | 'hmr'\n    | 'ws'\n    | 'watch'\n    | 'origin'\n    | 'hotUpdateEnvironments'\n  >,\n  'fs' | 'middlewareMode' | 'sourcemapIgnoreList' | 'forwardConsole'\n> {\n  fs: Required<FileSystemServeOptions>\n  middlewareMode: NonNullable<ServerOptions['middlewareMode']>\n  sourcemapIgnoreList: Exclude<\n    ServerOptions['sourcemapIgnoreList'],\n    false | undefined\n  >\n  forwardConsole: ResolvedForwardConsoleOptions\n}\n\nexport interface FileSystemServeOptions {\n  /**\n   * Strictly restrict file accessing outside of allowing paths.\n   *\n   * Set to `false` to disable the warning\n   *\n   * @default true\n   */\n  strict?: boolean\n\n  /**\n   * Restrict accessing files outside the allowed directories.\n   *\n   * Accepts absolute path or a path relative to project root.\n   * Will try to search up for workspace root by default.\n   */\n  allow?: string[]\n\n  /**\n   * Restrict accessing files that matches the patterns.\n   *\n   * This will have higher priority than `allow`.\n   * picomatch patterns are supported.\n   *\n   * @default ['.env', '.env.*', '*.{crt,pem}', '**\\/.git/**']\n   */\n  deny?: string[]\n}\n\nexport type ServerHook = (\n  this: MinimalPluginContextWithoutEnvironment,\n  server: ViteDevServer,\n) => (() => void) | void | Promise<(() => void) | void>\n\nexport type HttpServer = http.Server | Http2SecureServer\n\nexport async function resolveForwardConsoleOptions(\n  value: boolean | ForwardConsoleOptions | undefined,\n): Promise<ResolvedForwardConsoleOptions> {\n  value ??= (await determineAgent()).isAgent\n\n  if (value === false) {\n    return {\n      enabled: false,\n      unhandledErrors: false,\n      logLevels: [],\n    }\n  }\n\n  if (value === true) {\n    return {\n      enabled: true,\n      unhandledErrors: true,\n      logLevels: ['error', 'warn'],\n    }\n  }\n\n  const unhandledErrors = value.unhandledErrors ?? true\n  const logLevels = value.logLevels ?? []\n\n  return {\n    enabled: unhandledErrors || logLevels.length > 0,\n    unhandledErrors,\n    logLevels,\n  }\n}\n\nexport interface ViteDevServer {\n  /**\n   * The resolved vite config object\n   */\n  config: ResolvedConfig\n  /**\n   * A connect app instance.\n   * - Can be used to attach custom middlewares to the dev server.\n   * - Can also be used as the handler function of a custom http server\n   *   or as a middleware in any connect-style Node.js frameworks\n   *\n   * https://github.com/senchalabs/connect#use-middleware\n   */\n  middlewares: Connect.Server\n  /**\n   * native Node http server instance\n   * will be null in middleware mode\n   */\n  httpServer: HttpServer | null\n  /**\n   * Chokidar watcher instance. If `config.server.watch` is set to `null`,\n   * it will not watch any files and calling `add` or `unwatch` will have no effect.\n   * https://github.com/paulmillr/chokidar/tree/3.6.0#api\n   */\n  watcher: FSWatcher\n  /**\n   * WebSocket server with `send(payload)` method\n   */\n  ws: WebSocketServer\n  /**\n   * An alias to `server.environments.client.hot`.\n   * If you want to interact with all environments, loop over `server.environments`.\n   */\n  hot: NormalizedHotChannel\n  /**\n   * Rollup plugin container that can run plugin hooks on a given file\n   */\n  pluginContainer: PluginContainer\n  /**\n   * Module execution environments attached to the Vite server.\n   */\n  environments: Record<'client' | 'ssr' | (string & {}), DevEnvironment>\n  /**\n   * Module graph that tracks the import relationships, url to file mapping\n   * and hmr state.\n   */\n  moduleGraph: ModuleGraph\n  /**\n   * The resolved urls Vite prints on the CLI (URL-encoded). Returns `null`\n   * in middleware mode or if the server is not listening on any port.\n   */\n  resolvedUrls: ResolvedServerUrls | null\n  /**\n   * Programmatically resolve, load and transform a URL and get the result\n   * without going through the http request pipeline.\n   */\n  transformRequest(\n    url: string,\n    options?: TransformOptions,\n  ): Promise<TransformResult | null>\n  /**\n   * Same as `transformRequest` but only warm up the URLs so the next request\n   * will already be cached. The function will never throw as it handles and\n   * reports errors internally.\n   */\n  warmupRequest(url: string, options?: TransformOptions): Promise<void>\n  /**\n   * Apply vite built-in HTML transforms and any plugin HTML transforms.\n   */\n  transformIndexHtml(\n    url: string,\n    html: string,\n    originalUrl?: string,\n  ): Promise<string>\n  /**\n   * Transform module code into SSR format.\n   */\n  ssrTransform(\n    code: string,\n    inMap: SourceMap | { mappings: '' } | null,\n    url: string,\n    originalCode?: string,\n  ): Promise<TransformResult | null>\n  /**\n   * Load a given URL as an instantiated module for SSR.\n   */\n  ssrLoadModule(\n    url: string,\n    opts?: { fixStacktrace?: boolean },\n  ): Promise<Record<string, any>>\n  /**\n   * Returns a fixed version of the given stack\n   */\n  ssrRewriteStacktrace(stack: string): string\n  /**\n   * Mutates the given SSR error by rewriting the stacktrace\n   */\n  ssrFixStacktrace(e: Error): void\n  /**\n   * Triggers HMR for a module in the module graph. You can use the `server.moduleGraph`\n   * API to retrieve the module to be reloaded. If `hmr` is false, this is a no-op.\n   */\n  reloadModule(module: ModuleNode): Promise<void>\n  /**\n   * Start the server.\n   */\n  listen(port?: number, isRestart?: boolean): Promise<ViteDevServer>\n  /**\n   * Stop the server.\n   */\n  close(): Promise<void>\n  /**\n   * Print server urls\n   */\n  printUrls(): void\n  /**\n   * Bind CLI shortcuts\n   */\n  bindCLIShortcuts(options?: BindCLIShortcutsOptions<ViteDevServer>): void\n  /**\n   * Restart the server.\n   *\n   * @param forceOptimize - force the optimizer to re-bundle, same as --force cli flag\n   */\n  restart(forceOptimize?: boolean): Promise<void>\n  /**\n   * Open browser\n   */\n  openBrowser(): void\n  /**\n   * Calling `await server.waitForRequestsIdle(id)` will wait until all static imports\n   * are processed. If called from a load or transform plugin hook, the id needs to be\n   * passed as a parameter to avoid deadlocks. Calling this function after the first\n   * static imports section of the module graph has been processed will resolve immediately.\n   */\n  waitForRequestsIdle: (ignoredId?: string) => Promise<void>\n  /**\n   * @internal\n   */\n  _setInternalServer(server: ViteDevServer): void\n  /**\n   * @internal\n   */\n  _restartPromise: Promise<void> | null\n  /**\n   * @internal\n   */\n  _forceOptimizeOnRestart: boolean\n  /**\n   * @internal\n   */\n  _shortcutsState?: ShortcutsState<ViteDevServer>\n  /**\n   * @internal\n   */\n  _currentServerPort?: number | undefined\n  /**\n   * @internal\n   */\n  _configServerPort?: number | undefined\n  /**\n   * @internal\n   */\n  _ssrCompatModuleRunner?: ModuleRunner\n}\n\nexport interface ResolvedServerUrls {\n  local: string[]\n  network: string[]\n}\n\nexport function createServer(\n  inlineConfig: InlineConfig | ResolvedConfig = {},\n): Promise<ViteDevServer> {\n  return _createServer(inlineConfig, { listen: true })\n}\n\nexport async function _createServer(\n  inlineConfig: ResolvedConfig | InlineConfig | undefined = {},\n  options: {\n    listen: boolean\n    previousEnvironments?: Record<string, DevEnvironment>\n    previousShortcutsState?: ShortcutsState<ViteDevServer>\n    previousRestartPromise?: Promise<void> | null\n    previousForceOptimizeOnRestart?: boolean\n  },\n): Promise<ViteDevServer> {\n  const config = isResolvedConfig(inlineConfig)\n    ? inlineConfig\n    : await resolveConfig(inlineConfig, 'serve')\n\n  if (usedConfigs.has(config)) {\n    throw new Error(`There is already a server associated with the config.`)\n  }\n\n  if (config.command !== 'serve') {\n    throw new Error(\n      `Config was resolved for a \"build\", expected a \"serve\" command.`,\n    )\n  }\n\n  usedConfigs.add(config)\n\n  const initPublicFilesPromise = initPublicFiles(config)\n\n  const { root, server: serverConfig } = config\n  const httpsOptions = await resolveHttpsConfig(config.server.https)\n  const { middlewareMode } = serverConfig\n\n  const resolvedOutDirs = getResolvedOutDirs(\n    config.root,\n    config.build.outDir,\n    config.build.rollupOptions.output,\n  )\n  const emptyOutDir = resolveEmptyOutDir(\n    config.build.emptyOutDir,\n    config.root,\n    resolvedOutDirs,\n  )\n  const resolvedWatchOptions = resolveChokidarOptions(\n    {\n      disableGlobbing: true,\n      ...serverConfig.watch,\n    },\n    resolvedOutDirs,\n    emptyOutDir,\n    config.cacheDir,\n  )\n\n  const middlewares = connect() as Connect.Server\n  const httpServer = middlewareMode\n    ? null\n    : await resolveHttpServer(middlewares, httpsOptions)\n\n  const ws = createWebSocketServer(httpServer, config, httpsOptions)\n\n  const publicFiles = await initPublicFilesPromise\n  const { publicDir } = config\n\n  if (httpServer) {\n    setClientErrorHandler(httpServer, config.logger)\n  }\n\n  // eslint-disable-next-line eqeqeq\n  const watchEnabled = serverConfig.watch !== null\n  const watcher = watchEnabled\n    ? (chokidar.watch(\n        // config file dependencies and env file might be outside of root\n        [\n          ...(config.experimental.bundledDev ? [] : [root]),\n          ...config.configFileDependencies,\n          ...getEnvFilesForMode(config.mode, config.envDir),\n          // Watch the public directory explicitly because it might be outside\n          // of the root directory.\n          ...(publicDir && publicFiles ? [publicDir] : []),\n        ],\n\n        resolvedWatchOptions,\n      ) as FSWatcher)\n    : createNoopWatcher(resolvedWatchOptions)\n\n  const environments: Record<string, DevEnvironment> = {}\n\n  await Promise.all(\n    Object.entries(config.environments).map(\n      async ([name, environmentOptions]) => {\n        const environment = await environmentOptions.dev.createEnvironment(\n          name,\n          config,\n          {\n            ws,\n          },\n        )\n        environments[name] = environment\n\n        const previousInstance =\n          options.previousEnvironments?.[environment.name]\n        await environment.init({ watcher, previousInstance })\n      },\n    ),\n  )\n\n  // Backward compatibility\n\n  let moduleGraph = new ModuleGraph({\n    client: () => environments.client.moduleGraph,\n    ssr: () => environments.ssr.moduleGraph,\n  })\n  let pluginContainer = createPluginContainer(environments)\n\n  const closeHttpServer = createServerCloseFn(httpServer)\n\n  const devHtmlTransformFn = createDevHtmlTransformFn(config)\n\n  // Promise used by `server.close()` to ensure `closeServer()` is only called once\n  let closeServerPromise: Promise<void> | undefined\n  const closeServer = async () => {\n    if (!middlewareMode) {\n      teardownSIGTERMListener(closeServerAndExit)\n    }\n\n    await Promise.allSettled([\n      watcher.close(),\n      ws.close(),\n      Promise.allSettled(\n        Object.values(server.environments).map((environment) =>\n          environment.close(),\n        ),\n      ),\n      closeHttpServer(),\n      server._ssrCompatModuleRunner?.close(),\n    ])\n    server.resolvedUrls = null\n    server._ssrCompatModuleRunner = undefined\n  }\n\n  let hot = ws\n  let server: ViteDevServer = {\n    config,\n    middlewares,\n    httpServer,\n    watcher,\n    ws,\n    get hot() {\n      warnFutureDeprecation(config, 'removeServerHot')\n      return hot\n    },\n    set hot(h) {\n      hot = h\n    },\n\n    environments,\n    get pluginContainer() {\n      warnFutureDeprecation(config, 'removeServerPluginContainer')\n      return pluginContainer\n    },\n    set pluginContainer(p) {\n      pluginContainer = p\n    },\n    get moduleGraph() {\n      warnFutureDeprecation(config, 'removeServerModuleGraph')\n      return moduleGraph\n    },\n    set moduleGraph(graph) {\n      moduleGraph = graph\n    },\n\n    resolvedUrls: null, // will be set on listen\n    ssrTransform(\n      code: string,\n      inMap: SourceMap | { mappings: '' } | null,\n      url: string,\n      originalCode = code,\n    ) {\n      return ssrTransform(code, inMap, url, originalCode, {\n        json: {\n          stringify:\n            config.json.stringify === true && config.json.namedExports !== true,\n        },\n      })\n    },\n    transformRequest(url, options) {\n      warnFutureDeprecation(config, 'removeServerTransformRequest')\n      const environment = server.environments[options?.ssr ? 'ssr' : 'client']\n      return environment.transformRequest(url)\n    },\n    warmupRequest(url, options) {\n      warnFutureDeprecation(config, 'removeServerWarmupRequest')\n      const environment = server.environments[options?.ssr ? 'ssr' : 'client']\n      return environment.warmupRequest(url)\n    },\n    transformIndexHtml(url, html, originalUrl) {\n      return devHtmlTransformFn(server, url, html, originalUrl)\n    },\n    async ssrLoadModule(url, opts?: { fixStacktrace?: boolean }) {\n      warnFutureDeprecation(config, 'removeSsrLoadModule')\n      return ssrLoadModule(url, server, opts?.fixStacktrace)\n    },\n    ssrFixStacktrace(e) {\n      warnFutureDeprecation(\n        config,\n        'removeSsrLoadModule',\n        \"ssrFixStacktrace doesn't need to be used for Environment Module Runners.\",\n      )\n      ssrFixStacktrace(e, server.environments.ssr.moduleGraph)\n    },\n    ssrRewriteStacktrace(stack: string) {\n      warnFutureDeprecation(\n        config,\n        'removeSsrLoadModule',\n        \"ssrRewriteStacktrace doesn't need to be used for Environment Module Runners.\",\n      )\n      return ssrRewriteStacktrace(stack, server.environments.ssr.moduleGraph)\n        .result\n    },\n    async reloadModule(module) {\n      warnFutureDeprecation(config, 'removeServerReloadModule')\n      if (serverConfig.hmr !== false && module.file) {\n        // TODO: Should we also update the node moduleGraph for backward compatibility?\n        const environmentModule = (module._clientModule ?? module._ssrModule)!\n        updateModules(\n          environments[environmentModule.environment]!,\n          module.file,\n          [environmentModule],\n          monotonicDateNow(),\n        )\n      }\n    },\n    async listen(port?: number, isRestart?: boolean) {\n      const hostname = await resolveHostname(config.server.host)\n      if (httpServer) {\n        httpServer.prependListener('listening', () => {\n          server.resolvedUrls = resolveServerUrls(\n            httpServer,\n            config.server,\n            hostname,\n            httpsOptions,\n            config,\n          )\n        })\n      }\n      await startServer(server, hostname, port)\n      if (httpServer) {\n        if (!isRestart && config.server.open) server.openBrowser()\n      }\n      return server\n    },\n    openBrowser() {\n      const options = server.config.server\n      const url = getServerUrlByHost(server.resolvedUrls, options.host)\n      if (url) {\n        const path =\n          typeof options.open === 'string'\n            ? new URL(options.open, url).href\n            : url\n\n        // We know the url that the browser would be opened to, so we can\n        // start the request while we are awaiting the browser. This will\n        // start the crawling of static imports ~500ms before.\n        // preTransformRequests needs to be enabled for this optimization.\n        if (server.config.server.preTransformRequests) {\n          setTimeout(() => {\n            const getMethod = path.startsWith('https:') ? httpsGet : httpGet\n\n            getMethod(\n              path,\n              {\n                headers: {\n                  // Allow the history middleware to redirect to /index.html\n                  Accept: 'text/html',\n                },\n              },\n              (res) => {\n                res.on('end', () => {\n                  // Ignore response, scripts discovered while processing the entry\n                  // will be preprocessed (server.config.server.preTransformRequests)\n                })\n              },\n            )\n              .on('error', () => {\n                // Ignore errors\n              })\n              .end()\n          }, 0)\n        }\n\n        _openBrowser(path, true, server.config.logger)\n      } else {\n        server.config.logger.warn('No URL available to open in browser')\n      }\n    },\n    async close() {\n      if (!closeServerPromise) {\n        closeServerPromise = closeServer()\n      }\n      return closeServerPromise\n    },\n    printUrls() {\n      if (server.resolvedUrls) {\n        printServerUrls(\n          server.resolvedUrls,\n          serverConfig.host,\n          config.logger.info,\n        )\n      } else if (middlewareMode) {\n        throw new Error('cannot print server URLs in middleware mode.')\n      } else {\n        throw new Error(\n          'cannot print server URLs before server.listen is called.',\n        )\n      }\n    },\n    bindCLIShortcuts(options) {\n      bindCLIShortcuts(server, options)\n    },\n    async restart(forceOptimize?: boolean) {\n      if (!server._restartPromise) {\n        server._forceOptimizeOnRestart = !!forceOptimize\n        server._restartPromise = restartServer(server).finally(() => {\n          server._restartPromise = null\n          server._forceOptimizeOnRestart = false\n        })\n      }\n      return server._restartPromise\n    },\n\n    waitForRequestsIdle(ignoredId?: string): Promise<void> {\n      return environments.client.waitForRequestsIdle(ignoredId)\n    },\n\n    _setInternalServer(_server: ViteDevServer) {\n      // Rebind internal the server variable so functions reference the user\n      // server instance after a restart\n      server = _server\n    },\n    _restartPromise: options.previousRestartPromise ?? null,\n    _forceOptimizeOnRestart: options.previousForceOptimizeOnRestart ?? false,\n    _shortcutsState: options.previousShortcutsState,\n  }\n\n  // maintain consistency with the server instance after restarting.\n  const reflexServer = new Proxy(server, {\n    get: (_, property: keyof ViteDevServer) => {\n      return server[property]\n    },\n    set: (_, property: keyof ViteDevServer, value: never) => {\n      server[property] = value\n      return true\n    },\n  })\n\n  const closeServerAndExit = async (_: unknown, exitCode?: number) => {\n    try {\n      await server.close()\n    } finally {\n      process.exitCode ??= exitCode ? 128 + exitCode : undefined\n      process.exit()\n    }\n  }\n\n  if (!middlewareMode) {\n    setupSIGTERMListener(closeServerAndExit)\n  }\n\n  const onHMRUpdate = async (\n    type: 'create' | 'delete' | 'update',\n    file: string,\n  ) => {\n    if (serverConfig.hmr !== false) {\n      await handleHMRUpdate(type, file, server)\n    }\n  }\n\n  const onFileAddUnlink = async (file: string, isUnlink: boolean) => {\n    file = normalizePath(file)\n    reloadOnTsconfigChange(server, file)\n\n    await Promise.all(\n      Object.values(server.environments).map((environment) =>\n        environment.pluginContainer.watchChange(file, {\n          event: isUnlink ? 'delete' : 'create',\n        }),\n      ),\n    )\n\n    if (publicDir && publicFiles) {\n      if (file.startsWith(publicDir)) {\n        const path = file.slice(publicDir.length)\n        publicFiles[isUnlink ? 'delete' : 'add'](path)\n        if (!isUnlink) {\n          const clientModuleGraph = server.environments.client.moduleGraph\n          const moduleWithSamePath =\n            await clientModuleGraph.getModuleByUrl(path)\n          const etag = moduleWithSamePath?.transformResult?.etag\n          if (etag) {\n            // The public file should win on the next request over a module with the\n            // same path. Prevent the transform etag fast path from serving the module\n            clientModuleGraph.etagToModuleMap.delete(etag)\n          }\n        }\n      }\n    }\n    if (isUnlink) {\n      // invalidate module graph cache on file change\n      for (const environment of Object.values(server.environments)) {\n        environment.moduleGraph.onFileDelete(file)\n      }\n    }\n    await onHMRUpdate(isUnlink ? 'delete' : 'create', file)\n  }\n\n  watcher.on('change', async (file) => {\n    file = normalizePath(file)\n    reloadOnTsconfigChange(server, file)\n\n    await Promise.all(\n      Object.values(server.environments).map((environment) =>\n        environment.pluginContainer.watchChange(file, { event: 'update' }),\n      ),\n    )\n    // invalidate module graph cache on file change\n    for (const environment of Object.values(server.environments)) {\n      environment.moduleGraph.onFileChange(file)\n    }\n    await onHMRUpdate('update', file)\n  })\n\n  watcher.on('add', (file) => {\n    onFileAddUnlink(file, false)\n  })\n  watcher.on('unlink', (file) => {\n    onFileAddUnlink(file, true)\n  })\n\n  if (!middlewareMode && httpServer) {\n    httpServer.once('listening', () => {\n      // update actual port since this may be different from initial value\n      serverConfig.port = (httpServer.address() as net.AddressInfo).port\n    })\n  }\n\n  // Pre applied internal middlewares ------------------------------------------\n\n  // request timer\n  if (process.env.DEBUG) {\n    middlewares.use(timeMiddleware(root))\n  }\n\n  middlewares.use(rejectInvalidRequestMiddleware())\n  middlewares.use(rejectNoCorsRequestMiddleware())\n\n  // cors\n  const { cors } = serverConfig\n  if (cors !== false) {\n    middlewares.use(corsMiddleware(typeof cors === 'boolean' ? {} : cors))\n  }\n\n  // host check (to prevent DNS rebinding attacks)\n  const { allowedHosts } = serverConfig\n  // no need to check for HTTPS as HTTPS is not vulnerable to DNS rebinding attacks\n  if (allowedHosts !== true && !serverConfig.https) {\n    middlewares.use(hostValidationMiddleware(allowedHosts, false))\n  }\n\n  // apply configureServer hooks ------------------------------------------------\n\n  const configureServerContext = new BasicMinimalPluginContext(\n    { ...basePluginContextMeta, watchMode: true },\n    config.logger,\n  )\n  const postHooks: ((() => void) | void)[] = []\n  for (const hook of config.getSortedPluginHooks('configureServer')) {\n    postHooks.push(await hook.call(configureServerContext, reflexServer))\n  }\n\n  // Internal middlewares ------------------------------------------------------\n\n  if (!config.experimental.bundledDev) {\n    middlewares.use(cachedTransformMiddleware(server))\n  }\n\n  // proxy\n  const { proxy } = serverConfig\n  if (proxy) {\n    const middlewareServer =\n      (isObject(middlewareMode) ? middlewareMode.server : null) || httpServer\n    middlewares.use(proxyMiddleware(middlewareServer, proxy, config))\n  }\n\n  // base\n  if (config.base !== '/') {\n    middlewares.use(baseMiddleware(config.rawBase, !!middlewareMode))\n  }\n\n  // open in editor support\n  middlewares.use('/__open-in-editor', launchEditorMiddleware())\n\n  // ping request handler\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  middlewares.use(function viteHMRPingMiddleware(req, res, next) {\n    if (req.headers['accept'] === 'text/x-vite-ping') {\n      res.writeHead(204).end()\n    } else {\n      next()\n    }\n  })\n\n  // serve static files under /public\n  // this applies before the transform middleware so that these files are served\n  // as-is without transforms.\n  if (publicDir) {\n    middlewares.use(servePublicMiddleware(server, publicFiles))\n  }\n\n  if (config.experimental.bundledDev) {\n    middlewares.use(memoryFilesMiddleware(server))\n  } else {\n    // main transform middleware\n    middlewares.use(transformMiddleware(server))\n\n    // serve static files\n    middlewares.use(serveRawFsMiddleware(server))\n    middlewares.use(serveStaticMiddleware(server))\n  }\n\n  // html fallback\n  if (config.appType === 'spa' || config.appType === 'mpa') {\n    middlewares.use(\n      htmlFallbackMiddleware(\n        root,\n        config.appType === 'spa',\n        server.environments.client,\n      ),\n    )\n  }\n\n  // apply configureServer post hooks ------------------------------------------\n\n  // This is applied before the html middleware so that user middleware can\n  // serve custom content instead of index.html.\n  postHooks.forEach((fn) => fn && fn())\n\n  if (config.appType === 'spa' || config.appType === 'mpa') {\n    // transform index.html\n    middlewares.use(indexHtmlMiddleware(root, server))\n\n    // handle 404s\n    middlewares.use(notFoundMiddleware())\n  }\n\n  // error handler\n  middlewares.use(errorMiddleware(server, !!middlewareMode))\n\n  // httpServer.listen can be called multiple times\n  // when port when using next port number\n  // this code is to avoid calling buildStart multiple times\n  let initingServer: Promise<void> | undefined\n  let serverInited = false\n  const initServer = async (onListen: boolean) => {\n    if (serverInited) return\n    if (initingServer) return initingServer\n\n    initingServer = (async function () {\n      if (!config.experimental.bundledDev) {\n        // For backward compatibility, we call buildStart for the client\n        // environment when initing the server. For other environments\n        // buildStart will be called when the first request is transformed\n        await environments.client.pluginContainer.buildStart()\n      }\n\n      // ensure ws server started\n      if (onListen || options.listen) {\n        await Promise.all(\n          Object.values(environments).map((e) => e.listen(server)),\n        )\n      }\n\n      initingServer = undefined\n      serverInited = true\n    })()\n    return initingServer\n  }\n\n  if (!middlewareMode && httpServer) {\n    // overwrite listen to init optimizer before server start\n    const listen = httpServer.listen.bind(httpServer)\n    httpServer.listen = (async (port: number, ...args: any[]) => {\n      try {\n        await initServer(true)\n      } catch (e) {\n        httpServer.emit('error', e)\n        return\n      }\n      return listen(port, ...args)\n    }) as any\n  } else {\n    await initServer(false)\n  }\n\n  return server\n}\n\nasync function startServer(\n  server: ViteDevServer,\n  hostname: Hostname,\n  inlinePort?: number,\n): Promise<void> {\n  const httpServer = server.httpServer\n  if (!httpServer) {\n    throw new Error('Cannot call server.listen in middleware mode.')\n  }\n\n  const options = server.config.server\n  const configPort = inlinePort ?? options.port\n  // When using non strict port for the dev server, the running port can be different from the config one.\n  // When restarting, the original port may be available but to avoid a switch of URL for the running\n  // browser tabs, we enforce the previously used port, expect if the config port changed.\n  const port =\n    (!configPort || configPort === server._configServerPort\n      ? server._currentServerPort\n      : configPort) ?? DEFAULT_DEV_PORT\n  server._configServerPort = configPort\n\n  const serverPort = await httpServerStart(httpServer, {\n    port,\n    strictPort: options.strictPort,\n    host: hostname.host,\n    logger: server.config.logger,\n  })\n  server._currentServerPort = serverPort\n}\n\nexport function createServerCloseFn(\n  server: HttpServer | null,\n): () => Promise<void> {\n  if (!server) {\n    return () => Promise.resolve()\n  }\n\n  let hasListened = false\n  const openSockets = new Set<net.Socket>()\n\n  server.on('connection', (socket) => {\n    openSockets.add(socket)\n    socket.on('close', () => {\n      openSockets.delete(socket)\n    })\n  })\n\n  server.once('listening', () => {\n    hasListened = true\n  })\n\n  return () =>\n    new Promise<void>((resolve, reject) => {\n      openSockets.forEach((s) => s.destroy())\n      if (hasListened) {\n        server.close((err) => {\n          if (err) {\n            reject(err)\n          } else {\n            resolve()\n          }\n        })\n      } else {\n        resolve()\n      }\n    })\n}\n\nfunction resolvedAllowDir(root: string, dir: string): string {\n  return normalizePath(path.resolve(root, dir))\n}\n\nconst _serverConfigDefaults = Object.freeze({\n  port: DEFAULT_DEV_PORT,\n  strictPort: false,\n  host: 'localhost',\n  allowedHosts: [],\n  https: undefined,\n  open: false,\n  proxy: undefined,\n  cors: { origin: defaultAllowedOrigins },\n  headers: {},\n  // hmr\n  // ws\n  warmup: {\n    clientFiles: [],\n    ssrFiles: [],\n  },\n  // watch\n  middlewareMode: false,\n  fs: {\n    strict: true,\n    // allow\n    deny: ['.env', '.env.*', '*.{crt,pem}', '**/.git/**'],\n  },\n  // origin\n  preTransformRequests: true,\n  // sourcemapIgnoreList\n  perEnvironmentStartEndDuringDev: false,\n  perEnvironmentWatchChangeDuringDev: false,\n  // hotUpdateEnvironments\n  forwardConsole: undefined,\n} satisfies ServerOptions)\nexport const serverConfigDefaults: Readonly<Partial<ServerOptions>> =\n  _serverConfigDefaults\n\nexport async function resolveServerOptions(\n  root: string,\n  raw: ServerOptions | undefined,\n  logger: Logger,\n): Promise<ResolvedServerOptions> {\n  const _server = mergeWithDefaults(\n    {\n      ..._serverConfigDefaults,\n      host: undefined, // do not set here to detect whether host is set or not\n      sourcemapIgnoreList: isInNodeModules,\n    },\n    raw ?? {},\n  )\n\n  const server: ResolvedServerOptions = {\n    ..._server,\n    fs: {\n      ..._server.fs,\n      // run searchForWorkspaceRoot only if needed\n      allow: raw?.fs?.allow ?? [searchForWorkspaceRoot(root)],\n    },\n    sourcemapIgnoreList:\n      _server.sourcemapIgnoreList === false\n        ? () => false\n        : _server.sourcemapIgnoreList,\n    forwardConsole: await resolveForwardConsoleOptions(_server.forwardConsole),\n  }\n\n  let allowDirs = server.fs.allow\n\n  if (process.versions.pnp) {\n    // running a command fails if cwd doesn't exist and root may not exist\n    // search for package root to find a path that exists\n    const cwd = searchForPackageRoot(root)\n    try {\n      const enableGlobalCache =\n        execSync('yarn config get enableGlobalCache', { cwd })\n          .toString()\n          .trim() === 'true'\n      const yarnCacheDir = execSync(\n        `yarn config get ${enableGlobalCache ? 'globalFolder' : 'cacheFolder'}`,\n        { cwd },\n      )\n        .toString()\n        .trim()\n      allowDirs.push(yarnCacheDir)\n    } catch (e) {\n      logger.warn(`Get yarn cache dir error: ${e.message}`, {\n        timestamp: true,\n      })\n    }\n  }\n\n  allowDirs = allowDirs.map((i) => resolvedAllowDir(root, i))\n\n  // only push client dir when vite itself is outside-of-root\n  const resolvedClientDir = resolvedAllowDir(root, CLIENT_DIR)\n  if (!allowDirs.some((dir) => isParentDirectory(dir, resolvedClientDir))) {\n    allowDirs.push(resolvedClientDir)\n  }\n\n  server.fs.allow = allowDirs\n\n  if (server.origin?.endsWith('/')) {\n    server.origin = server.origin.slice(0, -1)\n    logger.warn(\n      colors.yellow(\n        `${colors.bold('(!)')} server.origin should not end with \"/\". Using \"${\n          server.origin\n        }\" instead.`,\n      ),\n    )\n  }\n\n  if (\n    process.env.__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS &&\n    Array.isArray(server.allowedHosts)\n  ) {\n    const additionalHost = process.env.__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS\n    server.allowedHosts = [...server.allowedHosts, additionalHost]\n  }\n\n  return server\n}\n\nasync function restartServer(server: ViteDevServer) {\n  global.__vite_start_time = performance.now()\n\n  let inlineConfig = server.config.inlineConfig\n  if (server._forceOptimizeOnRestart) {\n    inlineConfig = mergeConfig(inlineConfig, {\n      forceOptimizeDeps: true,\n    })\n  }\n\n  // Reinit the server by creating a new instance using the same inlineConfig\n  // This will trigger a reload of the config file and re-create the plugins and\n  // middlewares. We then assign all properties of the new server to the existing\n  // server instance and set the user instance to be used in the new server.\n  // This allows us to keep the same server instance for the user.\n  {\n    let newServer: ViteDevServer | null = null\n    try {\n      // delay ws server listen\n      newServer = await _createServer(inlineConfig, {\n        listen: false,\n        previousEnvironments: server.environments,\n        previousShortcutsState: server._shortcutsState,\n        previousRestartPromise: server._restartPromise,\n        previousForceOptimizeOnRestart: server._forceOptimizeOnRestart,\n      })\n    } catch (err: any) {\n      server.config.logger.error(err.message, {\n        timestamp: true,\n      })\n      server.config.logger.error('server restart failed', { timestamp: true })\n      return\n    }\n\n    // Detach readline so close handler skips it. Reused to avoid stdin issues\n    server._shortcutsState = undefined\n\n    await server.close()\n\n    // Assign new server props to existing server instance\n    const middlewares = server.middlewares\n    newServer._configServerPort = server._configServerPort\n    newServer._currentServerPort = server._currentServerPort\n    Object.assign(server, newServer)\n\n    // Keep the same connect instance so app.use(vite.middlewares) works\n    // after a restart in middlewareMode (.route is always '/')\n    middlewares.stack = newServer.middlewares.stack\n    server.middlewares = middlewares\n\n    // Rebind internal server variable so functions reference the user server\n    newServer._setInternalServer(server)\n  }\n\n  const {\n    logger,\n    server: { port, middlewareMode },\n  } = server.config\n  if (!middlewareMode) {\n    await server.listen(port, true)\n  } else {\n    await Promise.all(\n      Object.values(server.environments).map((e) => e.listen(server)),\n    )\n  }\n  logger.info('server restarted.', { timestamp: true })\n\n  if (\n    (server._shortcutsState as ShortcutsState<ViteDevServer> | undefined)\n      ?.options\n  ) {\n    bindCLIShortcuts(\n      server,\n      { print: false },\n      // Skip environment checks since shortcuts were bound before restart\n      true,\n    )\n  }\n}\n\n/**\n * Internal function to restart the Vite server and print URLs if changed\n */\nexport async function restartServerWithUrls(\n  server: ViteDevServer,\n): Promise<void> {\n  if (server.config.server.middlewareMode) {\n    await server.restart()\n    return\n  }\n\n  const { port: prevPort, host: prevHost } = server.config.server\n  const prevUrls = server.resolvedUrls\n\n  await server.restart()\n\n  const {\n    logger,\n    server: { port, host },\n  } = server.config\n  if (\n    (port ?? DEFAULT_DEV_PORT) !== (prevPort ?? DEFAULT_DEV_PORT) ||\n    host !== prevHost ||\n    diffDnsOrderChange(prevUrls, server.resolvedUrls)\n  ) {\n    logger.info('')\n    server.printUrls()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/__tests__/hostCheck.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getAdditionalAllowedHosts } from '../hostCheck'\n\ntest('getAdditionalAllowedHosts', async () => {\n  const actual = getAdditionalAllowedHosts(\n    {\n      host: 'vite.host.example.com',\n      hmr: {\n        host: 'vite.hmr-host.example.com',\n      },\n      origin: 'http://vite.origin.example.com:5173',\n    },\n    {\n      host: 'vite.preview-host.example.com',\n    },\n  ).sort()\n  expect(actual).toStrictEqual(\n    [\n      'vite.host.example.com',\n      'vite.hmr-host.example.com',\n      'vite.origin.example.com',\n      'vite.preview-host.example.com',\n    ].sort(),\n  )\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/__tests__/static.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { isFileInTargetPath } from '../static'\n\ndescribe('isFileInTargetPath', () => {\n  const cases = {\n    '/parent': {\n      '/parent': true,\n      '/parenta': false,\n      '/parent/': true,\n      '/parent/child': true,\n      '/parent/child/child2': true,\n    },\n    '/parent/': {\n      '/parent': false,\n      '/parenta': false,\n      '/parent/': true,\n      '/parent/child': true,\n      '/parent/child/child2': true,\n    },\n  }\n\n  for (const [parent, children] of Object.entries(cases)) {\n    for (const [child, expected] of Object.entries(children)) {\n      test(`isFileInTargetPath(\"${parent}\", \"${child}\")`, () => {\n        expect(isFileInTargetPath(parent, child)).toBe(expected)\n      })\n    }\n  }\n})\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/base.ts",
    "content": "import type { Connect } from '#dep-types/connect'\nimport { joinUrlSegments, stripBase } from '../../utils'\nimport { cleanUrl, withTrailingSlash } from '../../../shared/utils'\n\n// this middleware is only active when (base !== '/')\n\nexport function baseMiddleware(\n  rawBase: string,\n  middlewareMode: boolean,\n): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteBaseMiddleware(req, res, next) {\n    const url = req.url!\n    const pathname = cleanUrl(url)\n    const base = rawBase\n\n    if (pathname.startsWith(base)) {\n      // rewrite url to remove base. this ensures that other middleware does\n      // not need to consider base being prepended or not\n      req.url = stripBase(url, base)\n      return next()\n    }\n\n    // skip redirect and error fallback on middleware mode, #4057\n    if (middlewareMode) {\n      return next()\n    }\n\n    if (pathname === '/' || pathname === '/index.html') {\n      // redirect root visit to based url with search and hash\n      res.writeHead(302, {\n        Location: base + url.slice(pathname.length),\n      })\n      res.end()\n      return\n    }\n\n    // non-based page visit\n    const redirectPath =\n      withTrailingSlash(url) !== base ? joinUrlSegments(base, url) : base\n    if (req.headers.accept?.includes('text/html')) {\n      res.writeHead(404, {\n        'Content-Type': 'text/html',\n      })\n      res.end(\n        `The server is configured with a public base URL of ${base} - ` +\n          `did you mean to visit <a href=\"${redirectPath}\">${redirectPath}</a> instead?`,\n      )\n      return\n    } else {\n      // not found for resources\n      res.writeHead(404, {\n        'Content-Type': 'text/plain',\n      })\n      res.end(\n        `The server is configured with a public base URL of ${base} - ` +\n          `did you mean to visit ${redirectPath} instead?`,\n      )\n      return\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/error.ts",
    "content": "import path from 'node:path'\nimport { stripVTControlCharacters as strip } from 'node:util'\nimport colors from 'picocolors'\nimport type { RollupError } from 'rolldown'\nimport type { Connect } from '#dep-types/connect'\nimport type { ErrorPayload } from '#types/hmrPayload'\nimport { pad } from '../../utils'\nimport type { ViteDevServer } from '../..'\nimport { CLIENT_PUBLIC_PATH } from '../../constants'\n\nexport function prepareError(err: Error | RollupError): ErrorPayload['err'] {\n  // only copy the information we need and avoid serializing unnecessary\n  // properties, since some errors may attach full objects (e.g. PostCSS)\n  return {\n    message: strip(err.message),\n    stack: strip(cleanStack(err.stack || '')),\n    id: (err as RollupError).id,\n    frame: strip((err as RollupError).frame || ''),\n    plugin: (err as RollupError).plugin,\n    pluginCode: (err as RollupError).pluginCode?.toString(),\n    loc: (err as RollupError).loc,\n  }\n}\n\nexport function buildErrorMessage(\n  err: RollupError,\n  args: string[] = [],\n  includeStack = true,\n): string {\n  if (err.plugin) args.push(`  Plugin: ${colors.magenta(err.plugin)}`)\n  const loc = err.loc ? `:${err.loc.line}:${err.loc.column}` : ''\n  if (err.id) args.push(`  File: ${colors.cyan(err.id)}${loc}`)\n  if (err.frame) args.push(colors.yellow(pad(err.frame)))\n  if (includeStack && err.stack) args.push(pad(cleanStack(err.stack)))\n  return args.join('\\n')\n}\n\nfunction cleanStack(stack: string) {\n  return stack\n    .split(/\\n/)\n    .filter((l) => /^\\s*at/.test(l))\n    .join('\\n')\n}\n\nexport function logError(server: ViteDevServer, err: RollupError): void {\n  const msg = buildErrorMessage(err, [\n    colors.red(`Internal server error: ${err.message}`),\n  ])\n\n  server.config.logger.error(msg, {\n    clear: true,\n    timestamp: true,\n    error: err,\n  })\n\n  server.environments.client.hot.send({\n    type: 'error',\n    err: prepareError(err),\n  })\n}\n\nexport function errorMiddleware(\n  server: ViteDevServer,\n  allowNext = false,\n): Connect.ErrorHandleFunction {\n  // note the 4 args must be kept for connect to treat this as error middleware\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteErrorMiddleware(err: RollupError, _req, res, next) {\n    logError(server, err)\n\n    if (allowNext) {\n      next()\n    } else {\n      res.statusCode = 500\n      res.end(`\n        <!DOCTYPE html>\n        <html lang=\"en\">\n          <head>\n            <meta charset=\"UTF-8\" />\n            <title>Error</title>\n            <script type=\"module\">\n              const error = ${JSON.stringify(prepareError(err)).replace(\n                /</g,\n                '\\\\u003c',\n              )}\n              try {\n                const { ErrorOverlay } = await import(${JSON.stringify(path.posix.join(server.config.base, CLIENT_PUBLIC_PATH))})\n                document.body.appendChild(new ErrorOverlay(error))\n              } catch {\n                const h = (tag, text) => {\n                  const el = document.createElement(tag)\n                  el.textContent = text\n                  return el\n                }\n                document.body.appendChild(h('h1', 'Internal Server Error'))\n                document.body.appendChild(h('h2', error.message))\n                document.body.appendChild(h('pre', error.stack))\n                document.body.appendChild(h('p', '(Error overlay failed to load)'))\n              }\n            </script>\n          </head>\n          <body>\n          </body>\n        </html>\n      `)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/hostCheck.ts",
    "content": "import { hostValidationMiddleware as originalHostValidationMiddleware } from 'host-validation-middleware'\nimport type { Connect } from '#dep-types/connect'\nimport type { ResolvedPreviewOptions, ResolvedServerOptions } from '../..'\n\nexport function getAdditionalAllowedHosts(\n  resolvedServerOptions: Pick<ResolvedServerOptions, 'host' | 'hmr' | 'origin'>,\n  resolvedPreviewOptions: Pick<ResolvedPreviewOptions, 'host'>,\n): string[] {\n  const list = []\n\n  // allow host option by default as that indicates that the user is\n  // expecting Vite to respond on that host\n  if (\n    typeof resolvedServerOptions.host === 'string' &&\n    resolvedServerOptions.host\n  ) {\n    list.push(resolvedServerOptions.host)\n  }\n  if (\n    typeof resolvedServerOptions.hmr === 'object' &&\n    resolvedServerOptions.hmr.host\n  ) {\n    list.push(resolvedServerOptions.hmr.host)\n  }\n  if (\n    typeof resolvedPreviewOptions.host === 'string' &&\n    resolvedPreviewOptions.host\n  ) {\n    list.push(resolvedPreviewOptions.host)\n  }\n\n  // allow server origin by default as that indicates that the user is\n  // expecting Vite to respond on that host\n  if (resolvedServerOptions.origin) {\n    // some frameworks may pass the origin as a placeholder, so it's not\n    // possible to parse as URL, so use a try-catch here as a best effort\n    try {\n      const serverOriginUrl = new URL(resolvedServerOptions.origin)\n      list.push(serverOriginUrl.hostname)\n    } catch {}\n  }\n\n  return list\n}\n\nexport function hostValidationMiddleware(\n  allowedHosts: string[],\n  isPreview: boolean,\n): Connect.NextHandleFunction {\n  return originalHostValidationMiddleware({\n    // Freeze the array to allow caching\n    allowedHosts: Object.freeze([...allowedHosts]),\n    generateErrorMessage(hostname) {\n      const hostnameWithQuotes = JSON.stringify(hostname)\n      const optionName = `${isPreview ? 'preview' : 'server'}.allowedHosts`\n      return (\n        `Blocked request. This host (${hostnameWithQuotes}) is not allowed.\\n` +\n        `To allow this host, add ${hostnameWithQuotes} to \\`${optionName}\\` in vite.config.js.`\n      )\n    },\n  })\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/htmlFallback.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport type { Connect } from '#dep-types/connect'\nimport { createDebugger, joinUrlSegments } from '../../utils'\nimport { cleanUrl } from '../../../shared/utils'\nimport type { DevEnvironment } from '../environment'\nimport { FullBundleDevEnvironment } from '../environments/fullBundleEnvironment'\n\nconst debug = createDebugger('vite:html-fallback')\n\nexport function htmlFallbackMiddleware(\n  root: string,\n  spaFallback: boolean,\n  clientEnvironment?: DevEnvironment,\n): Connect.NextHandleFunction {\n  const memoryFiles =\n    clientEnvironment instanceof FullBundleDevEnvironment\n      ? clientEnvironment.memoryFiles\n      : undefined\n\n  function checkFileExists(relativePath: string) {\n    return (\n      memoryFiles?.has(\n        relativePath.slice(1), // remove first /\n      ) ?? fs.existsSync(path.join(root, relativePath))\n    )\n  }\n\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteHtmlFallbackMiddleware(req, _res, next) {\n    if (\n      // Only accept GET or HEAD\n      (req.method !== 'GET' && req.method !== 'HEAD') ||\n      // Exclude default favicon requests\n      req.url === '/favicon.ico' ||\n      // Require Accept: text/html or */*\n      !(\n        req.headers.accept === undefined || // equivalent to `Accept: */*`\n        req.headers.accept === '' || // equivalent to `Accept: */*`\n        req.headers.accept.includes('text/html') ||\n        req.headers.accept.includes('*/*')\n      )\n    ) {\n      return next()\n    }\n\n    const url = cleanUrl(req.url!)\n    let pathname\n    try {\n      pathname = decodeURIComponent(url)\n    } catch {\n      // ignore malformed URI\n      return next()\n    }\n\n    // .html files are not handled by serveStaticMiddleware\n    // so we need to check if the file exists\n    if (pathname.endsWith('.html')) {\n      if (checkFileExists(pathname)) {\n        debug?.(`Rewriting ${req.method} ${req.url} to ${url}`)\n        req.url = url\n        return next()\n      }\n    }\n    // trailing slash should check for fallback index.html\n    else if (pathname.endsWith('/')) {\n      if (checkFileExists(joinUrlSegments(pathname, 'index.html'))) {\n        const newUrl = url + 'index.html'\n        debug?.(`Rewriting ${req.method} ${req.url} to ${newUrl}`)\n        req.url = newUrl\n        return next()\n      }\n    }\n    // non-trailing slash should check for fallback .html\n    else {\n      if (checkFileExists(pathname + '.html')) {\n        const newUrl = url + '.html'\n        debug?.(`Rewriting ${req.method} ${req.url} to ${newUrl}`)\n        req.url = newUrl\n        return next()\n      }\n    }\n\n    if (spaFallback) {\n      debug?.(`Rewriting ${req.method} ${req.url} to /index.html`)\n      req.url = '/index.html'\n    }\n\n    next()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/indexHtml.ts",
    "content": "import fs from 'node:fs'\nimport fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport MagicString from 'magic-string'\nimport type { SourceMapInput } from 'rolldown'\nimport type { DefaultTreeAdapterMap, Token } from 'parse5'\nimport type { Connect } from '#dep-types/connect'\nimport type { IndexHtmlTransformHook } from '../../plugins/html'\nimport {\n  addToHTMLProxyCache,\n  applyHtmlTransforms,\n  extractImportExpressionFromClassicScript,\n  findNeedTransformStyleAttribute,\n  getScriptInfo,\n  htmlEnvHook,\n  htmlProxyResult,\n  injectCspNonceMetaTagHook,\n  injectNonceAttributeTagHook,\n  nodeIsElement,\n  overwriteAttrValue,\n  postImportMapHook,\n  preImportMapHook,\n  removeViteIgnoreAttr,\n  resolveHtmlTransforms,\n  traverseHtml,\n} from '../../plugins/html'\nimport type { PreviewServer, ResolvedConfig, ViteDevServer } from '../..'\nimport { send } from '../send'\nimport { CLIENT_PUBLIC_PATH, FS_PREFIX } from '../../constants'\nimport {\n  ensureWatchedFile,\n  fsPathFromId,\n  getHash,\n  injectQuery,\n  isCSSRequest,\n  isDevServer,\n  isJSRequest,\n  isParentDirectory,\n  joinUrlSegments,\n  normalizePath,\n  processSrcSetSync,\n  stripBase,\n} from '../../utils'\nimport { checkPublicFile } from '../../publicDir'\nimport { getCodeWithSourcemap, injectSourcesContent } from '../sourcemap'\nimport { cleanUrl, unwrapId, wrapId } from '../../../shared/utils'\nimport { getNodeAssetAttributes } from '../../assetSource'\nimport {\n  BasicMinimalPluginContext,\n  basePluginContextMeta,\n} from '../pluginContainer'\nimport { FullBundleDevEnvironment } from '../environments/fullBundleEnvironment'\nimport { getHmrImplementation } from '../../plugins/clientInjections'\nimport { checkLoadingAccess, respondWithAccessDenied } from './static'\n\ninterface AssetNode {\n  start: number\n  end: number\n  code: string\n}\n\ninterface InlineStyleAttribute {\n  index: number\n  location: Token.Location\n  code: string\n}\n\nexport function createDevHtmlTransformFn(\n  config: ResolvedConfig,\n): (\n  server: ViteDevServer,\n  url: string,\n  html: string,\n  originalUrl?: string,\n) => Promise<string> {\n  const [preHooks, normalHooks, postHooks] = resolveHtmlTransforms(\n    config.plugins,\n  )\n  const transformHooks = [\n    preImportMapHook(config),\n    injectCspNonceMetaTagHook(config),\n    ...preHooks,\n    htmlEnvHook(config),\n    devHtmlHook,\n    ...normalHooks,\n    ...postHooks,\n    injectNonceAttributeTagHook(config),\n    postImportMapHook(),\n  ]\n  const pluginContext = new BasicMinimalPluginContext(\n    { ...basePluginContextMeta, watchMode: true },\n    config.logger,\n  )\n  return (\n    server: ViteDevServer,\n    url: string,\n    html: string,\n    originalUrl?: string,\n  ): Promise<string> => {\n    return applyHtmlTransforms(html, transformHooks, pluginContext, {\n      path: url,\n      filename: getHtmlFilename(url, server),\n      server,\n      originalUrl,\n    })\n  }\n}\n\nfunction getHtmlFilename(url: string, server: ViteDevServer) {\n  if (url.startsWith(FS_PREFIX)) {\n    return decodeURIComponent(fsPathFromId(url))\n  } else {\n    return decodeURIComponent(\n      normalizePath(path.join(server.config.root, url.slice(1))),\n    )\n  }\n}\n\nfunction shouldPreTransform(url: string, config: ResolvedConfig) {\n  return (\n    !checkPublicFile(url, config) && (isJSRequest(url) || isCSSRequest(url))\n  )\n}\n\nconst wordCharRE = /\\w/\n\nfunction isBareRelative(url: string) {\n  return wordCharRE.test(url[0]) && !url.includes(':')\n}\n\nconst processNodeUrl = (\n  url: string,\n  useSrcSetReplacer: boolean,\n  config: ResolvedConfig,\n  htmlPath: string,\n  originalUrl?: string,\n  server?: ViteDevServer,\n  isClassicScriptLink?: boolean,\n): string => {\n  // prefix with base (dev only, base is never relative)\n  const replacer = (url: string) => {\n    if (\n      (url[0] === '/' && url[1] !== '/') ||\n      // #3230 if some request url (localhost:3000/a/b) return to fallback html, the relative assets\n      // path will add `/a/` prefix, it will caused 404.\n      //\n      // skip if url contains `:` as it implies a url protocol or Windows path that we don't want to replace.\n      //\n      // rewrite `./index.js` -> `localhost:5173/a/index.js`.\n      // rewrite `../index.js` -> `localhost:5173/index.js`.\n      // rewrite `relative/index.js` -> `localhost:5173/a/relative/index.js`.\n      ((url[0] === '.' || isBareRelative(url)) &&\n        originalUrl &&\n        originalUrl !== '/' &&\n        htmlPath === '/index.html')\n    ) {\n      url = path.posix.join(config.base, url)\n    }\n\n    let preTransformUrl: string | undefined\n\n    if (!isClassicScriptLink && shouldPreTransform(url, config)) {\n      if (url[0] === '/' && url[1] !== '/') {\n        preTransformUrl = url\n      } else if (url[0] === '.' || isBareRelative(url)) {\n        preTransformUrl = path.posix.join(\n          config.base,\n          path.posix.dirname(htmlPath),\n          url,\n        )\n      }\n    }\n\n    if (server) {\n      const mod = server.environments.client.moduleGraph.urlToModuleMap.get(\n        preTransformUrl || url,\n      )\n      if (mod && mod.lastHMRTimestamp > 0) {\n        url = injectQuery(url, `t=${mod.lastHMRTimestamp}`)\n      }\n    }\n\n    if (server && preTransformUrl) {\n      try {\n        preTransformUrl = decodeURI(preTransformUrl)\n      } catch {\n        // Malformed uri. Skip pre-transform.\n        return url\n      }\n      preTransformRequest(server, preTransformUrl, config.decodedBase)\n    }\n\n    return url\n  }\n\n  const processedUrl = useSrcSetReplacer\n    ? processSrcSetSync(url, ({ url }) => replacer(url))\n    : replacer(url)\n  return processedUrl\n}\nconst devHtmlHook: IndexHtmlTransformHook = async (\n  html,\n  { path: htmlPath, filename, server, originalUrl },\n) => {\n  const { config, watcher } = server!\n  const base = config.base || '/'\n  const decodedBase = config.decodedBase || '/'\n\n  let proxyModulePath: string\n  let proxyModuleUrl: string\n\n  const trailingSlash = htmlPath.endsWith('/')\n  if (!trailingSlash && fs.existsSync(filename)) {\n    proxyModulePath = htmlPath\n    proxyModuleUrl = proxyModulePath\n  } else {\n    // There are users of vite.transformIndexHtml calling it with url '/'\n    // for SSR integrations #7993, filename is root for this case\n    // A user may also use a valid name for a virtual html file\n    // Mark the path as virtual in both cases so sourcemaps aren't processed\n    // and ids are properly handled\n    const validPath = `${htmlPath}${trailingSlash ? 'index.html' : ''}`\n    proxyModulePath = `\\0${validPath}`\n    proxyModuleUrl = wrapId(proxyModulePath)\n  }\n  proxyModuleUrl = joinUrlSegments(decodedBase, proxyModuleUrl)\n\n  const s = new MagicString(html)\n  let inlineModuleIndex = -1\n  // The key to the proxyHtml cache is decoded, as it will be compared\n  // against decoded URLs by the HTML plugins.\n  const proxyCacheUrl = decodeURI(\n    cleanUrl(proxyModulePath).replace(normalizePath(config.root), ''),\n  )\n  const styleUrl: AssetNode[] = []\n  const inlineStyles: InlineStyleAttribute[] = []\n  const inlineModulePaths: string[] = []\n\n  const addInlineModule = (\n    node: DefaultTreeAdapterMap['element'],\n    ext: 'js',\n  ) => {\n    inlineModuleIndex++\n\n    const contentNode = node.childNodes[0] as DefaultTreeAdapterMap['textNode']\n\n    const code = contentNode.value\n\n    let map: SourceMapInput | undefined\n    if (proxyModulePath[0] !== '\\0') {\n      map = new MagicString(html)\n        .snip(\n          contentNode.sourceCodeLocation!.startOffset,\n          contentNode.sourceCodeLocation!.endOffset,\n        )\n        .generateMap({ hires: 'boundary' })\n      map.sources = [filename]\n      map.file = filename\n    }\n\n    // add HTML Proxy to Map\n    addToHTMLProxyCache(config, proxyCacheUrl, inlineModuleIndex, { code, map })\n\n    // inline js module. convert to src=\"proxy\" (dev only, base is never relative)\n    const modulePath = `${proxyModuleUrl}?html-proxy&index=${inlineModuleIndex}.${ext}`\n    inlineModulePaths.push(modulePath)\n\n    s.update(\n      node.sourceCodeLocation!.startOffset,\n      node.sourceCodeLocation!.endOffset,\n      `<script type=\"module\" src=\"${modulePath}\"></script>`,\n    )\n    preTransformRequest(server!, modulePath, decodedBase)\n  }\n\n  await traverseHtml(html, filename, config.logger.warn, (node) => {\n    if (!nodeIsElement(node)) {\n      return\n    }\n\n    // script tags\n    if (node.nodeName === 'script') {\n      const { src, srcSourceCodeLocation, isModule, isIgnored } =\n        getScriptInfo(node)\n\n      if (isIgnored) {\n        removeViteIgnoreAttr(s, node.sourceCodeLocation!)\n      } else if (src) {\n        const processedUrl = processNodeUrl(\n          src.value,\n          /* useSrcSetReplacer */ false,\n          config,\n          htmlPath,\n          originalUrl,\n          server,\n          !isModule,\n        )\n        if (processedUrl !== src.value) {\n          overwriteAttrValue(s, srcSourceCodeLocation!, processedUrl)\n        }\n      } else if (isModule && node.childNodes.length) {\n        addInlineModule(node, 'js')\n      } else if (node.childNodes.length) {\n        const scriptNode = node.childNodes[\n          node.childNodes.length - 1\n        ] as DefaultTreeAdapterMap['textNode']\n        for (const {\n          url,\n          start,\n          end,\n        } of extractImportExpressionFromClassicScript(scriptNode)) {\n          const processedUrl = processNodeUrl(\n            url,\n            false,\n            config,\n            htmlPath,\n            originalUrl,\n          )\n          if (processedUrl !== url) {\n            s.update(start, end, processedUrl)\n          }\n        }\n      }\n    }\n\n    const inlineStyle = findNeedTransformStyleAttribute(node)\n    if (inlineStyle) {\n      inlineModuleIndex++\n      inlineStyles.push({\n        index: inlineModuleIndex,\n        location: inlineStyle.location!,\n        code: inlineStyle.attr.value,\n      })\n    }\n\n    if (node.nodeName === 'style' && node.childNodes.length) {\n      const children = node.childNodes[0] as DefaultTreeAdapterMap['textNode']\n      styleUrl.push({\n        start: children.sourceCodeLocation!.startOffset,\n        end: children.sourceCodeLocation!.endOffset,\n        code: children.value,\n      })\n    }\n\n    // elements with [href/src] attrs\n    const assetAttributes = getNodeAssetAttributes(node)\n    for (const attr of assetAttributes) {\n      if (attr.type === 'remove') {\n        s.remove(attr.location.startOffset, attr.location.endOffset)\n      } else {\n        const processedUrl = processNodeUrl(\n          attr.value,\n          attr.type === 'srcset',\n          config,\n          htmlPath,\n          originalUrl,\n        )\n        if (processedUrl !== attr.value) {\n          overwriteAttrValue(s, attr.location, processedUrl)\n        }\n      }\n    }\n  })\n\n  // invalidate the module so the newly cached contents will be served\n  const clientModuleGraph = server?.environments.client.moduleGraph\n  if (clientModuleGraph) {\n    await Promise.all(\n      inlineModulePaths.map(async (url) => {\n        const module = await clientModuleGraph.getModuleByUrl(url)\n        if (module) {\n          clientModuleGraph.invalidateModule(module)\n        }\n      }),\n    )\n  }\n\n  await Promise.all([\n    ...styleUrl.map(async ({ start, end, code }, index) => {\n      const url = `${proxyModulePath}?html-proxy&direct&index=${index}.css`\n\n      // ensure module in graph after successful load\n      const mod =\n        await server!.environments.client.moduleGraph.ensureEntryFromUrl(\n          url,\n          false,\n        )\n      ensureWatchedFile(watcher, mod.file, config.root)\n\n      const result =\n        await server!.environments.client.pluginContainer.transform(\n          code,\n          mod.id!,\n        )\n      let content = ''\n      if (result.map && 'version' in result.map) {\n        if (result.map.mappings) {\n          await injectSourcesContent(result.map, proxyModulePath, config.logger)\n        }\n        content = getCodeWithSourcemap('css', result.code, result.map)\n      } else {\n        content = result.code\n      }\n      s.overwrite(start, end, content)\n    }),\n    ...inlineStyles.map(async ({ index, location, code }) => {\n      // will transform with css plugin and cache result with css-post plugin\n      const url = `${proxyModulePath}?html-proxy&inline-css&style-attr&index=${index}.css`\n\n      const mod =\n        await server!.environments.client.moduleGraph.ensureEntryFromUrl(\n          url,\n          false,\n        )\n      ensureWatchedFile(watcher, mod.file, config.root)\n\n      await server?.environments.client.pluginContainer.transform(code, mod.id!)\n\n      const hash = getHash(cleanUrl(mod.id!))\n      const result = htmlProxyResult.get(`${hash}_${index}`)\n      overwriteAttrValue(s, location, result ?? '')\n    }),\n  ])\n\n  html = s.toString()\n\n  return {\n    html,\n    tags: [\n      {\n        tag: 'script',\n        attrs: {\n          type: 'module',\n          src: path.posix.join(base, CLIENT_PUBLIC_PATH),\n        },\n        injectTo: 'head-prepend',\n      },\n    ],\n  }\n}\n\nexport function indexHtmlMiddleware(\n  root: string,\n  server: ViteDevServer | PreviewServer,\n): Connect.NextHandleFunction {\n  const isDev = isDevServer(server)\n  const fullBundleEnv =\n    isDev && server.environments.client instanceof FullBundleDevEnvironment\n      ? server.environments.client\n      : undefined\n\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return async function viteIndexHtmlMiddleware(req, res, next) {\n    if (res.writableEnded) {\n      return next()\n    }\n\n    const url = req.url && cleanUrl(req.url)\n    // htmlFallbackMiddleware appends '.html' to URLs\n    if (url?.endsWith('.html') && req.headers['sec-fetch-dest'] !== 'script') {\n      if (fullBundleEnv) {\n        const pathname = decodeURIComponent(url)\n        const filePath = pathname.slice(1) // remove first /\n\n        let file = fullBundleEnv.memoryFiles.get(filePath)\n        if (!file && fullBundleEnv.memoryFiles.size !== 0) {\n          return next()\n        }\n        const secFetchDest = req.headers['sec-fetch-dest']\n        if (\n          [\n            'document',\n            'iframe',\n            'frame',\n            'fencedframe',\n            '',\n            undefined,\n          ].includes(secFetchDest) &&\n          ((await fullBundleEnv.triggerBundleRegenerationIfStale()) ||\n            file === undefined)\n        ) {\n          file = { source: await generateFallbackHtml(server as ViteDevServer) }\n        }\n        if (!file) {\n          return next()\n        }\n\n        const html =\n          typeof file.source === 'string'\n            ? file.source\n            : Buffer.from(file.source)\n        const headers = isDev\n          ? server.config.server.headers\n          : server.config.preview.headers\n        return send(req, res, html, 'html', { headers, etag: file.etag })\n      }\n\n      let filePath: string\n      if (isDev && url.startsWith(FS_PREFIX)) {\n        filePath = decodeURIComponent(fsPathFromId(url))\n      } else {\n        filePath = normalizePath(\n          path.resolve(path.join(root, decodeURIComponent(url))),\n        )\n      }\n\n      if (isDev) {\n        const servingAccessResult = checkLoadingAccess(server.config, filePath)\n        if (servingAccessResult === 'denied') {\n          return respondWithAccessDenied(filePath, server, res)\n        }\n        if (servingAccessResult === 'fallback') {\n          return next()\n        }\n        servingAccessResult satisfies 'allowed'\n      } else {\n        // `server.fs` options does not apply to the preview server.\n        // But we should disallow serving files outside the output directory.\n        if (!isParentDirectory(root, filePath)) {\n          return next()\n        }\n      }\n\n      if (fs.existsSync(filePath)) {\n        const headers = isDev\n          ? server.config.server.headers\n          : server.config.preview.headers\n\n        try {\n          let html = await fsp.readFile(filePath, 'utf-8')\n          if (isDev) {\n            html = await server.transformIndexHtml(url, html, req.originalUrl)\n          }\n          return send(req, res, html, 'html', { headers })\n        } catch (e) {\n          return next(e)\n        }\n      }\n    }\n    next()\n  }\n}\n\n// NOTE: We usually don't prefix `url` and `base` with `decoded`, but in this file particularly\n// we're dealing with mixed encoded/decoded paths often, so we make this explicit for now.\nfunction preTransformRequest(\n  server: ViteDevServer,\n  decodedUrl: string,\n  decodedBase: string,\n) {\n  if (!server.config.server.preTransformRequests) return\n\n  // transform all url as non-ssr as html includes client-side assets only\n  decodedUrl = unwrapId(stripBase(decodedUrl, decodedBase))\n  server.warmupRequest(decodedUrl)\n}\n\nasync function generateFallbackHtml(server: ViteDevServer) {\n  const hmrRuntime = await getHmrImplementation(server.config)\n  return /* html */ `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <script type=\"module\">\n    ${hmrRuntime.replaceAll('</script>', '<\\\\/script>')}\n  </script>\n  <style>\n    :root {\n      --page-bg: #ffffff;\n      --text-color: #1d1d1f;\n      --spinner-track: #f5f5f7;\n      --spinner-accent: #0071e3;\n    }\n    @media (prefers-color-scheme: dark) {\n      :root {\n        --page-bg: #1e1e1e;\n        --text-color: #f5f5f5;\n        --spinner-track: #424242;\n      }\n    }\n\n    body {\n      margin: 0;\n      min-height: 100vh;\n      display: flex;\n      background-color: var(--page-bg);\n      color: var(--text-color);\n    }\n\n    .container {\n      margin: auto;\n      padding: 2rem;\n      text-align: center;\n      border-radius: 1rem;\n    }\n\n    .spinner {\n      width: 3rem;\n      height: 3rem;\n      margin: 2rem auto;\n      border: 3px solid var(--spinner-track);\n      border-top-color: var(--spinner-accent);\n      border-radius: 50%;\n      animation: spin 1s linear infinite;\n    }\n\n    @keyframes spin { to { transform: rotate(360deg) } }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <h1>Bundling in progress</h1>\n    <p>The page will automatically reload when ready.</p>\n    <div class=\"spinner\"></div>\n  </div>\n</body>\n</html>\n`\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/memoryFiles.ts",
    "content": "import * as mrmime from 'mrmime'\nimport type { Connect } from '#dep-types/connect'\nimport { cleanUrl } from '../../../shared/utils'\nimport type { ViteDevServer } from '..'\nimport { FullBundleDevEnvironment } from '../environments/fullBundleEnvironment'\n\nexport function memoryFilesMiddleware(\n  server: ViteDevServer,\n): Connect.NextHandleFunction {\n  const memoryFiles =\n    server.environments.client instanceof FullBundleDevEnvironment\n      ? server.environments.client.memoryFiles\n      : undefined\n  if (!memoryFiles) {\n    throw new Error('memoryFilesMiddleware can only be used for fullBundleMode')\n  }\n  const headers = server.config.server.headers\n\n  return function viteMemoryFilesMiddleware(req, res, next) {\n    const cleanedUrl = cleanUrl(req.url!)\n    if (cleanedUrl.endsWith('.html')) {\n      return next()\n    }\n\n    const pathname = decodeURIComponent(cleanedUrl)\n    const filePath = pathname.slice(1) // remove first /\n\n    const file = memoryFiles.get(filePath)\n    if (file) {\n      if (file.etag) {\n        if (req.headers['if-none-match'] === file.etag) {\n          res.statusCode = 304\n          res.end()\n          return\n        }\n        res.setHeader('Etag', file.etag)\n      }\n\n      const mime = mrmime.lookup(filePath)\n      if (mime) {\n        res.setHeader('Content-Type', mime)\n      }\n\n      for (const name in headers) {\n        res.setHeader(name, headers[name]!)\n      }\n\n      return res.end(file.source)\n    }\n    next()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/notFound.ts",
    "content": "import type { Connect } from '#dep-types/connect'\n\nexport function notFoundMiddleware(): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function vite404Middleware(_, res) {\n    res.statusCode = 404\n    res.end()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/proxy.ts",
    "content": "import type * as http from 'node:http'\nimport * as httpProxy from 'http-proxy-3'\nimport colors from 'picocolors'\nimport type { Connect } from '#dep-types/connect'\nimport { createDebugger } from '../../utils'\nimport type { CommonServerOptions, ResolvedConfig } from '../..'\nimport type { HttpServer } from '..'\n\nconst debug = createDebugger('vite:proxy')\n\nexport interface ProxyOptions extends httpProxy.ServerOptions {\n  /**\n   * rewrite path\n   */\n  rewrite?: (path: string) => string\n  /**\n   * configure the proxy server (e.g. listen to events)\n   */\n  configure?: (proxy: httpProxy.ProxyServer, options: ProxyOptions) => void\n  /**\n   * webpack-dev-server style bypass function\n   */\n  bypass?: (\n    req: http.IncomingMessage,\n    /** undefined for WebSocket upgrade requests */\n    res: http.ServerResponse | undefined,\n    options: ProxyOptions,\n  ) =>\n    | void\n    | null\n    | undefined\n    | false\n    | string\n    | Promise<void | null | undefined | boolean | string>\n  /**\n   * rewrite the Origin header of a WebSocket request to match the target\n   *\n   * **Exercise caution as rewriting the Origin can leave the proxying open to [CSRF attacks](https://owasp.org/www-community/attacks/csrf).**\n   */\n  rewriteWsOrigin?: boolean | undefined\n}\n\nconst rewriteOriginHeader = (\n  proxyReq: http.ClientRequest,\n  options: ProxyOptions,\n  config: ResolvedConfig,\n) => {\n  // Browsers may send Origin headers even with same-origin\n  // requests. It is common for WebSocket servers to check the Origin\n  // header, so if rewriteWsOrigin is true we change the Origin to match\n  // the target URL.\n  if (options.rewriteWsOrigin) {\n    const { target } = options\n\n    if (proxyReq.headersSent) {\n      config.logger.warn(\n        colors.yellow(\n          `Unable to rewrite Origin header as headers are already sent.`,\n        ),\n      )\n      return\n    }\n\n    if (proxyReq.getHeader('origin') && target) {\n      const changedOrigin =\n        typeof target === 'object'\n          ? `${target.protocol ?? 'http:'}//${target.host}`\n          : target\n\n      proxyReq.setHeader('origin', changedOrigin)\n    }\n  }\n}\n\nexport function proxyMiddleware(\n  httpServer: HttpServer | null,\n  options: NonNullable<CommonServerOptions['proxy']>,\n  config: ResolvedConfig,\n): Connect.NextHandleFunction {\n  // lazy require only when proxy is used\n  const proxies: Record<string, [httpProxy.ProxyServer, ProxyOptions]> = {}\n\n  Object.keys(options).forEach((context) => {\n    let opts = options[context]\n    if (!opts) {\n      return\n    }\n    if (typeof opts === 'string') {\n      opts = { target: opts, changeOrigin: true }\n    }\n    const proxy = httpProxy.createProxyServer(opts)\n\n    if (opts.configure) {\n      opts.configure(proxy, opts)\n    }\n\n    proxy.on('error', (err, _req, res) => {\n      // When it is ws proxy, res is net.Socket\n      if ('req' in res) {\n        config.logger.error(\n          `${colors.red(`http proxy error: ${res.req.url}`)}\\n${err.stack}`,\n          {\n            timestamp: true,\n            error: err,\n          },\n        )\n        if (!res.headersSent && !res.writableEnded) {\n          res\n            .writeHead(502, {\n              'Content-Type': 'text/plain',\n            })\n            .end()\n        }\n      } else {\n        config.logger.error(`${colors.red(`ws proxy error:`)}\\n${err.stack}`, {\n          timestamp: true,\n          error: err,\n        })\n        res.end()\n      }\n    })\n\n    proxy.on('proxyReqWs', (proxyReq, _req, socket, options) => {\n      rewriteOriginHeader(proxyReq, options, config)\n\n      socket.on('error', (err) => {\n        config.logger.error(\n          `${colors.red(`ws proxy socket error:`)}\\n${err.stack}`,\n          {\n            timestamp: true,\n            error: err,\n          },\n        )\n      })\n    })\n\n    // clone before saving because http-proxy mutates the options\n    proxies[context] = [proxy, { ...opts }]\n  })\n\n  if (httpServer) {\n    httpServer.on('upgrade', async (req, socket, head) => {\n      const url = req.url!\n      for (const context in proxies) {\n        if (doesProxyContextMatchUrl(context, url)) {\n          const [proxy, opts] = proxies[context]\n          if (\n            opts.ws ||\n            opts.target?.toString().startsWith('ws:') ||\n            opts.target?.toString().startsWith('wss:')\n          ) {\n            if (opts.bypass) {\n              try {\n                const bypassResult = await opts.bypass(req, undefined, opts)\n                if (typeof bypassResult === 'string') {\n                  debug?.(`bypass: ${req.url} -> ${bypassResult}`)\n                  req.url = bypassResult\n                  return\n                }\n                if (bypassResult === false) {\n                  debug?.(`bypass: ${req.url} -> 404`)\n                  socket.end('HTTP/1.1 404 Not Found\\r\\n\\r\\n', '')\n                  return\n                }\n              } catch (err) {\n                config.logger.error(\n                  `${colors.red(`ws proxy bypass error:`)}\\n${err.stack}`,\n                  {\n                    timestamp: true,\n                    error: err,\n                  },\n                )\n                return\n              }\n            }\n\n            if (opts.rewrite) {\n              req.url = opts.rewrite(url)\n            }\n            debug?.(`${req.url} -> ws ${opts.target}`)\n            proxy.ws(req, socket, head)\n            return\n          }\n        }\n      }\n    })\n  }\n\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return async function viteProxyMiddleware(req, res, next) {\n    const url = req.url!\n    for (const context in proxies) {\n      if (doesProxyContextMatchUrl(context, url)) {\n        const [proxy, opts] = proxies[context]\n        const options: httpProxy.ServerOptions = {}\n\n        if (opts.bypass) {\n          try {\n            const bypassResult = await opts.bypass(req, res, opts)\n            if (typeof bypassResult === 'string') {\n              debug?.(`bypass: ${req.url} -> ${bypassResult}`)\n              req.url = bypassResult\n              if (res.writableEnded) {\n                return\n              }\n              return next()\n            }\n            if (bypassResult === false) {\n              debug?.(`bypass: ${req.url} -> 404`)\n              res.statusCode = 404\n              return res.end()\n            }\n          } catch (e) {\n            debug?.(`bypass: ${req.url} -> ${e}`)\n            return next(e)\n          }\n        }\n\n        debug?.(`${req.url} -> ${opts.target || opts.forward}`)\n        if (opts.rewrite) {\n          req.url = opts.rewrite(req.url!)\n        }\n        proxy.web(req, res, options)\n        return\n      }\n    }\n    next()\n  }\n}\n\nfunction doesProxyContextMatchUrl(context: string, url: string): boolean {\n  return (\n    (context[0] === '^' && new RegExp(context).test(url)) ||\n    url.startsWith(context)\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/rejectInvalidRequest.ts",
    "content": "import type { Connect } from '#dep-types/connect'\n\n/**\n * disallows request that contains `#` in the URL\n */\nexport function rejectInvalidRequestMiddleware(): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteRejectInvalidRequestMiddleware(req, res, next) {\n    // HTTP spec does not allow `#` in the request-target\n    // (HTTP 1.1: https://datatracker.ietf.org/doc/html/rfc9112#section-3.2)\n    // (HTTP 2: https://datatracker.ietf.org/doc/html/rfc9113#section-8.3.1-2.4.1)\n    // But Node.js allows those requests.\n    // Our middlewares don't expect `#` to be included in `req.url`, especially the `server.fs.deny` checks.\n    if (req.url?.includes('#')) {\n      // HTTP 1.1 spec recommends sending 400 Bad Request\n      // (https://datatracker.ietf.org/doc/html/rfc9112#section-3.2-4)\n      res.writeHead(400)\n      res.end()\n      return\n    }\n    return next()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/rejectNoCorsRequest.ts",
    "content": "import type { Connect } from '#dep-types/connect'\n\n/**\n * A middleware that rejects no-cors mode requests that are not same-origin.\n *\n * We should avoid untrusted sites to load the script to avoid attacks like GHSA-4v9v-hfq4-rm2v.\n * This is because:\n * - the path of HMR patch files / entry point files can be predictable\n * - the HMR patch files may not include ESM syntax\n *   (if they include ESM syntax, loading as a classic script would fail)\n * - the HMR runtime in the browser has the list of all loaded modules\n *\n * https://github.com/webpack/webpack-dev-server/security/advisories/GHSA-4v9v-hfq4-rm2v\n * https://green.sapphi.red/blog/local-server-security-best-practices#_2-using-xssi-and-modifying-the-prototype\n * https://green.sapphi.red/blog/local-server-security-best-practices#properly-check-the-request-origin\n */\nexport function rejectNoCorsRequestMiddleware(): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteRejectNoCorsRequestMiddleware(req, res, next) {\n    // While we can set Cross-Origin-Resource-Policy header instead of rejecting requests,\n    // we choose to reject the request to be safer in case the request handler has any side-effects.\n    if (\n      req.headers['sec-fetch-mode'] === 'no-cors' &&\n      req.headers['sec-fetch-site'] !== 'same-origin' &&\n      // we only need to block classic script requests\n      req.headers['sec-fetch-dest'] === 'script'\n    ) {\n      // Send a JavaScript code instead of 403 so that the error is shown in the devtools\n      // If we send 403, the browser will avoid loading the body of the response\n      // and just show \"Failed to load\" error without the detailed message.\n      res.setHeader('Content-Type', 'text/javascript')\n      res.end(\n        `throw new Error(${JSON.stringify(\n          '[Vite] Cross-origin requests for classic scripts must be made with CORS mode enabled.' +\n            ' Make sure to set the \"crossorigin\" attribute on your <script> tag.',\n        )});`,\n      )\n      return\n    }\n    return next()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/static.ts",
    "content": "import path from 'node:path'\nimport type { OutgoingHttpHeaders, ServerResponse } from 'node:http'\nimport type { Options } from 'sirv'\nimport sirv from 'sirv'\nimport escapeHtml from 'escape-html'\nimport type { Connect } from '#dep-types/connect'\nimport type { ViteDevServer } from '../../server'\nimport type { ResolvedConfig } from '../../config'\nimport { FS_PREFIX } from '../../constants'\nimport {\n  decodeURIIfPossible,\n  fsPathFromUrl,\n  isFileReadable,\n  isImportRequest,\n  isInternalRequest,\n  isParentDirectory,\n  isSameFilePath,\n  normalizePath,\n  removeLeadingSlash,\n  urlRE,\n} from '../../utils'\nimport {\n  cleanUrl,\n  isWindows,\n  slash,\n  withTrailingSlash,\n} from '../../../shared/utils'\n\nconst knownJavascriptExtensionRE = /\\.(?:[tj]sx?|[cm][tj]s)$/\nconst ERR_DENIED_FILE = 'ERR_DENIED_FILE'\n\nconst sirvOptions = ({\n  config,\n  getHeaders,\n  disableFsServeCheck,\n}: {\n  config: ResolvedConfig\n  getHeaders: () => OutgoingHttpHeaders | undefined\n  disableFsServeCheck?: boolean\n}): Options => {\n  return {\n    dev: true,\n    etag: true,\n    extensions: [],\n    setHeaders(res, pathname) {\n      // Matches js, jsx, ts, tsx, mts, mjs, cjs, cts, ctx, mtx\n      // The reason this is done, is that the .ts and .mts file extensions are\n      // reserved for the MIME type video/mp2t. In almost all cases, we can expect\n      // these files to be TypeScript files, and for Vite to serve them with\n      // this Content-Type.\n      if (knownJavascriptExtensionRE.test(pathname)) {\n        res.setHeader('Content-Type', 'text/javascript')\n      }\n      const headers = getHeaders()\n      if (headers) {\n        for (const name in headers) {\n          res.setHeader(name, headers[name]!)\n        }\n      }\n    },\n    shouldServe: disableFsServeCheck\n      ? undefined\n      : (filePath) => {\n          const servingAccessResult = checkLoadingAccess(config, filePath)\n          if (servingAccessResult === 'denied') {\n            const error: any = new Error('denied access')\n            error.code = ERR_DENIED_FILE\n            error.path = filePath\n            throw error\n          }\n          if (servingAccessResult === 'fallback') {\n            return false\n          }\n          servingAccessResult satisfies 'allowed'\n          return true\n        },\n  }\n}\n\nexport function servePublicMiddleware(\n  server: ViteDevServer,\n  publicFiles?: Set<string>,\n): Connect.NextHandleFunction {\n  const dir = server.config.publicDir\n  const serve = sirv(\n    dir,\n    sirvOptions({\n      config: server.config,\n      getHeaders: () => server.config.server.headers,\n      disableFsServeCheck: true,\n    }),\n  )\n\n  const toFilePath = (url: string) => {\n    let filePath = cleanUrl(url)\n    if (filePath.indexOf('%') !== -1) {\n      try {\n        filePath = decodeURI(filePath)\n      } catch {\n        /* malform uri */\n      }\n    }\n    return normalizePath(filePath)\n  }\n\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteServePublicMiddleware(req, res, next) {\n    // To avoid the performance impact of `existsSync` on every request, we check against an\n    // in-memory set of known public files. This set is updated on restarts.\n    // also skip import request and internal requests `/@fs/ /@vite-client` etc...\n    if (\n      (publicFiles && !publicFiles.has(toFilePath(req.url!))) ||\n      isImportRequest(req.url!) ||\n      isInternalRequest(req.url!) ||\n      // for `/public-file.js?url` to be transformed\n      urlRE.test(req.url!)\n    ) {\n      return next()\n    }\n    serve(req, res, next)\n  }\n}\n\nexport function serveStaticMiddleware(\n  server: ViteDevServer,\n): Connect.NextHandleFunction {\n  const dir = server.config.root\n  const serve = sirv(\n    dir,\n    sirvOptions({\n      config: server.config,\n      getHeaders: () => server.config.server.headers,\n    }),\n  )\n\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteServeStaticMiddleware(req, res, next) {\n    // only serve the file if it's not an html request or ends with `/`\n    // so that html requests can fallthrough to our html middleware for\n    // special processing\n    // also skip internal requests `/@fs/ /@vite-client` etc...\n    const cleanedUrl = cleanUrl(req.url!)\n    if (\n      cleanedUrl.endsWith('/') ||\n      path.extname(cleanedUrl) === '.html' ||\n      isInternalRequest(req.url!) ||\n      // skip url starting with // as these will be interpreted as\n      // scheme relative URLs by new URL() and will not be a valid file path\n      req.url?.startsWith('//')\n    ) {\n      return next()\n    }\n\n    const url = new URL(req.url!, 'http://example.com')\n    const pathname = decodeURIIfPossible(url.pathname)\n    if (pathname === undefined) {\n      return next()\n    }\n\n    // apply aliases to static requests as well\n    let redirectedPathname: string | undefined\n    for (const { find, replacement } of server.config.resolve.alias) {\n      const matches =\n        typeof find === 'string'\n          ? pathname.startsWith(find)\n          : find.test(pathname)\n      if (matches) {\n        redirectedPathname = pathname.replace(find, replacement)\n        break\n      }\n    }\n    if (redirectedPathname) {\n      // dir is pre-normalized to posix style\n      if (redirectedPathname.startsWith(withTrailingSlash(dir))) {\n        redirectedPathname = redirectedPathname.slice(dir.length)\n      }\n    }\n\n    const resolvedPathname = redirectedPathname || pathname\n    let fileUrl = path.resolve(dir, removeLeadingSlash(resolvedPathname))\n    if (resolvedPathname.endsWith('/') && fileUrl[fileUrl.length - 1] !== '/') {\n      fileUrl = withTrailingSlash(fileUrl)\n    }\n    if (redirectedPathname) {\n      url.pathname = encodeURI(redirectedPathname)\n      req.url = url.href.slice(url.origin.length)\n    }\n\n    try {\n      serve(req, res, next)\n    } catch (e) {\n      if (e && 'code' in e && e.code === ERR_DENIED_FILE) {\n        respondWithAccessDenied(e.path, server, res)\n        return\n      }\n      throw e\n    }\n  }\n}\n\nexport function serveRawFsMiddleware(\n  server: ViteDevServer,\n): Connect.NextHandleFunction {\n  const serveFromRoot = sirv(\n    '/',\n    sirvOptions({\n      config: server.config,\n      getHeaders: () => server.config.server.headers,\n    }),\n  )\n\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteServeRawFsMiddleware(req, res, next) {\n    // In some cases (e.g. linked monorepos) files outside of root will\n    // reference assets that are also out of served root. In such cases\n    // the paths are rewritten to `/@fs/` prefixed paths and must be served by\n    // searching based from fs root.\n    if (req.url!.startsWith(FS_PREFIX)) {\n      const url = new URL(req.url!, 'http://example.com')\n      const pathname = decodeURIIfPossible(url.pathname)\n      if (pathname === undefined) {\n        return next()\n      }\n\n      let newPathname = pathname.slice(FS_PREFIX.length)\n      if (isWindows) newPathname = newPathname.replace(/^[A-Z]:/i, '')\n      url.pathname = encodeURI(newPathname)\n      req.url = url.href.slice(url.origin.length)\n\n      try {\n        serveFromRoot(req, res, next)\n      } catch (e) {\n        if (e && 'code' in e && e.code === ERR_DENIED_FILE) {\n          respondWithAccessDenied(e.path, server, res)\n          return\n        }\n        throw e\n      }\n    } else {\n      next()\n    }\n  }\n}\n\n/**\n * Check if the url is allowed to be served, via the `server.fs` config.\n * @deprecated Use the `isFileLoadingAllowed` function instead.\n */\nexport function isFileServingAllowed(\n  config: ResolvedConfig,\n  url: string,\n): boolean\nexport function isFileServingAllowed(\n  url: string,\n  server: ViteDevServer,\n): boolean\nexport function isFileServingAllowed(\n  configOrUrl: ResolvedConfig | string,\n  urlOrServer: string | ViteDevServer,\n): boolean {\n  const config = (\n    typeof urlOrServer === 'string' ? configOrUrl : urlOrServer.config\n  ) as ResolvedConfig\n  const url = (\n    typeof urlOrServer === 'string' ? urlOrServer : configOrUrl\n  ) as string\n\n  if (!config.server.fs.strict) return true\n  const filePath = fsPathFromUrl(url)\n  return isFileLoadingAllowed(config, filePath)\n}\n\n/**\n * Warning: parameters are not validated, only works with normalized absolute paths\n *\n * @param targetPath - normalized absolute path\n * @param filePath - normalized absolute path\n */\nexport function isFileInTargetPath(\n  targetPath: string,\n  filePath: string,\n): boolean {\n  return (\n    isSameFilePath(targetPath, filePath) ||\n    isParentDirectory(targetPath, filePath)\n  )\n}\n\n/**\n * Warning: parameters are not validated, only works with normalized absolute paths\n */\nexport function isFileLoadingAllowed(\n  config: ResolvedConfig,\n  filePath: string,\n): boolean {\n  const { fs } = config.server\n\n  if (!fs.strict) return true\n\n  // NOTE: `fs.readFile('/foo.png/')` tries to load `'/foo.png'`\n  // so we should check the path without trailing slash\n  const filePathWithoutTrailingSlash = filePath.endsWith('/')\n    ? filePath.slice(0, -1)\n    : filePath\n  if (config.fsDenyGlob(filePathWithoutTrailingSlash)) return false\n\n  if (config.safeModulePaths.has(filePath)) return true\n\n  if (fs.allow.some((uri) => isFileInTargetPath(uri, filePath))) return true\n\n  return false\n}\n\nexport function checkLoadingAccess(\n  config: ResolvedConfig,\n  path: string,\n): 'allowed' | 'denied' | 'fallback' {\n  if (isFileLoadingAllowed(config, slash(path))) {\n    return 'allowed'\n  }\n  if (isFileReadable(path)) {\n    return 'denied'\n  }\n  // if the file doesn't exist, we shouldn't restrict this path as it can\n  // be an API call. Middlewares would issue a 404 if the file isn't handled\n  return 'fallback'\n}\n\nexport function respondWithAccessDenied(\n  id: string,\n  server: ViteDevServer,\n  res: ServerResponse,\n): void {\n  const urlMessage = `The request id \"${id}\" is outside of Vite serving allow list.`\n  const hintMessage = `\n${server.config.server.fs.allow.map((i) => `- ${i}`).join('\\n')}\n\nRefer to docs https://vite.dev/config/server-options.html#server-fs-allow for configurations and more details.`\n\n  server.config.logger.error(urlMessage)\n  server.config.logger.warnOnce(hintMessage + '\\n')\n  res.statusCode = 403\n  res.write(renderRestrictedErrorHTML(urlMessage + '\\n' + hintMessage))\n  res.end()\n}\n\nfunction renderRestrictedErrorHTML(msg: string): string {\n  // to have syntax highlighting and autocompletion in IDE\n  const html = String.raw\n  return html`\n    <body>\n      <h1>403 Restricted</h1>\n      <p>${escapeHtml(msg).replace(/\\n/g, '<br/>')}</p>\n      <style>\n        body {\n          padding: 1em 2em;\n        }\n      </style>\n    </body>\n  `\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/time.ts",
    "content": "import { performance } from 'node:perf_hooks'\nimport type { Connect } from '#dep-types/connect'\nimport { createDebugger, prettifyUrl, timeFrom } from '../../utils'\n\nconst logTime = createDebugger('vite:time')\n\nexport function timeMiddleware(root: string): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteTimeMiddleware(req, res, next) {\n    const start = performance.now()\n    const end = res.end\n    res.end = (...args: readonly [any, any?, any?]) => {\n      logTime?.(`${timeFrom(start)} ${prettifyUrl(req.url!, root)}`)\n      return end.call(res, ...args)\n    }\n    next()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/middlewares/transform.ts",
    "content": "import path from 'node:path'\nimport fsp from 'node:fs/promises'\nimport colors from 'picocolors'\nimport type { ExistingRawSourceMap } from 'rolldown'\nimport type { Connect } from '#dep-types/connect'\nimport type { ViteDevServer } from '..'\nimport {\n  createDebugger,\n  fsPathFromId,\n  injectQuery,\n  isCSSRequest,\n  isImportRequest,\n  isJSRequest,\n  normalizePath,\n  prettifyUrl,\n  removeImportQuery,\n  removeTimestampQuery,\n} from '../../utils'\nimport { send } from '../send'\nimport { ERR_DENIED_ID, ERR_LOAD_URL } from '../transformRequest'\nimport { applySourcemapIgnoreList } from '../sourcemap'\nimport { isHTMLProxy } from '../../plugins/html'\nimport {\n  DEP_VERSION_RE,\n  ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR,\n  ERR_OPTIMIZE_DEPS_PROCESSING_ERROR,\n  FS_PREFIX,\n} from '../../constants'\nimport { isDirectCSSRequest, isDirectRequest } from '../../plugins/css'\nimport { ERR_CLOSED_SERVER } from '../pluginContainer'\nimport { cleanUrl, unwrapId, withTrailingSlash } from '../../../shared/utils'\nimport {\n  ERR_OUTDATED_OPTIMIZED_DEP,\n  NULL_BYTE_PLACEHOLDER,\n} from '../../../shared/constants'\nimport type { ResolvedConfig } from '../../config'\nimport { checkLoadingAccess, respondWithAccessDenied } from './static'\n\nconst debugCache = createDebugger('vite:cache')\n\nconst knownIgnoreList = new Set(['/', '/favicon.ico'])\n\nconst documentFetchDests = new Set([\n  'document',\n  'iframe',\n  'frame',\n  'fencedframe',\n])\nfunction isDocumentFetchDest(req: Connect.IncomingMessage) {\n  const fetchDest = req.headers['sec-fetch-dest']\n  return fetchDest !== undefined && documentFetchDests.has(fetchDest)\n}\n\n// TODO: consolidate this regex pattern with the url, raw, and inline checks in plugins\nconst urlRE = /[?&]url\\b/\nconst rawRE = /[?&]raw\\b/\nconst inlineRE = /[?&]inline\\b/\nconst svgRE = /\\.svg\\b/\n\nfunction isServerAccessDeniedForTransform(config: ResolvedConfig, id: string) {\n  if (rawRE.test(id) || urlRE.test(id) || inlineRE.test(id) || svgRE.test(id)) {\n    return checkLoadingAccess(config, id) !== 'allowed'\n  }\n  return false\n}\n\n/**\n * A middleware that short-circuits the middleware chain to serve cached transformed modules\n */\nexport function cachedTransformMiddleware(\n  server: ViteDevServer,\n): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n  return function viteCachedTransformMiddleware(req, res, next) {\n    const environment = server.environments.client\n\n    if (isDocumentFetchDest(req)) {\n      res.appendHeader('Vary', 'Sec-Fetch-Dest')\n      return next()\n    }\n\n    // check if we can return 304 early\n    const ifNoneMatch = req.headers['if-none-match']\n    if (ifNoneMatch) {\n      const moduleByEtag = environment.moduleGraph.getModuleByEtag(ifNoneMatch)\n      if (\n        moduleByEtag?.transformResult?.etag === ifNoneMatch &&\n        moduleByEtag.url === req.url\n      ) {\n        // For CSS requests, if the same CSS file is imported in a module,\n        // the browser sends the request for the direct CSS request with the etag\n        // from the imported CSS module. We ignore the etag in this case.\n        const maybeMixedEtag = isCSSRequest(req.url!)\n        if (!maybeMixedEtag) {\n          debugCache?.(`[304] ${prettifyUrl(req.url!, server.config.root)}`)\n          res.statusCode = 304\n          return res.end()\n        }\n      }\n    }\n\n    next()\n  }\n}\n\nexport function transformMiddleware(\n  server: ViteDevServer,\n): Connect.NextHandleFunction {\n  // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...`\n\n  // check if public dir is inside root dir\n  const { root, publicDir } = server.config\n  const publicDirInRoot = publicDir.startsWith(withTrailingSlash(root))\n  const publicPath = `${publicDir.slice(root.length)}/`\n\n  return async function viteTransformMiddleware(req, res, next) {\n    const environment = server.environments.client\n\n    if (\n      (req.method !== 'GET' && req.method !== 'HEAD') ||\n      knownIgnoreList.has(req.url!) ||\n      isDocumentFetchDest(req)\n    ) {\n      return next()\n    }\n\n    let url: string\n    try {\n      url = decodeURI(removeTimestampQuery(req.url!)).replace(\n        NULL_BYTE_PLACEHOLDER,\n        '\\0',\n      )\n    } catch (e) {\n      if (e instanceof URIError) {\n        server.config.logger.warn(\n          colors.yellow(\n            `Malformed URI sequence in request URL: ${removeTimestampQuery(req.url!)}`,\n          ),\n        )\n        return next()\n      }\n      return next(e)\n    }\n\n    const withoutQuery = cleanUrl(url)\n\n    try {\n      const isSourceMap = withoutQuery.endsWith('.map')\n      // since we generate source map references, handle those requests here\n      if (isSourceMap) {\n        const depsOptimizer = environment.depsOptimizer\n        if (depsOptimizer?.isOptimizedDepUrl(url)) {\n          // If the browser is requesting a source map for an optimized dep, it\n          // means that the dependency has already been pre-bundled and loaded\n          const sourcemapPath = url.startsWith(FS_PREFIX)\n            ? fsPathFromId(url)\n            : normalizePath(path.resolve(server.config.root, url.slice(1)))\n          try {\n            const map = JSON.parse(\n              await fsp.readFile(sourcemapPath, 'utf-8'),\n            ) as ExistingRawSourceMap\n\n            applySourcemapIgnoreList(\n              map,\n              sourcemapPath,\n              server.config.server.sourcemapIgnoreList,\n              server.config.logger,\n            )\n\n            return send(req, res, JSON.stringify(map), 'json', {\n              headers: server.config.server.headers,\n            })\n          } catch {\n            // Outdated source map request for optimized deps, this isn't an error\n            // but part of the normal flow when re-optimizing after missing deps\n            // Send back an empty source map so the browser doesn't issue warnings\n            const dummySourceMap = {\n              version: 3,\n              file: sourcemapPath.replace(/\\.map$/, ''),\n              sources: [],\n              sourcesContent: [],\n              names: [],\n              mappings: ';;;;;;;;;',\n            }\n            return send(req, res, JSON.stringify(dummySourceMap), 'json', {\n              cacheControl: 'no-cache',\n              headers: server.config.server.headers,\n            })\n          }\n        } else {\n          const originalUrl = url.replace(/\\.map($|\\?)/, '$1')\n          const map = (\n            await environment.moduleGraph.getModuleByUrl(originalUrl)\n          )?.transformResult?.map\n          if (map) {\n            return send(req, res, JSON.stringify(map), 'json', {\n              headers: server.config.server.headers,\n            })\n          } else {\n            return next()\n          }\n        }\n      }\n\n      if (publicDirInRoot && url.startsWith(publicPath)) {\n        warnAboutExplicitPublicPathInUrl(url)\n      }\n\n      if (\n        req.headers['sec-fetch-dest'] === 'script' ||\n        isJSRequest(url) ||\n        isImportRequest(url) ||\n        isCSSRequest(url) ||\n        isHTMLProxy(url)\n      ) {\n        // strip ?import\n        url = removeImportQuery(url)\n        // Strip valid id prefix. This is prepended to resolved Ids that are\n        // not valid browser import specifiers by the importAnalysis plugin.\n        url = unwrapId(url)\n\n        // for CSS, we differentiate between normal CSS requests and imports\n        if (isCSSRequest(url)) {\n          if (\n            req.headers.accept?.includes('text/css') &&\n            !isDirectRequest(url)\n          ) {\n            url = injectQuery(url, 'direct')\n          }\n\n          // check if we can return 304 early for CSS requests. These aren't handled\n          // by the cachedTransformMiddleware due to the browser possibly mixing the\n          // etags of direct and imported CSS\n          const ifNoneMatch = req.headers['if-none-match']\n          if (\n            ifNoneMatch &&\n            (await environment.moduleGraph.getModuleByUrl(url))?.transformResult\n              ?.etag === ifNoneMatch\n          ) {\n            debugCache?.(`[304] ${prettifyUrl(url, server.config.root)}`)\n            res.statusCode = 304\n            return res.end()\n          }\n        }\n\n        // resolve, load and transform using the plugin container\n        const result = await environment.transformRequest(url, {\n          allowId(id) {\n            return (\n              id[0] === '\\0' ||\n              !isServerAccessDeniedForTransform(server.config, id)\n            )\n          },\n        })\n        if (result) {\n          const depsOptimizer = environment.depsOptimizer\n          const type = isDirectCSSRequest(url) ? 'css' : 'js'\n          const isDep =\n            DEP_VERSION_RE.test(url) || depsOptimizer?.isOptimizedDepUrl(url)\n          return send(req, res, result.code, type, {\n            etag: result.etag,\n            // allow browser to cache npm deps!\n            cacheControl: isDep ? 'max-age=31536000,immutable' : 'no-cache',\n            headers: server.config.server.headers,\n            map: result.map,\n          })\n        }\n      }\n    } catch (e) {\n      if (e?.code === ERR_OPTIMIZE_DEPS_PROCESSING_ERROR) {\n        // Skip if response has already been sent\n        if (!res.writableEnded) {\n          res.statusCode = 504 // status code request timeout\n          res.statusMessage = 'Optimize Deps Processing Error'\n          res.end()\n        }\n        // This timeout is unexpected\n        server.config.logger.error(e.message)\n        return\n      }\n      if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) {\n        // Skip if response has already been sent\n        if (!res.writableEnded) {\n          res.statusCode = 504 // status code request timeout\n          res.statusMessage = 'Outdated Optimize Dep'\n          res.end()\n        }\n        // We don't need to log an error in this case, the request\n        // is outdated because new dependencies were discovered and\n        // the new pre-bundle dependencies have changed.\n        // A full-page reload has been issued, and these old requests\n        // can't be properly fulfilled. This isn't an unexpected\n        // error but a normal part of the missing deps discovery flow\n        return\n      }\n      if (e?.code === ERR_CLOSED_SERVER) {\n        // Skip if response has already been sent\n        if (!res.writableEnded) {\n          res.statusCode = 504 // status code request timeout\n          res.statusMessage = 'Outdated Request'\n          res.end()\n        }\n        // We don't need to log an error in this case, the request\n        // is outdated because new dependencies were discovered and\n        // the new pre-bundle dependencies have changed.\n        // A full-page reload has been issued, and these old requests\n        // can't be properly fulfilled. This isn't an unexpected\n        // error but a normal part of the missing deps discovery flow\n        return\n      }\n      if (e?.code === ERR_FILE_NOT_FOUND_IN_OPTIMIZED_DEP_DIR) {\n        // Skip if response has already been sent\n        if (!res.writableEnded) {\n          res.statusCode = 404\n          res.end()\n        }\n        server.config.logger.warn(colors.yellow(e.message))\n        return\n      }\n      if (e?.code === ERR_LOAD_URL) {\n        // Let other middleware handle if we can't load the url via transformRequest\n        return next()\n      }\n      if (e?.code === ERR_DENIED_ID) {\n        const id: string = e.id\n        const servingAccessResult = checkLoadingAccess(server.config, id)\n        if (servingAccessResult === 'denied') {\n          respondWithAccessDenied(id, server, res)\n          return true\n        }\n        if (servingAccessResult === 'fallback') {\n          next()\n          return true\n        }\n        servingAccessResult satisfies 'allowed'\n        throw new Error(`Unexpected access result for id ${id}`)\n      }\n      return next(e)\n    }\n\n    next()\n  }\n\n  function warnAboutExplicitPublicPathInUrl(url: string) {\n    let warning: string\n\n    if (isImportRequest(url)) {\n      const rawUrl = removeImportQuery(url)\n      if (urlRE.test(url)) {\n        warning =\n          `Assets in the public directory are served at the root path.\\n` +\n          `Instead of ${colors.cyan(rawUrl)}, use ${colors.cyan(\n            rawUrl.replace(publicPath, '/'),\n          )}.`\n      } else {\n        warning =\n          'Assets in public directory cannot be imported from JavaScript.\\n' +\n          `If you intend to import that asset, put the file in the src directory, and use ${colors.cyan(\n            rawUrl.replace(publicPath, '/src/'),\n          )} instead of ${colors.cyan(rawUrl)}.\\n` +\n          `If you intend to use the URL of that asset, use ${colors.cyan(\n            injectQuery(rawUrl.replace(publicPath, '/'), 'url'),\n          )}.`\n      }\n    } else {\n      warning =\n        `Files in the public directory are served at the root path.\\n` +\n        `Instead of ${colors.cyan(url)}, use ${colors.cyan(\n          url.replace(publicPath, '/'),\n        )}.`\n    }\n\n    server.config.logger.warn(colors.yellow(warning))\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/mixedModuleGraph.ts",
    "content": "import type { ModuleInfo } from 'rolldown'\nimport { monotonicDateNow } from '../utils'\nimport type { TransformResult } from './transformRequest'\nimport type {\n  EnvironmentModuleGraph,\n  EnvironmentModuleNode,\n  ResolvedUrl,\n} from './moduleGraph'\n\n/**\n * Backward compatible ModuleNode and ModuleGraph with mixed nodes from both the client and ssr environments\n * It would be good to take the types names for the new EnvironmentModuleNode and EnvironmentModuleGraph but we can't\n * do that at this point without breaking to much code in the ecosystem.\n * We are going to deprecate these types and we can try to use them back in the future.\n */\n\n// same default value of \"moduleInfo.meta\" as in Rollup\nconst EMPTY_OBJECT = Object.freeze({})\n\nexport class ModuleNode {\n  _moduleGraph: ModuleGraph\n  _clientModule: EnvironmentModuleNode | undefined\n  _ssrModule: EnvironmentModuleNode | undefined\n  constructor(\n    moduleGraph: ModuleGraph,\n    clientModule?: EnvironmentModuleNode,\n    ssrModule?: EnvironmentModuleNode,\n  ) {\n    this._moduleGraph = moduleGraph\n    this._clientModule = clientModule\n    this._ssrModule = ssrModule\n  }\n  _get<T extends keyof EnvironmentModuleNode>(\n    prop: T,\n  ): EnvironmentModuleNode[T] {\n    return (this._clientModule?.[prop] ?? this._ssrModule?.[prop])!\n  }\n  _set<T extends keyof EnvironmentModuleNode>(\n    prop: T,\n    value: EnvironmentModuleNode[T],\n  ): void {\n    if (this._clientModule) {\n      this._clientModule[prop] = value\n    }\n    if (this._ssrModule) {\n      this._ssrModule[prop] = value\n    }\n  }\n\n  _wrapModuleSet(\n    prop: ModuleSetNames,\n    module: EnvironmentModuleNode | undefined,\n  ): Set<ModuleNode> {\n    if (!module) {\n      return new Set()\n    }\n    return createBackwardCompatibleModuleSet(this._moduleGraph, prop, module)\n  }\n  _getModuleSetUnion(prop: 'importedModules' | 'importers'): Set<ModuleNode> {\n    // A good approximation to the previous logic that returned the union of\n    // the importedModules and importers from both the browser and server\n    const importedModules = new Set<ModuleNode>()\n    const ids = new Set<string>()\n    if (this._clientModule) {\n      for (const mod of this._clientModule[prop]) {\n        if (mod.id) ids.add(mod.id)\n        importedModules.add(\n          this._moduleGraph.getBackwardCompatibleModuleNode(mod),\n        )\n      }\n    }\n    if (this._ssrModule) {\n      for (const mod of this._ssrModule[prop]) {\n        if (mod.id && !ids.has(mod.id)) {\n          importedModules.add(\n            this._moduleGraph.getBackwardCompatibleModuleNode(mod),\n          )\n        }\n      }\n    }\n    return importedModules\n  }\n  _getModuleInfoUnion(prop: 'info'): ModuleInfo | undefined {\n    const _clientValue = this._clientModule?.[prop]\n    const _ssrValue = this._ssrModule?.[prop]\n\n    if (_clientValue == null && _ssrValue == null) return undefined\n\n    return new Proxy({} as any, {\n      get: (_, key: string) => {\n        // `meta` refers to `ModuleInfo.meta` so we refer to `this.meta` to\n        // handle the object union between client and ssr\n        if (key === 'meta') {\n          return this.meta || EMPTY_OBJECT\n        }\n        if (_clientValue) {\n          if (key in _clientValue) {\n            return _clientValue[key as keyof ModuleInfo]\n          }\n        }\n        if (_ssrValue) {\n          if (key in _ssrValue) {\n            return _ssrValue[key as keyof ModuleInfo]\n          }\n        }\n      },\n    })\n  }\n  _getModuleObjectUnion(prop: 'meta'): Record<string, any> | undefined {\n    const _clientValue = this._clientModule?.[prop]\n    const _ssrValue = this._ssrModule?.[prop]\n\n    if (_clientValue == null && _ssrValue == null) return undefined\n\n    const info: Record<string, any> = {}\n    if (_ssrValue) {\n      Object.assign(info, _ssrValue)\n    }\n    if (_clientValue) {\n      Object.assign(info, _clientValue)\n    }\n    return info\n  }\n\n  get url(): string {\n    return this._get('url')\n  }\n  set url(value: string) {\n    this._set('url', value)\n  }\n  get id(): string | null {\n    return this._get('id')\n  }\n  set id(value: string | null) {\n    this._set('id', value)\n  }\n  get file(): string | null {\n    return this._get('file')\n  }\n  set file(value: string | null) {\n    this._set('file', value)\n  }\n  get type(): 'js' | 'css' | 'asset' {\n    return this._get('type')\n  }\n  // `info` needs special care as it's defined as a proxy in `pluginContainer`,\n  // so we also merge it as a proxy too\n  get info(): ModuleInfo | undefined {\n    return this._getModuleInfoUnion('info')\n  }\n  get meta(): Record<string, any> | undefined {\n    return this._getModuleObjectUnion('meta')\n  }\n  get importers(): Set<ModuleNode> {\n    return this._getModuleSetUnion('importers')\n  }\n  get clientImportedModules(): Set<ModuleNode> {\n    return this._wrapModuleSet('importedModules', this._clientModule)\n  }\n  get ssrImportedModules(): Set<ModuleNode> {\n    return this._wrapModuleSet('importedModules', this._ssrModule)\n  }\n  get importedModules(): Set<ModuleNode> {\n    return this._getModuleSetUnion('importedModules')\n  }\n  get acceptedHmrDeps(): Set<ModuleNode> {\n    return this._wrapModuleSet('acceptedHmrDeps', this._clientModule)\n  }\n  get acceptedHmrExports(): Set<string> | null {\n    return this._clientModule?.acceptedHmrExports ?? null\n  }\n  get importedBindings(): Map<string, Set<string>> | null {\n    return this._clientModule?.importedBindings ?? null\n  }\n  get isSelfAccepting(): boolean | undefined {\n    return this._clientModule?.isSelfAccepting\n  }\n  get transformResult(): TransformResult | null {\n    return this._clientModule?.transformResult ?? null\n  }\n  set transformResult(value: TransformResult | null) {\n    if (this._clientModule) {\n      this._clientModule.transformResult = value\n    }\n  }\n  get ssrTransformResult(): TransformResult | null {\n    return this._ssrModule?.transformResult ?? null\n  }\n  set ssrTransformResult(value: TransformResult | null) {\n    if (this._ssrModule) {\n      this._ssrModule.transformResult = value\n    }\n  }\n  get ssrModule(): Record<string, any> | null {\n    return this._ssrModule?.ssrModule ?? null\n  }\n  get ssrError(): Error | null {\n    return this._ssrModule?.ssrError ?? null\n  }\n  get lastHMRTimestamp(): number {\n    return Math.max(\n      this._clientModule?.lastHMRTimestamp ?? 0,\n      this._ssrModule?.lastHMRTimestamp ?? 0,\n    )\n  }\n  set lastHMRTimestamp(value: number) {\n    if (this._clientModule) {\n      this._clientModule.lastHMRTimestamp = value\n    }\n    if (this._ssrModule) {\n      this._ssrModule.lastHMRTimestamp = value\n    }\n  }\n  get lastInvalidationTimestamp(): number {\n    return Math.max(\n      this._clientModule?.lastInvalidationTimestamp ?? 0,\n      this._ssrModule?.lastInvalidationTimestamp ?? 0,\n    )\n  }\n  get invalidationState(): TransformResult | 'HARD_INVALIDATED' | undefined {\n    return this._clientModule?.invalidationState\n  }\n  get ssrInvalidationState(): TransformResult | 'HARD_INVALIDATED' | undefined {\n    return this._ssrModule?.invalidationState\n  }\n}\n\nfunction mapIterator<T, K = T>(\n  iterable: IterableIterator<T>,\n  transform: (value: T) => K,\n): IterableIterator<K> {\n  return {\n    [Symbol.iterator](): IterableIterator<K> {\n      return this\n    },\n    next(): IteratorResult<K> {\n      const r = iterable.next()\n      return r.done\n        ? r\n        : {\n            value: transform(r.value),\n            done: false,\n          }\n    },\n  }\n}\n\nexport class ModuleGraph {\n  /** @internal */\n  _moduleGraphs: {\n    client: () => EnvironmentModuleGraph\n    ssr: () => EnvironmentModuleGraph\n  }\n\n  /** @internal */\n  get _client(): EnvironmentModuleGraph {\n    return this._moduleGraphs.client()\n  }\n\n  /** @internal */\n  get _ssr(): EnvironmentModuleGraph {\n    return this._moduleGraphs.ssr()\n  }\n\n  urlToModuleMap: Map<string, ModuleNode>\n  idToModuleMap: Map<string, ModuleNode>\n  etagToModuleMap: Map<string, ModuleNode>\n\n  fileToModulesMap: Map<string, Set<ModuleNode>>\n\n  private moduleNodeCache = new DualWeakMap<\n    EnvironmentModuleNode,\n    EnvironmentModuleNode,\n    ModuleNode\n  >()\n\n  constructor(moduleGraphs: {\n    client: () => EnvironmentModuleGraph\n    ssr: () => EnvironmentModuleGraph\n  }) {\n    this._moduleGraphs = moduleGraphs\n\n    const getModuleMapUnion =\n      (prop: 'urlToModuleMap' | 'idToModuleMap') => () => {\n        // A good approximation to the previous logic that returned the union of\n        // the importedModules and importers from both the browser and server\n        if (this._ssr[prop].size === 0) {\n          return this._client[prop]\n        }\n        const map = new Map(this._client[prop])\n        for (const [key, module] of this._ssr[prop]) {\n          if (!map.has(key)) {\n            map.set(key, module)\n          }\n        }\n        return map\n      }\n\n    this.urlToModuleMap = createBackwardCompatibleModuleMap(\n      this,\n      'urlToModuleMap',\n      getModuleMapUnion('urlToModuleMap'),\n    )\n    this.idToModuleMap = createBackwardCompatibleModuleMap(\n      this,\n      'idToModuleMap',\n      getModuleMapUnion('idToModuleMap'),\n    )\n    this.etagToModuleMap = createBackwardCompatibleModuleMap(\n      this,\n      'etagToModuleMap',\n      () => this._client.etagToModuleMap,\n    )\n    this.fileToModulesMap = createBackwardCompatibleFileToModulesMap(this)\n  }\n\n  getModuleById(id: string): ModuleNode | undefined {\n    const clientModule = this._client.getModuleById(id)\n    const ssrModule = this._ssr.getModuleById(id)\n    if (!clientModule && !ssrModule) {\n      return\n    }\n    return this.getBackwardCompatibleModuleNodeDual(clientModule, ssrModule)\n  }\n\n  async getModuleByUrl(\n    url: string,\n    _ssr?: boolean,\n  ): Promise<ModuleNode | undefined> {\n    // In the mixed graph, the ssr flag was used to resolve the id.\n    const [clientModule, ssrModule] = await Promise.all([\n      this._client.getModuleByUrl(url),\n      this._ssr.getModuleByUrl(url),\n    ])\n    if (!clientModule && !ssrModule) {\n      return\n    }\n    return this.getBackwardCompatibleModuleNodeDual(clientModule, ssrModule)\n  }\n\n  getModulesByFile(file: string): Set<ModuleNode> | undefined {\n    // Until Vite 5.1.x, the moduleGraph contained modules from both the browser and server\n    // We maintain backwards compatibility by returning a Set of module proxies assuming\n    // that the modules for a certain file are the same in both the browser and server\n    const clientModules = this._client.getModulesByFile(file)\n    const ssrModules = this._ssr.getModulesByFile(file)\n    if (!clientModules && !ssrModules) {\n      return undefined\n    }\n    const result = new Set<ModuleNode>()\n    if (clientModules) {\n      for (const mod of clientModules) {\n        result.add(this.getBackwardCompatibleBrowserModuleNode(mod)!)\n      }\n    }\n    if (ssrModules) {\n      for (const mod of ssrModules) {\n        if (mod.id == null || !this._client.getModuleById(mod.id)) {\n          result.add(this.getBackwardCompatibleServerModuleNode(mod)!)\n        }\n      }\n    }\n    return result\n  }\n\n  onFileChange(file: string): void {\n    this._client.onFileChange(file)\n    this._ssr.onFileChange(file)\n  }\n\n  onFileDelete(file: string): void {\n    this._client.onFileDelete(file)\n    this._ssr.onFileDelete(file)\n  }\n\n  /** @internal */\n  _getModuleGraph(environment: string): EnvironmentModuleGraph {\n    switch (environment) {\n      case 'client':\n        return this._client\n      case 'ssr':\n        return this._ssr\n      default:\n        throw new Error(`Invalid module node environment ${environment}`)\n    }\n  }\n\n  invalidateModule(\n    mod: ModuleNode,\n    seen: Set<ModuleNode> = new Set(),\n    timestamp: number = monotonicDateNow(),\n    isHmr: boolean = false,\n    /** @internal */\n    softInvalidate = false,\n  ): void {\n    if (mod._clientModule) {\n      this._client.invalidateModule(\n        mod._clientModule,\n        new Set(\n          [...seen].map((mod) => mod._clientModule).filter(Boolean),\n        ) as Set<EnvironmentModuleNode>,\n        timestamp,\n        isHmr,\n        softInvalidate,\n      )\n    }\n    if (mod._ssrModule) {\n      // TODO: Maybe this isn't needed?\n      this._ssr.invalidateModule(\n        mod._ssrModule,\n        new Set(\n          [...seen].map((mod) => mod._ssrModule).filter(Boolean),\n        ) as Set<EnvironmentModuleNode>,\n        timestamp,\n        isHmr,\n        softInvalidate,\n      )\n    }\n  }\n\n  invalidateAll(): void {\n    this._client.invalidateAll()\n    this._ssr.invalidateAll()\n  }\n\n  /* TODO: It seems there isn't usage of this method in the ecosystem\n     Waiting to check if we really need this for backwards compatibility\n  async updateModuleInfo(\n    module: ModuleNode,\n    importedModules: Set<string | ModuleNode>,\n    importedBindings: Map<string, Set<string>> | null,\n    acceptedModules: Set<string | ModuleNode>,\n    acceptedExports: Set<string> | null,\n    isSelfAccepting: boolean,\n    ssr?: boolean,\n    staticImportedUrls?: Set<string>, // internal\n  ): Promise<Set<ModuleNode> | undefined> {\n    // Not implemented\n  }\n  */\n\n  async ensureEntryFromUrl(\n    rawUrl: string,\n    ssr?: boolean,\n    setIsSelfAccepting = true,\n  ): Promise<ModuleNode> {\n    const module = await (ssr ? this._ssr : this._client).ensureEntryFromUrl(\n      rawUrl,\n      setIsSelfAccepting,\n    )\n    return this.getBackwardCompatibleModuleNode(module)!\n  }\n\n  createFileOnlyEntry(file: string): ModuleNode {\n    const clientModule = this._client.createFileOnlyEntry(file)\n    const ssrModule = this._ssr.createFileOnlyEntry(file)\n    return this.getBackwardCompatibleModuleNodeDual(clientModule, ssrModule)!\n  }\n\n  async resolveUrl(url: string, ssr?: boolean): Promise<ResolvedUrl> {\n    return ssr ? this._ssr.resolveUrl(url) : this._client.resolveUrl(url)\n  }\n\n  updateModuleTransformResult(\n    mod: ModuleNode,\n    result: TransformResult | null,\n    ssr?: boolean,\n  ): void {\n    const environment = ssr ? 'ssr' : 'client'\n    this._getModuleGraph(environment).updateModuleTransformResult(\n      (environment === 'client' ? mod._clientModule : mod._ssrModule)!,\n      result,\n    )\n  }\n\n  getModuleByEtag(etag: string): ModuleNode | undefined {\n    const mod = this._client.etagToModuleMap.get(etag)\n    return mod && this.getBackwardCompatibleBrowserModuleNode(mod)\n  }\n\n  getBackwardCompatibleBrowserModuleNode(\n    clientModule: EnvironmentModuleNode,\n  ): ModuleNode {\n    return this.getBackwardCompatibleModuleNodeDual(\n      clientModule,\n      clientModule.id ? this._ssr.getModuleById(clientModule.id) : undefined,\n    )\n  }\n\n  getBackwardCompatibleServerModuleNode(\n    ssrModule: EnvironmentModuleNode,\n  ): ModuleNode {\n    return this.getBackwardCompatibleModuleNodeDual(\n      ssrModule.id ? this._client.getModuleById(ssrModule.id) : undefined,\n      ssrModule,\n    )\n  }\n\n  getBackwardCompatibleModuleNode(mod: EnvironmentModuleNode): ModuleNode {\n    return mod.environment === 'client'\n      ? this.getBackwardCompatibleBrowserModuleNode(mod)\n      : this.getBackwardCompatibleServerModuleNode(mod)\n  }\n\n  getBackwardCompatibleModuleNodeDual(\n    clientModule?: EnvironmentModuleNode,\n    ssrModule?: EnvironmentModuleNode,\n  ): ModuleNode {\n    const cached = this.moduleNodeCache.get(clientModule, ssrModule)\n    if (cached) {\n      return cached\n    }\n\n    const moduleNode = new ModuleNode(this, clientModule, ssrModule)\n    this.moduleNodeCache.set(clientModule, ssrModule, moduleNode)\n    return moduleNode\n  }\n}\n\nclass DualWeakMap<K1 extends WeakKey, K2 extends WeakKey, V> {\n  private map = new WeakMap<K1 | object, WeakMap<K2 | object, V>>()\n  private undefinedKey = {}\n\n  get(key1: K1 | undefined, key2: K2 | undefined): V | undefined {\n    const k1 = key1 ?? this.undefinedKey\n    const k2 = key2 ?? this.undefinedKey\n    return this.map.get(k1)?.get(k2)\n  }\n\n  set(key1: K1 | undefined, key2: K2 | undefined, value: V): void {\n    const k1 = key1 ?? this.undefinedKey\n    const k2 = key2 ?? this.undefinedKey\n    if (!this.map.has(k1)) {\n      this.map.set(k1, new Map<K2, V>())\n    }\n\n    const m = this.map.get(k1)!\n    m.set(k2, value)\n  }\n}\n\ntype ModuleSetNames = 'acceptedHmrDeps' | 'importedModules'\n\nfunction createBackwardCompatibleModuleSet(\n  moduleGraph: ModuleGraph,\n  prop: ModuleSetNames,\n  module: EnvironmentModuleNode,\n): Set<ModuleNode> {\n  return {\n    [Symbol.iterator]() {\n      return this.keys()\n    },\n    has(key) {\n      if (!key.id) {\n        return false\n      }\n      const keyModule = moduleGraph\n        ._getModuleGraph(module.environment)\n        .getModuleById(key.id)\n      return keyModule !== undefined && module[prop].has(keyModule)\n    },\n    values() {\n      return this.keys()\n    },\n    keys() {\n      return mapIterator(module[prop].keys(), (mod) =>\n        moduleGraph.getBackwardCompatibleModuleNode(mod),\n      )\n    },\n    get size() {\n      return module[prop].size\n    },\n    forEach(callback, thisArg) {\n      return module[prop].forEach((mod) => {\n        const backwardCompatibleMod =\n          moduleGraph.getBackwardCompatibleModuleNode(mod)\n        callback.call(\n          thisArg,\n          backwardCompatibleMod,\n          backwardCompatibleMod,\n          this,\n        )\n      })\n    },\n    // There are several methods missing. We can implement them if downstream\n    // projects are relying on them: add, clear, delete, difference, intersection,\n    // sDisjointFrom, isSubsetOf, isSupersetOf, symmetricDifference, union\n  } as Set<ModuleNode>\n}\n\nfunction createBackwardCompatibleModuleMap(\n  moduleGraph: ModuleGraph,\n  prop: 'urlToModuleMap' | 'idToModuleMap' | 'etagToModuleMap',\n  getModuleMap: () => Map<string, EnvironmentModuleNode>,\n): Map<string, ModuleNode> {\n  return {\n    [Symbol.iterator]() {\n      return this.entries()\n    },\n    get(key) {\n      const clientModule = moduleGraph._client[prop].get(key)\n      const ssrModule = moduleGraph._ssr[prop].get(key)\n      if (!clientModule && !ssrModule) {\n        return\n      }\n      return moduleGraph.getBackwardCompatibleModuleNodeDual(\n        clientModule,\n        ssrModule,\n      )\n    },\n    set(key, mod) {\n      const clientModule = mod._clientModule\n      if (clientModule) {\n        moduleGraph._client[prop].set(key, clientModule)\n      }\n      const ssrModule = mod._ssrModule\n      if (ssrModule) {\n        moduleGraph._ssr[prop].set(key, ssrModule)\n      }\n    },\n    keys() {\n      return getModuleMap().keys()\n    },\n    values() {\n      return mapIterator(getModuleMap().values(), (mod) =>\n        moduleGraph.getBackwardCompatibleModuleNode(mod),\n      )\n    },\n    entries() {\n      return mapIterator(getModuleMap().entries(), ([key, mod]) => [\n        key,\n        moduleGraph.getBackwardCompatibleModuleNode(mod),\n      ])\n    },\n    get size() {\n      return getModuleMap().size\n    },\n    forEach(callback, thisArg) {\n      return getModuleMap().forEach((mod, key) => {\n        const backwardCompatibleMod =\n          moduleGraph.getBackwardCompatibleModuleNode(mod)\n        callback.call(thisArg, backwardCompatibleMod, key, this)\n      })\n    },\n  } as Map<string, ModuleNode>\n}\n\nfunction createBackwardCompatibleFileToModulesMap(\n  moduleGraph: ModuleGraph,\n): Map<string, Set<ModuleNode>> {\n  const getFileToModulesMap = (): Map<string, Set<EnvironmentModuleNode>> => {\n    // A good approximation to the previous logic that returned the union of\n    // the importedModules and importers from both the browser and server\n    if (!moduleGraph._ssr.fileToModulesMap.size) {\n      return moduleGraph._client.fileToModulesMap\n    }\n    const map = new Map(moduleGraph._client.fileToModulesMap)\n    for (const [key, modules] of moduleGraph._ssr.fileToModulesMap) {\n      const modulesSet = map.get(key)\n      if (!modulesSet) {\n        map.set(key, modules)\n      } else {\n        for (const ssrModule of modules) {\n          let hasModule = false\n          for (const clientModule of modulesSet) {\n            hasModule ||= clientModule.id === ssrModule.id\n            if (hasModule) {\n              break\n            }\n          }\n          if (!hasModule) {\n            modulesSet.add(ssrModule)\n          }\n        }\n      }\n    }\n    return map\n  }\n  const getBackwardCompatibleModules = (\n    modules: Set<EnvironmentModuleNode>,\n  ): Set<ModuleNode> =>\n    new Set(\n      [...modules].map((mod) =>\n        moduleGraph.getBackwardCompatibleModuleNode(mod),\n      ),\n    )\n\n  return {\n    [Symbol.iterator]() {\n      return this.entries()\n    },\n    get(key) {\n      const clientModules = moduleGraph._client.fileToModulesMap.get(key)\n      const ssrModules = moduleGraph._ssr.fileToModulesMap.get(key)\n      if (!clientModules && !ssrModules) {\n        return\n      }\n      const modules = clientModules ?? new Set<EnvironmentModuleNode>()\n      if (ssrModules) {\n        for (const ssrModule of ssrModules) {\n          if (ssrModule.id) {\n            let found = false\n            for (const mod of modules) {\n              found ||= mod.id === ssrModule.id\n              if (found) {\n                break\n              }\n            }\n            if (!found) {\n              modules.add(ssrModule)\n            }\n          }\n        }\n      }\n      return getBackwardCompatibleModules(modules)\n    },\n    keys() {\n      return getFileToModulesMap().keys()\n    },\n    values() {\n      return mapIterator(\n        getFileToModulesMap().values(),\n        getBackwardCompatibleModules,\n      )\n    },\n    entries() {\n      return mapIterator(getFileToModulesMap().entries(), ([key, modules]) => [\n        key,\n        getBackwardCompatibleModules(modules),\n      ])\n    },\n    get size() {\n      return getFileToModulesMap().size\n    },\n    forEach(callback, thisArg) {\n      return getFileToModulesMap().forEach((modules, key) => {\n        callback.call(thisArg, getBackwardCompatibleModules(modules), key, this)\n      })\n    },\n  } as Map<string, Set<ModuleNode>>\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/moduleGraph.ts",
    "content": "import { extname } from 'node:path'\nimport type { ModuleInfo, PartialResolvedId } from 'rolldown'\nimport { isDirectCSSRequest } from '../plugins/css'\nimport {\n  monotonicDateNow,\n  normalizePath,\n  removeImportQuery,\n  removeTimestampQuery,\n} from '../utils'\nimport { FS_PREFIX } from '../constants'\nimport { cleanUrl } from '../../shared/utils'\nimport type { TransformResult } from './transformRequest'\n\nexport class EnvironmentModuleNode {\n  environment: string\n  /**\n   * Public served url path, starts with /\n   */\n  url: string\n  /**\n   * Resolved file system path + query\n   */\n  id: string | null = null\n  file: string | null = null\n  type: 'js' | 'css' | 'asset'\n  info?: ModuleInfo\n  meta?: Record<string, any>\n  importers: Set<EnvironmentModuleNode> = new Set()\n\n  importedModules: Set<EnvironmentModuleNode> = new Set()\n\n  acceptedHmrDeps: Set<EnvironmentModuleNode> = new Set()\n  acceptedHmrExports: Set<string> | null = null\n  importedBindings: Map<string, Set<string>> | null = null\n  isSelfAccepting?: boolean\n  transformResult: TransformResult | null = null\n\n  // ssrModule and ssrError are no longer needed. They are on the module runner module cache.\n  // Once `ssrLoadModule` is re-implemented on top of the new APIs, we can delete these.\n  ssrModule: Record<string, any> | null = null\n  ssrError: Error | null = null\n\n  lastHMRTimestamp = 0\n  /**\n   * `import.meta.hot.invalidate` is called by the client.\n   * If there's multiple clients, multiple `invalidate` request is received.\n   * This property is used to dedupe those request to avoid multiple updates happening.\n   * @internal\n   */\n  lastHMRInvalidationReceived = false\n  lastInvalidationTimestamp = 0\n  /**\n   * If the module only needs to update its imports timestamp (e.g. within an HMR chain),\n   * it is considered soft-invalidated. In this state, its `transformResult` should exist,\n   * and the next `transformRequest` for this module will replace the timestamps.\n   *\n   * By default the value is `undefined` if it's not soft/hard-invalidated. If it gets\n   * soft-invalidated, this will contain the previous `transformResult` value. If it gets\n   * hard-invalidated, this will be set to `'HARD_INVALIDATED'`.\n   * @internal\n   */\n  invalidationState: TransformResult | 'HARD_INVALIDATED' | undefined\n  /**\n   * The module urls that are statically imported in the code. This information is separated\n   * out from `importedModules` as only importers that statically import the module can be\n   * soft invalidated. Other imports (e.g. watched files) needs the importer to be hard invalidated.\n   * @internal\n   */\n  staticImportedUrls?: Set<string>\n\n  /**\n   * @param setIsSelfAccepting - set `false` to set `isSelfAccepting` later. e.g. #7870\n   */\n  constructor(url: string, environment: string, setIsSelfAccepting = true) {\n    this.environment = environment\n    this.url = url\n    this.type = isDirectCSSRequest(url) ? 'css' : 'js'\n    if (setIsSelfAccepting) {\n      this.isSelfAccepting = false\n    }\n  }\n}\n\nexport type ResolvedUrl = [\n  url: string,\n  resolvedId: string,\n  meta: object | null | undefined,\n]\n\nexport class EnvironmentModuleGraph {\n  environment: string\n\n  urlToModuleMap: Map<string, EnvironmentModuleNode> = new Map()\n  idToModuleMap: Map<string, EnvironmentModuleNode> = new Map()\n  etagToModuleMap: Map<string, EnvironmentModuleNode> = new Map()\n  // a single file may corresponds to multiple modules with different queries\n  fileToModulesMap: Map<string, Set<EnvironmentModuleNode>> = new Map()\n\n  /**\n   * @internal\n   */\n  _unresolvedUrlToModuleMap: Map<\n    string,\n    EnvironmentModuleNode | Promise<EnvironmentModuleNode>\n  > = new Map()\n\n  /**\n   * @internal\n   */\n  _resolveId: (url: string) => Promise<PartialResolvedId | null>\n\n  /** @internal */\n  _hasResolveFailedErrorModules: Set<EnvironmentModuleNode> = new Set()\n\n  constructor(\n    environment: string,\n    resolveId: (url: string) => Promise<PartialResolvedId | null>,\n  ) {\n    this.environment = environment\n    this._resolveId = resolveId\n  }\n\n  async getModuleByUrl(\n    rawUrl: string,\n  ): Promise<EnvironmentModuleNode | undefined> {\n    // Quick path, if we already have a module for this rawUrl (even without extension)\n    rawUrl = removeImportQuery(removeTimestampQuery(rawUrl))\n    const mod = this._getUnresolvedUrlToModule(rawUrl)\n    if (mod) {\n      return mod\n    }\n\n    const [url] = await this._resolveUrl(rawUrl)\n    return this.urlToModuleMap.get(url)\n  }\n\n  getModuleById(id: string): EnvironmentModuleNode | undefined {\n    return this.idToModuleMap.get(removeTimestampQuery(id))\n  }\n\n  getModulesByFile(file: string): Set<EnvironmentModuleNode> | undefined {\n    return this.fileToModulesMap.get(file)\n  }\n\n  onFileChange(file: string): void {\n    const mods = this.getModulesByFile(file)\n    if (mods) {\n      const seen = new Set<EnvironmentModuleNode>()\n      mods.forEach((mod) => {\n        this.invalidateModule(mod, seen)\n      })\n    }\n  }\n\n  onFileDelete(file: string): void {\n    const mods = this.getModulesByFile(file)\n    if (mods) {\n      mods.forEach((mod) => {\n        mod.importedModules.forEach((importedMod) => {\n          importedMod.importers.delete(mod)\n        })\n      })\n    }\n  }\n\n  invalidateModule(\n    mod: EnvironmentModuleNode,\n    seen: Set<EnvironmentModuleNode> = new Set(),\n    timestamp: number = monotonicDateNow(),\n    isHmr: boolean = false,\n    /** @internal */\n    softInvalidate = false,\n  ): void {\n    const prevInvalidationState = mod.invalidationState\n\n    // Handle soft invalidation before the `seen` check, as consecutive soft/hard invalidations can\n    // cause the final soft invalidation state to be different.\n    // If soft invalidated, save the previous `transformResult` so that we can reuse and transform the\n    // import timestamps only in `transformRequest`. If there's no previous `transformResult`, hard invalidate it.\n    if (softInvalidate) {\n      mod.invalidationState ??= mod.transformResult ?? 'HARD_INVALIDATED'\n    }\n    // If hard invalidated, further soft invalidations have no effect until it's reset to `undefined`\n    else {\n      mod.invalidationState = 'HARD_INVALIDATED'\n    }\n\n    // Skip updating the module if it was already invalidated before and the invalidation state has not changed\n    if (seen.has(mod) && prevInvalidationState === mod.invalidationState) {\n      return\n    }\n    seen.add(mod)\n\n    if (isHmr) {\n      mod.lastHMRTimestamp = timestamp\n      mod.lastHMRInvalidationReceived = false\n    } else {\n      // Save the timestamp for this invalidation, so we can avoid caching the result of possible already started\n      // processing being done for this module\n      mod.lastInvalidationTimestamp = timestamp\n    }\n\n    // Don't invalidate mod.info and mod.meta, as they are part of the processing pipeline\n    // Invalidating the transform result is enough to ensure this module is re-processed next time it is requested\n    const etag = mod.transformResult?.etag\n    if (etag) this.etagToModuleMap.delete(etag)\n\n    mod.transformResult = null\n\n    mod.ssrModule = null\n    mod.ssrError = null\n\n    mod.importers.forEach((importer) => {\n      if (!importer.acceptedHmrDeps.has(mod)) {\n        // If the importer statically imports the current module, we can soft-invalidate the importer\n        // to only update the import timestamps. If it's not statically imported, e.g. watched/glob file,\n        // we can only soft invalidate if the current module was also soft-invalidated. A soft-invalidation\n        // doesn't need to trigger a re-load and re-transform of the importer.\n        // But we exclude direct CSS files as those cannot be soft invalidated.\n        const shouldSoftInvalidateImporter =\n          (importer.staticImportedUrls?.has(mod.url) || softInvalidate) &&\n          importer.type === 'js'\n        this.invalidateModule(\n          importer,\n          seen,\n          timestamp,\n          isHmr,\n          shouldSoftInvalidateImporter,\n        )\n      }\n    })\n\n    this._hasResolveFailedErrorModules.delete(mod)\n  }\n\n  invalidateAll(): void {\n    const timestamp = monotonicDateNow()\n    const seen = new Set<EnvironmentModuleNode>()\n    this.idToModuleMap.forEach((mod) => {\n      this.invalidateModule(mod, seen, timestamp)\n    })\n  }\n\n  /**\n   * Update the module graph based on a module's updated imports information\n   * If there are dependencies that no longer have any importers, they are\n   * returned as a Set.\n   *\n   * @param staticImportedUrls Subset of `importedModules` where they're statically imported in code.\n   *   This is only used for soft invalidations so `undefined` is fine but may cause more runtime processing.\n   */\n  async updateModuleInfo(\n    mod: EnvironmentModuleNode,\n    importedModules: Set<string | EnvironmentModuleNode>,\n    importedBindings: Map<string, Set<string>> | null,\n    acceptedModules: Set<string | EnvironmentModuleNode>,\n    acceptedExports: Set<string> | null,\n    isSelfAccepting: boolean,\n    /** @internal */\n    staticImportedUrls?: Set<string>,\n  ): Promise<Set<EnvironmentModuleNode> | undefined> {\n    mod.isSelfAccepting = isSelfAccepting\n    const prevImports = mod.importedModules\n    let noLongerImported: Set<EnvironmentModuleNode> | undefined\n\n    let resolvePromises = []\n    let resolveResults = new Array(importedModules.size)\n    let index = 0\n    // update import graph\n    for (const imported of importedModules) {\n      const nextIndex = index++\n      if (typeof imported === 'string') {\n        resolvePromises.push(\n          this.ensureEntryFromUrl(imported).then((dep) => {\n            dep.importers.add(mod)\n            resolveResults[nextIndex] = dep\n          }),\n        )\n      } else {\n        imported.importers.add(mod)\n        resolveResults[nextIndex] = imported\n      }\n    }\n\n    if (resolvePromises.length) {\n      await Promise.all(resolvePromises)\n    }\n\n    const nextImports = new Set(resolveResults)\n    mod.importedModules = nextImports\n\n    // remove the importer from deps that were imported but no longer are.\n    prevImports.forEach((dep) => {\n      if (!mod.importedModules.has(dep)) {\n        dep.importers.delete(mod)\n        if (!dep.importers.size) {\n          // dependency no longer imported\n          ;(noLongerImported || (noLongerImported = new Set())).add(dep)\n        }\n      }\n    })\n\n    // update accepted hmr deps\n    resolvePromises = []\n    resolveResults = new Array(acceptedModules.size)\n    index = 0\n    for (const accepted of acceptedModules) {\n      const nextIndex = index++\n      if (typeof accepted === 'string') {\n        resolvePromises.push(\n          this.ensureEntryFromUrl(accepted).then((dep) => {\n            resolveResults[nextIndex] = dep\n          }),\n        )\n      } else {\n        resolveResults[nextIndex] = accepted\n      }\n    }\n\n    if (resolvePromises.length) {\n      await Promise.all(resolvePromises)\n    }\n\n    mod.acceptedHmrDeps = new Set(resolveResults)\n    mod.staticImportedUrls = staticImportedUrls\n\n    // update accepted hmr exports\n    mod.acceptedHmrExports = acceptedExports\n    mod.importedBindings = importedBindings\n    return noLongerImported\n  }\n\n  async ensureEntryFromUrl(\n    rawUrl: string,\n    setIsSelfAccepting = true,\n  ): Promise<EnvironmentModuleNode> {\n    return this._ensureEntryFromUrl(rawUrl, setIsSelfAccepting)\n  }\n\n  /**\n   * @internal\n   */\n  async _ensureEntryFromUrl(\n    rawUrl: string,\n    setIsSelfAccepting = true,\n    // Optimization, avoid resolving the same url twice if the caller already did it\n    resolved?: PartialResolvedId,\n  ): Promise<EnvironmentModuleNode> {\n    // Quick path, if we already have a module for this rawUrl (even without extension)\n    rawUrl = removeImportQuery(removeTimestampQuery(rawUrl))\n    let mod = this._getUnresolvedUrlToModule(rawUrl)\n    if (mod) {\n      return mod\n    }\n    const modPromise = (async () => {\n      const [url, resolvedId, meta] = await this._resolveUrl(rawUrl, resolved)\n      mod = this.idToModuleMap.get(resolvedId)\n      if (!mod) {\n        mod = new EnvironmentModuleNode(\n          url,\n          this.environment,\n          setIsSelfAccepting,\n        )\n        if (meta) mod.meta = meta\n        this.urlToModuleMap.set(url, mod)\n        mod.id = resolvedId\n        this.idToModuleMap.set(resolvedId, mod)\n        const file = (mod.file = cleanUrl(resolvedId))\n        let fileMappedModules = this.fileToModulesMap.get(file)\n        if (!fileMappedModules) {\n          fileMappedModules = new Set()\n          this.fileToModulesMap.set(file, fileMappedModules)\n        }\n        fileMappedModules.add(mod)\n      }\n      // multiple urls can map to the same module and id, make sure we register\n      // the url to the existing module in that case\n      else if (!this.urlToModuleMap.has(url)) {\n        this.urlToModuleMap.set(url, mod)\n      }\n      this._setUnresolvedUrlToModule(rawUrl, mod)\n      return mod\n    })()\n\n    // Also register the clean url to the module, so that we can short-circuit\n    // resolving the same url twice\n    this._setUnresolvedUrlToModule(rawUrl, modPromise)\n    return modPromise\n  }\n\n  // some deps, like a css file referenced via @import, don't have its own\n  // url because they are inlined into the main css import. But they still\n  // need to be represented in the module graph so that they can trigger\n  // hmr in the importing css file.\n  createFileOnlyEntry(file: string): EnvironmentModuleNode {\n    file = normalizePath(file)\n    let fileMappedModules = this.fileToModulesMap.get(file)\n    if (!fileMappedModules) {\n      fileMappedModules = new Set()\n      this.fileToModulesMap.set(file, fileMappedModules)\n    }\n\n    const url = `${FS_PREFIX}${file}`\n    for (const m of fileMappedModules) {\n      if ((m.url === url || m.id === file) && m.type === 'asset') {\n        return m\n      }\n    }\n\n    const mod = new EnvironmentModuleNode(url, this.environment)\n    mod.type = 'asset'\n    mod.file = file\n    fileMappedModules.add(mod)\n    return mod\n  }\n\n  // for incoming urls, it is important to:\n  // 1. remove the HMR timestamp query (?t=xxxx) and the ?import query\n  // 2. resolve its extension so that urls with or without extension all map to\n  // the same module\n  async resolveUrl(url: string): Promise<ResolvedUrl> {\n    url = removeImportQuery(removeTimestampQuery(url))\n    const mod = await this._getUnresolvedUrlToModule(url)\n    if (mod?.id) {\n      return [mod.url, mod.id, mod.meta]\n    }\n    return this._resolveUrl(url)\n  }\n\n  updateModuleTransformResult(\n    mod: EnvironmentModuleNode,\n    result: TransformResult | null,\n  ): void {\n    if (this.environment === 'client') {\n      const prevEtag = mod.transformResult?.etag\n      if (prevEtag) this.etagToModuleMap.delete(prevEtag)\n      if (result?.etag) this.etagToModuleMap.set(result.etag, mod)\n    }\n\n    mod.transformResult = result\n  }\n\n  getModuleByEtag(etag: string): EnvironmentModuleNode | undefined {\n    return this.etagToModuleMap.get(etag)\n  }\n\n  /**\n   * @internal\n   */\n  _getUnresolvedUrlToModule(\n    url: string,\n  ): Promise<EnvironmentModuleNode> | EnvironmentModuleNode | undefined {\n    return this._unresolvedUrlToModuleMap.get(url)\n  }\n  /**\n   * @internal\n   */\n  _setUnresolvedUrlToModule(\n    url: string,\n    mod: Promise<EnvironmentModuleNode> | EnvironmentModuleNode,\n  ): void {\n    this._unresolvedUrlToModuleMap.set(url, mod)\n  }\n\n  /**\n   * @internal\n   */\n  async _resolveUrl(\n    url: string,\n    alreadyResolved?: PartialResolvedId,\n  ): Promise<ResolvedUrl> {\n    const resolved = alreadyResolved ?? (await this._resolveId(url))\n    const resolvedId = resolved?.id || url\n    if (\n      url !== resolvedId &&\n      !url.includes('\\0') &&\n      !url.startsWith(`virtual:`)\n    ) {\n      const ext = extname(cleanUrl(resolvedId))\n      if (ext) {\n        const pathname = cleanUrl(url)\n        if (!pathname.endsWith(ext)) {\n          url = pathname + ext + url.slice(pathname.length)\n        }\n      }\n    }\n    return [url, resolvedId, resolved?.meta]\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/openBrowser.ts",
    "content": "/**\n * The following is modified based on source found in\n * https://github.com/facebook/create-react-app\n *\n * MIT Licensed\n * Copyright (c) 2015-present, Facebook, Inc.\n * https://github.com/facebook/create-react-app/blob/main/LICENSE\n *\n */\n\nimport { join } from 'node:path'\nimport { exec } from 'node:child_process'\nimport type { ExecOptions } from 'node:child_process'\nimport open from 'open'\nimport type { Options } from 'open'\nimport spawn from 'cross-spawn'\nimport colors from 'picocolors'\nimport type { Logger } from '../logger'\nimport { VITE_PACKAGE_DIR } from '../constants'\n\n/**\n * Reads the BROWSER environment variable and decides what to do with it.\n */\nexport function openBrowser(\n  url: string,\n  opt: string | true,\n  logger: Logger,\n): void {\n  // The browser executable to open.\n  // See https://github.com/sindresorhus/open#app for documentation.\n  const browser = typeof opt === 'string' ? opt : process.env.BROWSER || ''\n  if (browser.toLowerCase().endsWith('.js')) {\n    executeNodeScript(browser, url, logger)\n  } else if (browser.toLowerCase() !== 'none') {\n    const browserArgs = process.env.BROWSER_ARGS\n      ? process.env.BROWSER_ARGS.split(' ')\n      : []\n    startBrowserProcess(browser, browserArgs, url, logger)\n  }\n}\n\nfunction executeNodeScript(scriptPath: string, url: string, logger: Logger) {\n  const extraArgs = process.argv.slice(2)\n  const child = spawn(process.execPath, [scriptPath, ...extraArgs, url], {\n    stdio: 'inherit',\n  })\n  child.on('close', (code) => {\n    if (code !== 0) {\n      logger.error(\n        colors.red(\n          `\\nThe script specified as BROWSER environment variable failed.\\n\\n${colors.cyan(\n            scriptPath,\n          )} exited with code ${code}.`,\n        ),\n        { error: null },\n      )\n    }\n  })\n}\n\nconst supportedChromiumBrowsers = [\n  'Google Chrome Canary',\n  'Google Chrome Dev',\n  'Google Chrome Beta',\n  'Google Chrome',\n  'Microsoft Edge',\n  'Brave Browser',\n  'Vivaldi',\n  'Chromium',\n]\n\nasync function startBrowserProcess(\n  browser: string | undefined,\n  browserArgs: string[],\n  url: string,\n  logger: Logger,\n) {\n  // If we're on OS X, the user hasn't specifically\n  // requested a different browser, we can try opening\n  // a Chromium browser with JXA. This lets us reuse an\n  // existing tab when possible instead of creating a new one.\n  const preferredOSXBrowser =\n    browser === 'google chrome' ? 'Google Chrome' : browser\n  const shouldTryOpenChromeWithJXA =\n    process.platform === 'darwin' &&\n    (!preferredOSXBrowser ||\n      supportedChromiumBrowsers.includes(preferredOSXBrowser))\n\n  if (shouldTryOpenChromeWithJXA) {\n    try {\n      const ps = await execAsync('ps cax')\n      const openedBrowser =\n        preferredOSXBrowser && ps.includes(preferredOSXBrowser)\n          ? preferredOSXBrowser\n          : supportedChromiumBrowsers.find((b) => ps.includes(b))\n      if (openedBrowser) {\n        // Try our best to reuse existing tab with JXA\n        await execAsync(`osascript openChrome.js \"${url}\" \"${openedBrowser}\"`, {\n          cwd: join(VITE_PACKAGE_DIR, 'bin'),\n        })\n        return true\n      }\n    } catch {\n      // Ignore errors\n    }\n  }\n\n  // Another special case: on OS X, check if BROWSER has been set to \"open\".\n  // In this case, instead of passing the string `open` to `open` function (which won't work),\n  // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):\n  // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768\n  if (process.platform === 'darwin' && browser === 'open') {\n    browser = undefined\n  }\n\n  // Fallback to open\n  // (It will always open new tab)\n  try {\n    const options: Options = browser\n      ? { app: { name: browser, arguments: browserArgs } }\n      : {}\n\n    new Promise((_, reject) => {\n      open(url, options)\n        .then((subprocess) => {\n          subprocess.on('error', reject)\n        })\n        .catch(reject)\n    }).catch((err) => {\n      logger.error(err.stack || err.message)\n    })\n\n    return true\n  } catch {\n    return false\n  }\n}\n\nfunction execAsync(command: string, options?: ExecOptions): Promise<string> {\n  return new Promise((resolve, reject) => {\n    exec(command, options, (error, stdout) => {\n      if (error) {\n        reject(error)\n      } else {\n        resolve(stdout.toString())\n      }\n    })\n  })\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/pluginContainer.ts",
    "content": "/**\n * This file is refactored into TypeScript based on\n * https://github.com/preactjs/wmr/blob/main/packages/wmr/src/lib/rollup-plugin-container.js\n */\n\n/**\nhttps://github.com/preactjs/wmr/blob/master/LICENSE\n\nMIT License\n\nCopyright (c) 2020 The Preact Authors\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*/\n\nimport fs from 'node:fs'\nimport fsp from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport { parseAst as rolldownParseAst } from 'rolldown/parseAst'\nimport type { ESTree } from 'rolldown/utils'\nimport type {\n  AsyncPluginHooks,\n  CustomPluginOptions,\n  EmittedFile,\n  FunctionPluginHooks,\n  ImportKind,\n  InputOptions,\n  LoadResult,\n  ModuleInfo,\n  ModuleOptions,\n  ModuleType,\n  NormalizedInputOptions,\n  OutputOptions,\n  ParallelPluginHooks,\n  PartialNull,\n  PartialResolvedId,\n  PluginContextMeta,\n  ResolvedId,\n  RollupError,\n  RolldownFsModule as RollupFsModule,\n  RollupLog,\n  MinimalPluginContext as RollupMinimalPluginContext,\n  PluginContext as RollupPluginContext,\n  TransformPluginContext as RollupTransformPluginContext,\n  SourceDescription,\n  SourceMap,\n  TransformResult,\n} from 'rolldown'\nimport type { RawSourceMap } from '@jridgewell/remapping'\nimport { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping'\nimport MagicString from 'magic-string'\nimport colors from 'picocolors'\nimport type { FSWatcher } from '#dep-types/chokidar'\nimport type { Plugin } from '../plugin'\nimport {\n  combineSourcemaps,\n  createDebugger,\n  ensureWatchedFile,\n  generateCodeFrame,\n  isExternalUrl,\n  isObject,\n  normalizePath,\n  numberToPos,\n  prettifyUrl,\n  rolldownVersion,\n  rollupVersion,\n  timeFrom,\n} from '../utils'\nimport { FS_PREFIX, VERSION as viteVersion } from '../constants'\nimport {\n  createPluginHookUtils,\n  getCachedFilterForPlugin,\n  getHookHandler,\n} from '../plugins'\nimport { cleanUrl, unwrapId } from '../../shared/utils'\nimport type { PluginHookUtils } from '../config'\nimport type { Environment } from '../environment'\nimport type { Logger } from '../logger'\nimport {\n  isFutureDeprecationEnabled,\n  warnFutureDeprecation,\n} from '../deprecations'\nimport type { DevEnvironment } from './environment'\nimport { buildErrorMessage } from './middlewares/error'\nimport type {\n  EnvironmentModuleGraph,\n  EnvironmentModuleNode,\n} from './moduleGraph'\n\n// same default value of \"moduleInfo.meta\" as in Rollup\nconst EMPTY_OBJECT = Object.freeze({})\n\nconst debugSourcemapCombineFilter =\n  process.env.DEBUG_VITE_SOURCEMAP_COMBINE_FILTER\nconst debugSourcemapCombine = createDebugger('vite:sourcemap-combine', {\n  onlyWhenFocused: true,\n})\nconst debugResolve = createDebugger('vite:resolve')\nconst debugPluginResolve = createDebugger('vite:plugin-resolve', {\n  onlyWhenFocused: 'vite:plugin',\n})\nconst debugPluginTransform = createDebugger('vite:plugin-transform', {\n  onlyWhenFocused: 'vite:plugin',\n})\nconst debugPluginContainerContext = createDebugger(\n  'vite:plugin-container-context',\n)\n\nexport const ERR_CLOSED_SERVER = 'ERR_CLOSED_SERVER'\n\nexport function throwClosedServerError(): never {\n  const err: any = new Error(\n    'The server is being restarted or closed. Request is outdated',\n  )\n  err.code = ERR_CLOSED_SERVER\n  // This error will be caught by the transform middleware that will\n  // send a 504 status code request timeout\n  throw err\n}\n\nexport interface PluginContainerOptions {\n  cwd?: string\n  output?: OutputOptions\n  modules?: Map<string, { info: ModuleInfo }>\n  writeFile?: (name: string, source: string | Uint8Array) => void\n}\n\n/**\n * Create a plugin container with a set of plugins. We pass them as a parameter\n * instead of using environment.plugins to allow the creation of different\n * pipelines working with the same environment (used for createIdResolver).\n */\nexport async function createEnvironmentPluginContainer<\n  Env extends Environment = Environment,\n>(\n  environment: Env,\n  plugins: readonly Plugin[],\n  watcher?: FSWatcher,\n  autoStart = true,\n): Promise<EnvironmentPluginContainer<Env>> {\n  const container = new EnvironmentPluginContainer(\n    environment,\n    plugins,\n    watcher,\n    autoStart,\n  )\n  await container.resolveRollupOptions()\n  return container\n}\n\nexport type SkipInformation = {\n  id: string\n  importer: string | undefined\n  plugin: Plugin\n  called?: boolean\n}\n\nclass EnvironmentPluginContainer<Env extends Environment = Environment> {\n  private _pluginContextMap = new Map<Plugin, PluginContext>()\n  private _resolvedRollupOptions?: InputOptions\n  private _processesing = new Set<Promise<any>>()\n  private _seenResolves: Record<string, true | undefined> = {}\n\n  // _addedFiles from the `load()` hook gets saved here so it can be reused in the `transform()` hook\n  private _moduleNodeToLoadAddedImports = new WeakMap<\n    EnvironmentModuleNode,\n    Set<string> | null\n  >()\n\n  getSortedPluginHooks: PluginHookUtils['getSortedPluginHooks']\n  getSortedPlugins: PluginHookUtils['getSortedPlugins']\n\n  moduleGraph: EnvironmentModuleGraph | undefined\n  watchFiles: Set<string> = new Set()\n  minimalContext: MinimalPluginContext<Env>\n\n  private _started = false\n  private _buildStartPromise: Promise<void> | undefined\n  private _closed = false\n\n  /**\n   * @internal use `createEnvironmentPluginContainer` instead\n   */\n  constructor(\n    public environment: Env,\n    public plugins: readonly Plugin[],\n    public watcher?: FSWatcher | undefined,\n    autoStart = true,\n  ) {\n    this._started = !autoStart\n    this.minimalContext = new MinimalPluginContext(\n      { ...basePluginContextMeta, watchMode: true },\n      environment,\n    )\n    const utils = createPluginHookUtils(plugins)\n    this.getSortedPlugins = utils.getSortedPlugins\n    this.getSortedPluginHooks = utils.getSortedPluginHooks\n    this.moduleGraph =\n      environment.mode === 'dev' ? environment.moduleGraph : undefined\n  }\n\n  private _updateModuleLoadAddedImports(\n    id: string,\n    addedImports: Set<string> | null,\n  ): void {\n    const module = this.moduleGraph?.getModuleById(id)\n    if (module) {\n      this._moduleNodeToLoadAddedImports.set(module, addedImports)\n    }\n  }\n\n  private _getAddedImports(id: string): Set<string> | null {\n    const module = this.moduleGraph?.getModuleById(id)\n    return module\n      ? this._moduleNodeToLoadAddedImports.get(module) || null\n      : null\n  }\n\n  getModuleInfo(id: string): ModuleInfo | null {\n    const module = this.moduleGraph?.getModuleById(id)\n    if (!module) {\n      return null\n    }\n    if (!module.info) {\n      module.info = new Proxy(\n        { id, meta: module.meta || EMPTY_OBJECT } as ModuleInfo,\n        // throw when an unsupported ModuleInfo property is accessed,\n        // so that incompatible plugins fail in a non-cryptic way.\n        {\n          get(info: any, key: string) {\n            if (key in info) {\n              return info[key]\n            }\n            // Don't throw an error when returning from an async function\n            if (key === 'then') {\n              return undefined\n            }\n            throw Error(\n              `[vite] The \"${key}\" property of ModuleInfo is not supported.`,\n            )\n          },\n        },\n      )\n    }\n    return module.info ?? null\n  }\n\n  // keeps track of hook promises so that we can wait for them all to finish upon closing the server\n  private handleHookPromise<T>(maybePromise: undefined | T | Promise<T>) {\n    if (!(maybePromise as any)?.then) {\n      return maybePromise\n    }\n    const promise = maybePromise as Promise<T>\n    this._processesing.add(promise)\n    return promise.finally(() => this._processesing.delete(promise))\n  }\n\n  get options(): InputOptions {\n    return this._resolvedRollupOptions!\n  }\n\n  async resolveRollupOptions(): Promise<InputOptions> {\n    if (!this._resolvedRollupOptions) {\n      let options = this.environment.config.build.rollupOptions\n      for (const optionsHook of this.getSortedPluginHooks('options')) {\n        if (this._closed) {\n          throwClosedServerError()\n        }\n        options =\n          (await this.handleHookPromise(\n            optionsHook.call(this.minimalContext, options),\n          )) || options\n      }\n      this._resolvedRollupOptions = options\n    }\n    return this._resolvedRollupOptions\n  }\n\n  private _getPluginContext(plugin: Plugin) {\n    if (!this._pluginContextMap.has(plugin)) {\n      this._pluginContextMap.set(plugin, new PluginContext(plugin, this))\n    }\n    return this._pluginContextMap.get(plugin)!\n  }\n\n  // parallel, ignores returns\n  private async hookParallel<H extends AsyncPluginHooks & ParallelPluginHooks>(\n    hookName: H,\n    context: (plugin: Plugin) => ThisType<FunctionPluginHooks[H]>,\n    args: (plugin: Plugin) => Parameters<FunctionPluginHooks[H]>,\n    condition?: (plugin: Plugin) => boolean | undefined,\n  ): Promise<void> {\n    const parallelPromises: Promise<unknown>[] = []\n    for (const plugin of this.getSortedPlugins(hookName)) {\n      // Don't throw here if closed, so buildEnd and closeBundle hooks can finish running\n      if (condition && !condition(plugin)) continue\n\n      const hook = plugin[hookName]\n      const handler: Function = getHookHandler(hook)\n      if ((hook as { sequential?: boolean }).sequential) {\n        await Promise.all(parallelPromises)\n        parallelPromises.length = 0\n        await handler.apply(context(plugin), args(plugin))\n      } else {\n        parallelPromises.push(handler.apply(context(plugin), args(plugin)))\n      }\n    }\n    await Promise.all(parallelPromises)\n  }\n\n  async buildStart(_options?: InputOptions): Promise<void> {\n    if (this._started) {\n      if (this._buildStartPromise) {\n        await this._buildStartPromise\n      }\n      return\n    }\n    this._started = true\n    const config = this.environment.getTopLevelConfig()\n    this._buildStartPromise = this.handleHookPromise(\n      this.hookParallel(\n        'buildStart',\n        (plugin) => this._getPluginContext(plugin),\n        () => [this.options as NormalizedInputOptions],\n        (plugin) =>\n          this.environment.name === 'client' ||\n          config.server.perEnvironmentStartEndDuringDev ||\n          plugin.perEnvironmentStartEndDuringDev,\n      ),\n    ) as Promise<void>\n    await this._buildStartPromise\n    this._buildStartPromise = undefined\n  }\n\n  async resolveId(\n    rawId: string,\n    importer: string | undefined = join(\n      this.environment.config.root,\n      'index.html',\n    ),\n    options?: {\n      kind?: ImportKind\n      attributes?: Record<string, string>\n      custom?: CustomPluginOptions\n      /** @deprecated use `skipCalls` instead */\n      skip?: Set<Plugin>\n      skipCalls?: readonly SkipInformation[]\n      /**\n       * @internal\n       */\n      scan?: boolean\n      isEntry?: boolean\n    },\n  ): Promise<PartialResolvedId | null> {\n    if (!this._started) {\n      this.buildStart()\n      await this._buildStartPromise\n    }\n    const skip = options?.skip\n    const skipCalls = options?.skipCalls\n    const scan = !!options?.scan\n    const ssr = this.environment.config.consumer === 'server'\n    const ctx = new ResolveIdContext(this, skip, skipCalls, scan)\n    const topLevelConfig = this.environment.getTopLevelConfig()\n\n    const mergedSkip = new Set<Plugin>(skip)\n    for (const call of skipCalls ?? []) {\n      if (call.called || (call.id === rawId && call.importer === importer)) {\n        mergedSkip.add(call.plugin)\n      }\n    }\n\n    const resolveStart = debugResolve ? performance.now() : 0\n    let id: string | null = null\n    const partial: Partial<PartialResolvedId> = {}\n    for (const plugin of this.getSortedPlugins('resolveId')) {\n      if (this._closed && this.environment.config.dev.recoverable)\n        throwClosedServerError()\n      if (mergedSkip?.has(plugin)) continue\n\n      const filter = getCachedFilterForPlugin(plugin, 'resolveId')\n      if (filter && !filter(rawId)) continue\n\n      ctx._plugin = plugin\n\n      const normalizedOptions = {\n        kind: options?.kind,\n        attributes: options?.attributes ?? {},\n        custom: options?.custom,\n        isEntry: !!options?.isEntry,\n        ssr,\n        scan,\n      }\n      if (\n        isFutureDeprecationEnabled(\n          topLevelConfig,\n          'removePluginHookSsrArgument',\n        )\n      ) {\n        let ssrTemp = ssr\n        Object.defineProperty(normalizedOptions, 'ssr', {\n          get() {\n            warnFutureDeprecation(\n              topLevelConfig,\n              'removePluginHookSsrArgument',\n              `Used in plugin \"${plugin.name}\".`,\n            )\n            return ssrTemp\n          },\n          set(v) {\n            ssrTemp = v\n          },\n        })\n      }\n\n      const pluginResolveStart = debugPluginResolve ? performance.now() : 0\n      const handler = getHookHandler(plugin.resolveId)\n      const result = await this.handleHookPromise(\n        handler.call(ctx as any, rawId, importer, normalizedOptions),\n      )\n      if (!result) continue\n\n      if (typeof result === 'string') {\n        id = result\n      } else {\n        id = result.id\n        Object.assign(partial, result)\n      }\n\n      debugPluginResolve?.(\n        timeFrom(pluginResolveStart),\n        plugin.name,\n        prettifyUrl(id, this.environment.config.root),\n      )\n\n      // resolveId() is hookFirst - first non-null result is returned.\n      break\n    }\n\n    if (debugResolve && rawId !== id && !rawId.startsWith(FS_PREFIX)) {\n      const key = rawId + id\n      // avoid spamming\n      if (!this._seenResolves[key]) {\n        this._seenResolves[key] = true\n        debugResolve(\n          `${timeFrom(resolveStart)} ${colors.cyan(rawId)} -> ${colors.dim(\n            id,\n          )}`,\n        )\n      }\n    }\n\n    if (id) {\n      partial.id = isExternalUrl(id) || id[0] === '\\0' ? id : normalizePath(id)\n      return partial as PartialResolvedId\n    } else {\n      return null\n    }\n  }\n\n  async load(id: string): Promise<LoadResult | null> {\n    let ssr = this.environment.config.consumer === 'server'\n    const topLevelConfig = this.environment.getTopLevelConfig()\n    const options = { ssr }\n    const ctx = new LoadPluginContext(this)\n    for (const plugin of this.getSortedPlugins('load')) {\n      if (this._closed && this.environment.config.dev.recoverable)\n        throwClosedServerError()\n\n      const filter = getCachedFilterForPlugin(plugin, 'load')\n      if (filter && !filter(id)) continue\n\n      ctx._plugin = plugin\n\n      if (\n        isFutureDeprecationEnabled(\n          topLevelConfig,\n          'removePluginHookSsrArgument',\n        )\n      ) {\n        Object.defineProperty(options, 'ssr', {\n          get() {\n            warnFutureDeprecation(\n              topLevelConfig,\n              'removePluginHookSsrArgument',\n              `Used in plugin \"${plugin.name}\".`,\n            )\n            return ssr\n          },\n          set(v) {\n            ssr = v\n          },\n        })\n      }\n\n      const handler = getHookHandler(plugin.load)\n      const result = await this.handleHookPromise(\n        handler.call(ctx as any, id, options),\n      )\n      if (result != null) {\n        if (isObject(result)) {\n          ctx._updateModuleInfo(id, result)\n        }\n        this._updateModuleLoadAddedImports(id, ctx._addedImports)\n        return result\n      }\n    }\n    this._updateModuleLoadAddedImports(id, ctx._addedImports)\n    return null\n  }\n\n  async transform(\n    code: string,\n    id: string,\n    options?: {\n      inMap?: SourceDescription['map']\n      moduleType?: string\n    },\n  ): Promise<{\n    code: string\n    map: SourceMap | { mappings: '' } | null\n    moduleType?: ModuleType\n  }> {\n    let ssr = this.environment.config.consumer === 'server'\n    const topLevelConfig = this.environment.getTopLevelConfig()\n    const optionsWithSSR = options\n      ? { ...options, ssr, moduleType: options.moduleType ?? 'js' }\n      : { ssr, moduleType: 'js' }\n    const inMap = options?.inMap\n\n    const ctx = new TransformPluginContext(this, id, code, inMap as SourceMap)\n    ctx._addedImports = this._getAddedImports(id)\n\n    for (const plugin of this.getSortedPlugins('transform')) {\n      if (this._closed && this.environment.config.dev.recoverable)\n        throwClosedServerError()\n\n      const filter = getCachedFilterForPlugin(plugin, 'transform')\n      if (filter && !filter(id, code, optionsWithSSR.moduleType)) continue\n\n      if (\n        isFutureDeprecationEnabled(\n          topLevelConfig,\n          'removePluginHookSsrArgument',\n        )\n      ) {\n        Object.defineProperty(optionsWithSSR, 'ssr', {\n          get() {\n            warnFutureDeprecation(\n              topLevelConfig,\n              'removePluginHookSsrArgument',\n              `Used in plugin \"${plugin.name}\".`,\n            )\n            return ssr\n          },\n          set(v) {\n            ssr = v\n          },\n        })\n      }\n\n      ctx._updateActiveInfo(plugin, id, code)\n      const start = debugPluginTransform ? performance.now() : 0\n      let result: TransformResult | string | undefined\n      const handler = getHookHandler(plugin.transform)\n      try {\n        result = await this.handleHookPromise(\n          handler.call(ctx as any, code, id, optionsWithSSR),\n        )\n      } catch (e) {\n        ctx.error(e)\n      }\n      if (!result) continue\n      debugPluginTransform?.(\n        timeFrom(start),\n        plugin.name,\n        prettifyUrl(id, this.environment.config.root),\n      )\n      if (isObject(result)) {\n        if (result.code !== undefined) {\n          code = result.code as string\n          if (result.map) {\n            if (debugSourcemapCombine) {\n              // @ts-expect-error inject plugin name for debug purpose\n              result.map.name = plugin.name\n            }\n            ctx.sourcemapChain.push(result.map)\n          }\n        }\n        if (result.moduleType !== undefined) {\n          optionsWithSSR.moduleType = result.moduleType\n        }\n        ctx._updateModuleInfo(id, result)\n      } else {\n        code = result\n      }\n    }\n    return {\n      code,\n      map: ctx._getCombinedSourcemap(),\n      moduleType: optionsWithSSR.moduleType,\n    }\n  }\n\n  async watchChange(\n    id: string,\n    change: { event: 'create' | 'update' | 'delete' },\n  ): Promise<void> {\n    const config = this.environment.getTopLevelConfig()\n    await this.hookParallel(\n      'watchChange',\n      (plugin) => this._getPluginContext(plugin),\n      () => [id, change],\n      (plugin) =>\n        this.environment.name === 'client' ||\n        config.server.perEnvironmentWatchChangeDuringDev ||\n        plugin.perEnvironmentWatchChangeDuringDev,\n    )\n  }\n\n  async close(): Promise<void> {\n    if (this._closed) return\n    this._closed = true\n    await Promise.allSettled(Array.from(this._processesing))\n    const config = this.environment.getTopLevelConfig()\n    await this.hookParallel(\n      'buildEnd',\n      (plugin) => this._getPluginContext(plugin),\n      () => [],\n      (plugin) =>\n        this.environment.name === 'client' ||\n        config.server.perEnvironmentStartEndDuringDev ||\n        plugin.perEnvironmentStartEndDuringDev,\n    )\n    await this.hookParallel(\n      'closeBundle',\n      (plugin) => this._getPluginContext(plugin),\n      () => [],\n    )\n  }\n}\n\nexport const basePluginContextMeta: {\n  viteVersion: string\n  rollupVersion: string\n  rolldownVersion: string\n} = {\n  viteVersion,\n  rollupVersion,\n  rolldownVersion,\n}\n\nexport class BasicMinimalPluginContext<Meta = PluginContextMeta> {\n  constructor(\n    public meta: Meta,\n    private _logger: Logger,\n  ) {}\n\n  // FIXME: properly support this later\n  // eslint-disable-next-line @typescript-eslint/class-literal-property-style\n  get pluginName(): string {\n    return ''\n  }\n\n  debug(rawLog: string | RollupLog | (() => string | RollupLog)): void {\n    const log = this._normalizeRawLog(rawLog)\n    const msg = buildErrorMessage(log, [`debug: ${log.message}`], false)\n    debugPluginContainerContext?.(msg)\n  }\n\n  info(rawLog: string | RollupLog | (() => string | RollupLog)): void {\n    const log = this._normalizeRawLog(rawLog)\n    const msg = buildErrorMessage(log, [`info: ${log.message}`], false)\n    this._logger.info(msg, { clear: true, timestamp: true })\n  }\n\n  warn(rawLog: string | RollupLog | (() => string | RollupLog)): void {\n    const log = this._normalizeRawLog(rawLog)\n    const msg = buildErrorMessage(\n      log,\n      [colors.yellow(`warning: ${log.message}`)],\n      false,\n    )\n    this._logger.warn(msg, { clear: true, timestamp: true })\n  }\n\n  error(e: string | RollupError): never {\n    const err = (typeof e === 'string' ? new Error(e) : e) as RollupError\n    throw err\n  }\n\n  private _normalizeRawLog(\n    rawLog: string | RollupLog | (() => string | RollupLog),\n  ): RollupLog {\n    const logValue = typeof rawLog === 'function' ? rawLog() : rawLog\n    return typeof logValue === 'string' ? new Error(logValue) : logValue\n  }\n}\n\nclass MinimalPluginContext<T extends Environment = Environment>\n  extends BasicMinimalPluginContext\n  implements RollupMinimalPluginContext\n{\n  public environment: T\n  constructor(meta: PluginContextMeta, environment: T) {\n    super(meta, environment.logger)\n    this.environment = environment\n  }\n}\n\nconst fsModule: RollupFsModule = {\n  appendFile: fsp.appendFile,\n  copyFile: fsp.copyFile,\n  mkdir: fsp.mkdir as RollupFsModule['mkdir'],\n  mkdtemp: fsp.mkdtemp,\n  readdir: fsp.readdir,\n  readFile: fsp.readFile as RollupFsModule['readFile'],\n  realpath: fsp.realpath,\n  rename: fsp.rename,\n  rmdir: fsp.rmdir,\n  stat: fsp.stat,\n  lstat: fsp.lstat,\n  unlink: fsp.unlink,\n  writeFile: fsp.writeFile,\n}\n\nclass PluginContext\n  extends MinimalPluginContext\n  implements Omit<RollupPluginContext, 'cache'>\n{\n  ssr = false\n  _scan = false\n  _activeId: string | null = null\n  _activeCode: string | null = null\n  _resolveSkips?: Set<Plugin>\n  _resolveSkipCalls?: readonly SkipInformation[]\n\n  override get pluginName(): string {\n    return this._plugin.name\n  }\n\n  constructor(\n    public _plugin: Plugin,\n    public _container: EnvironmentPluginContainer,\n  ) {\n    super(_container.minimalContext.meta, _container.environment)\n  }\n\n  fs: RollupFsModule = fsModule\n\n  parse(code: string, opts: any): ESTree.Program {\n    return rolldownParseAst(code, opts)\n  }\n\n  async resolve(\n    id: string,\n    importer?: string,\n    options?: {\n      attributes?: Record<string, string>\n      custom?: CustomPluginOptions\n      isEntry?: boolean\n      skipSelf?: boolean\n    },\n  ): Promise<ResolvedId | null> {\n    let skipCalls: readonly SkipInformation[] | undefined\n    if (options?.skipSelf === false) {\n      skipCalls = this._resolveSkipCalls\n    } else if (this._resolveSkipCalls) {\n      const skipCallsTemp = [...this._resolveSkipCalls]\n      const sameCallIndex = this._resolveSkipCalls.findIndex(\n        (c) =>\n          c.id === id && c.importer === importer && c.plugin === this._plugin,\n      )\n      if (sameCallIndex !== -1) {\n        skipCallsTemp[sameCallIndex] = {\n          ...skipCallsTemp[sameCallIndex],\n          called: true,\n        }\n      } else {\n        skipCallsTemp.push({ id, importer, plugin: this._plugin })\n      }\n      skipCalls = skipCallsTemp\n    } else {\n      skipCalls = [{ id, importer, plugin: this._plugin }]\n    }\n\n    let out = await this._container.resolveId(id, importer, {\n      attributes: options?.attributes,\n      custom: options?.custom,\n      isEntry: !!options?.isEntry,\n      skip: this._resolveSkips,\n      skipCalls,\n      scan: this._scan,\n    })\n    if (typeof out === 'string') out = { id: out }\n    return out as ResolvedId | null\n  }\n\n  async load(\n    options: {\n      id: string\n      resolveDependencies?: boolean\n    } & Partial<PartialNull<ModuleOptions>>,\n  ): Promise<ModuleInfo> {\n    // We may not have added this to our module graph yet, so ensure it exists\n    await this._container.moduleGraph?.ensureEntryFromUrl(unwrapId(options.id))\n    // Not all options passed to this function make sense in the context of loading individual files,\n    // but we can at least update the module info properties we support\n    this._updateModuleInfo(options.id, options)\n\n    const loadResult = await this._container.load(options.id)\n    const code = typeof loadResult === 'object' ? loadResult?.code : loadResult\n    if (code != null) {\n      await this._container.transform(code, options.id)\n    }\n\n    const moduleInfo = this.getModuleInfo(options.id)\n    // This shouldn't happen due to calling ensureEntryFromUrl, but 1) our types can't ensure that\n    // and 2) moduleGraph may not have been provided (though in the situations where that happens,\n    // we should never have plugins calling this.load)\n    if (!moduleInfo) throw Error(`Failed to load module with id ${options.id}`)\n    return moduleInfo\n  }\n\n  getModuleInfo(id: string): ModuleInfo | null {\n    return this._container.getModuleInfo(id)\n  }\n\n  _updateModuleInfo(id: string, { meta }: { meta?: object | null }): void {\n    if (meta) {\n      const moduleInfo = this.getModuleInfo(id)\n      if (moduleInfo) {\n        moduleInfo.meta = { ...moduleInfo.meta, ...meta }\n      }\n    }\n  }\n\n  getModuleIds(): IterableIterator<string> {\n    return this._container.moduleGraph\n      ? this._container.moduleGraph.idToModuleMap.keys()\n      : Array.prototype[Symbol.iterator]()\n  }\n\n  addWatchFile(id: string): void {\n    this._container.watchFiles.add(id)\n    if (this._container.watcher)\n      ensureWatchedFile(\n        this._container.watcher,\n        id,\n        this.environment.config.root,\n      )\n  }\n\n  getWatchFiles(): string[] {\n    return [...this._container.watchFiles]\n  }\n\n  emitFile(_assetOrFile: EmittedFile): string {\n    this._warnIncompatibleMethod(`emitFile`)\n    return ''\n  }\n\n  setAssetSource(): void {\n    this._warnIncompatibleMethod(`setAssetSource`)\n  }\n\n  getFileName(): string {\n    this._warnIncompatibleMethod(`getFileName`)\n    return ''\n  }\n\n  override debug(log: string | RollupLog | (() => string | RollupLog)): void {\n    const err = this._formatLog(typeof log === 'function' ? log() : log)\n    super.debug(err)\n  }\n\n  override info(log: string | RollupLog | (() => string | RollupLog)): void {\n    const err = this._formatLog(typeof log === 'function' ? log() : log)\n    super.info(err)\n  }\n\n  override warn(\n    log: string | RollupLog | (() => string | RollupLog),\n    position?: number | { column: number; line: number },\n  ): void {\n    const err = this._formatLog(\n      typeof log === 'function' ? log() : log,\n      position,\n    )\n    super.warn(err)\n  }\n\n  override error(\n    e: string | RollupError,\n    position?: number | { column: number; line: number },\n  ): never {\n    // error thrown here is caught by the transform middleware and passed on\n    // the error middleware.\n    throw this._formatLog(e, position)\n  }\n\n  private _formatLog<E extends RollupLog>(\n    e: string | E,\n    position?: number | { column: number; line: number } | undefined,\n  ): E {\n    const err = (typeof e === 'string' ? new Error(e) : e) as E\n    if (err.pluginCode) {\n      return err // The plugin likely called `this.error`\n    }\n    err.plugin = this._plugin.name\n    if (this._activeId && !err.id) err.id = this._activeId\n    if (this._activeCode) {\n      err.pluginCode = this._activeCode\n\n      // some rollup plugins, e.g. json, sets err.position instead of err.pos\n      const pos = position ?? err.pos ?? (err as any).position\n\n      if (pos != null) {\n        let errLocation\n        try {\n          errLocation = numberToPos(this._activeCode, pos)\n        } catch (err2) {\n          this.environment.logger.error(\n            colors.red(\n              `Error in error handler:\\n${err2.stack || err2.message}\\n`,\n            ),\n            // print extra newline to separate the two errors\n            { error: err2 },\n          )\n          throw err\n        }\n        err.loc = err.loc || {\n          file: err.id,\n          ...errLocation,\n        }\n        err.frame = err.frame || generateCodeFrame(this._activeCode, pos)\n      } else if (err.loc) {\n        // css preprocessors may report errors in an included file\n        if (!err.frame) {\n          let code = this._activeCode\n          if (err.loc.file) {\n            err.id = normalizePath(err.loc.file)\n            try {\n              code = fs.readFileSync(err.loc.file, 'utf-8')\n            } catch {}\n          }\n          err.frame = generateCodeFrame(code, err.loc)\n        }\n      } else if ((err as any).line && (err as any).column) {\n        err.loc = {\n          file: err.id,\n          line: (err as any).line,\n          column: (err as any).column,\n        }\n        err.frame = err.frame || generateCodeFrame(this._activeCode, err.loc)\n      }\n\n      // TODO: move it to overrides\n      if (\n        this instanceof TransformPluginContext &&\n        typeof err.loc?.line === 'number' &&\n        typeof err.loc.column === 'number'\n      ) {\n        const rawSourceMap = this._getCombinedSourcemap()\n        if (rawSourceMap && 'version' in rawSourceMap) {\n          const traced = new TraceMap(rawSourceMap as any)\n          const { source, line, column } = originalPositionFor(traced, {\n            line: Number(err.loc.line),\n            column: Number(err.loc.column),\n          })\n          if (source) {\n            err.loc = { file: source, line, column }\n          }\n        }\n      }\n    } else if (err.loc) {\n      if (!err.frame) {\n        let code = err.pluginCode\n        if (err.loc.file) {\n          err.id = normalizePath(err.loc.file)\n          if (!code) {\n            try {\n              code = fs.readFileSync(err.loc.file, 'utf-8')\n            } catch {}\n          }\n        }\n        if (code) {\n          err.frame = generateCodeFrame(`${code}`, err.loc)\n        }\n      }\n    }\n\n    if (\n      typeof err.loc?.column !== 'number' &&\n      typeof err.loc?.line !== 'number' &&\n      !err.loc?.file\n    ) {\n      delete err.loc\n    }\n\n    return err\n  }\n\n  _warnIncompatibleMethod(method: string): void {\n    this.environment.logger.warn(\n      colors.cyan(`[plugin:${this._plugin.name}] `) +\n        colors.yellow(\n          `context method ${colors.bold(\n            `${method}()`,\n          )} is not supported in serve mode. This plugin is likely not vite-compatible.`,\n        ),\n    )\n  }\n}\n\nclass ResolveIdContext extends PluginContext {\n  constructor(\n    container: EnvironmentPluginContainer,\n    skip: Set<Plugin> | undefined,\n    skipCalls: readonly SkipInformation[] | undefined,\n    scan: boolean,\n  ) {\n    super(null!, container)\n    this._resolveSkips = skip\n    this._resolveSkipCalls = skipCalls\n    this._scan = scan\n  }\n}\n\nclass LoadPluginContext extends PluginContext {\n  _addedImports: Set<string> | null = null\n\n  constructor(container: EnvironmentPluginContainer) {\n    super(null!, container)\n  }\n\n  override addWatchFile(id: string): void {\n    if (!this._addedImports) {\n      this._addedImports = new Set()\n    }\n    this._addedImports.add(id)\n    super.addWatchFile(id)\n  }\n}\n\nclass TransformPluginContext\n  extends LoadPluginContext\n  implements Omit<RollupTransformPluginContext, 'cache'>\n{\n  filename: string\n  originalCode: string\n  originalSourcemap: SourceMap | null = null\n  sourcemapChain: NonNullable<SourceDescription['map']>[] = []\n  combinedMap: SourceMap | { mappings: '' } | null = null\n\n  constructor(\n    container: EnvironmentPluginContainer,\n    id: string,\n    code: string,\n    inMap?: SourceMap | string,\n  ) {\n    super(container)\n\n    this.filename = id\n    this.originalCode = code\n    if (inMap) {\n      if (debugSourcemapCombine) {\n        // @ts-expect-error inject name for debug purpose\n        inMap.name = '$inMap'\n      }\n      this.sourcemapChain.push(inMap)\n    }\n  }\n\n  _getCombinedSourcemap(): SourceMap | { mappings: '' } | null {\n    if (\n      debugSourcemapCombine &&\n      debugSourcemapCombineFilter &&\n      this.filename.includes(debugSourcemapCombineFilter)\n    ) {\n      debugSourcemapCombine('----------', this.filename)\n      debugSourcemapCombine(this.combinedMap)\n      debugSourcemapCombine(this.sourcemapChain)\n      debugSourcemapCombine('----------')\n    }\n\n    let combinedMap = this.combinedMap\n    // { mappings: '' }\n    if (\n      combinedMap &&\n      !('version' in combinedMap) &&\n      combinedMap.mappings === ''\n    ) {\n      this.sourcemapChain.length = 0\n      return combinedMap\n    }\n\n    for (let m of this.sourcemapChain) {\n      if (typeof m === 'string') m = JSON.parse(m)\n      if (!('version' in (m as SourceMap))) {\n        // { mappings: '' }\n        if ((m as SourceMap).mappings === '') {\n          combinedMap = { mappings: '' }\n          break\n        }\n        // empty, nullified source map\n        combinedMap = null\n        break\n      }\n      if (!combinedMap) {\n        const sm = m as SourceMap\n        // sourcemap should not include `sources: [null]` (because `sources` should be string) nor\n        // `sources: ['']` (because `''` means the path of sourcemap)\n        // but MagicString generates this when `filename` option is not set.\n        // Rollup supports these and therefore we support this as well\n        if (sm.sources.length === 1 && !sm.sources[0]) {\n          combinedMap = {\n            ...sm,\n            sources: [this.filename],\n            sourcesContent: [this.originalCode],\n          }\n        } else {\n          combinedMap = sm\n        }\n      } else {\n        combinedMap = combineSourcemaps(cleanUrl(this.filename), [\n          m as RawSourceMap,\n          combinedMap as RawSourceMap,\n        ]) as SourceMap\n      }\n    }\n    if (combinedMap !== this.combinedMap) {\n      this.combinedMap = combinedMap\n      this.sourcemapChain.length = 0\n    }\n    return this.combinedMap\n  }\n\n  getCombinedSourcemap(): SourceMap {\n    const map = this._getCombinedSourcemap()\n    if (!map || (!('version' in map) && map.mappings === '')) {\n      return new MagicString(this.originalCode).generateMap({\n        includeContent: true,\n        hires: 'boundary',\n        source: cleanUrl(this.filename),\n      }) as SourceMap\n    }\n    return map\n  }\n\n  _updateActiveInfo(plugin: Plugin, id: string, code: string): void {\n    this._plugin = plugin\n    this._activeId = id\n    this._activeCode = code\n  }\n}\n\nexport type {\n  EnvironmentPluginContainer,\n  TransformPluginContext,\n  TransformResult,\n}\n\n// Backward compatibility\nclass PluginContainer {\n  constructor(private environments: Record<string, Environment>) {}\n\n  // Backward compatibility\n  // Users should call pluginContainer.resolveId (and load/transform) passing the environment they want to work with\n  // But there is code that is going to call it without passing an environment, or with the ssr flag to get the ssr environment\n  private _getEnvironment(options?: {\n    ssr?: boolean\n    environment?: Environment\n  }) {\n    return options?.environment\n      ? options.environment\n      : this.environments[options?.ssr ? 'ssr' : 'client']\n  }\n\n  private _getPluginContainer(options?: {\n    ssr?: boolean\n    environment?: Environment\n  }) {\n    return (this._getEnvironment(options) as DevEnvironment).pluginContainer\n  }\n\n  getModuleInfo(id: string): ModuleInfo | null {\n    const clientModuleInfo = (\n      this.environments.client as DevEnvironment\n    ).pluginContainer.getModuleInfo(id)\n    const ssrModuleInfo = (\n      this.environments.ssr as DevEnvironment\n    ).pluginContainer.getModuleInfo(id)\n\n    if (clientModuleInfo == null && ssrModuleInfo == null) return null\n\n    return new Proxy({} as any, {\n      get: (_, key: string) => {\n        // `meta` refers to `ModuleInfo.meta` of both environments, so we also\n        // need to merge it here\n        if (key === 'meta') {\n          const meta: Record<string, any> = {}\n          if (ssrModuleInfo) {\n            Object.assign(meta, ssrModuleInfo.meta)\n          }\n          if (clientModuleInfo) {\n            Object.assign(meta, clientModuleInfo.meta)\n          }\n          return meta\n        }\n        if (clientModuleInfo) {\n          if (key in clientModuleInfo) {\n            return clientModuleInfo[key as keyof ModuleInfo]\n          }\n        }\n        if (ssrModuleInfo) {\n          if (key in ssrModuleInfo) {\n            return ssrModuleInfo[key as keyof ModuleInfo]\n          }\n        }\n      },\n    })\n  }\n\n  get options(): InputOptions {\n    return (this.environments.client as DevEnvironment).pluginContainer.options\n  }\n\n  // For backward compatibility, buildStart and watchChange are called only for the client environment\n  // buildStart is called per environment for a plugin with the perEnvironmentStartEndDuringDev flag\n  // watchChange is called per environment for a plugin with the perEnvironmentWatchChangeDuringDev flag\n\n  async buildStart(_options?: InputOptions): Promise<void> {\n    return (\n      this.environments.client as DevEnvironment\n    ).pluginContainer.buildStart(_options)\n  }\n\n  async watchChange(\n    id: string,\n    change: { event: 'create' | 'update' | 'delete' },\n  ): Promise<void> {\n    return (\n      this.environments.client as DevEnvironment\n    ).pluginContainer.watchChange(id, change)\n  }\n\n  async resolveId(\n    rawId: string,\n    importer?: string,\n    options?: {\n      attributes?: Record<string, string>\n      custom?: CustomPluginOptions\n      /** @deprecated use `skipCalls` instead */\n      skip?: Set<Plugin>\n      skipCalls?: readonly SkipInformation[]\n      ssr?: boolean\n      /**\n       * @internal\n       */\n      scan?: boolean\n      isEntry?: boolean\n    },\n  ): Promise<PartialResolvedId | null> {\n    return this._getPluginContainer(options).resolveId(rawId, importer, options)\n  }\n\n  async load(\n    id: string,\n    options?: {\n      ssr?: boolean\n    },\n  ): Promise<LoadResult | null> {\n    return this._getPluginContainer(options).load(id)\n  }\n\n  async transform(\n    code: string,\n    id: string,\n    options?: {\n      ssr?: boolean\n      environment?: Environment\n      inMap?: SourceDescription['map']\n    },\n  ): Promise<{ code: string; map: SourceMap | { mappings: '' } | null }> {\n    return this._getPluginContainer(options).transform(code, id, options)\n  }\n\n  async close(): Promise<void> {\n    // noop, close will be called for each environment\n  }\n}\n\n/**\n * server.pluginContainer compatibility\n *\n * The default environment is in buildStart, buildEnd, watchChange, and closeBundle hooks,\n * which are called once for all environments, or when no environment is passed in other hooks.\n * The ssrEnvironment is needed for backward compatibility when the ssr flag is passed without\n * an environment. The defaultEnvironment in the main pluginContainer in the server should be\n * the client environment for backward compatibility.\n **/\nexport function createPluginContainer(\n  environments: Record<string, Environment>,\n): PluginContainer {\n  return new PluginContainer(environments)\n}\n\nexport type { PluginContainer }\n"
  },
  {
    "path": "packages/vite/src/node/server/searchRoot.ts",
    "content": "import fs from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { isFileReadable } from '../utils'\n\n// https://github.com/vitejs/vite/issues/2820#issuecomment-812495079\nconst ROOT_FILES = [\n  // '.git',\n\n  // https://pnpm.io/workspaces/\n  'pnpm-workspace.yaml',\n\n  // https://rushjs.io/pages/advanced/config_files/\n  // 'rush.json',\n\n  // https://nx.dev/latest/react/getting-started/nx-setup\n  // 'workspace.json',\n  // 'nx.json',\n\n  // https://github.com/lerna/lerna#lernajson\n  'lerna.json',\n]\n\n// npm: https://docs.npmjs.com/cli/v7/using-npm/workspaces#installing-workspaces\n// yarn: https://classic.yarnpkg.com/en/docs/workspaces/#toc-how-to-use-it\nfunction hasWorkspacePackageJSON(root: string): boolean {\n  const path = join(root, 'package.json')\n  if (!isFileReadable(path)) {\n    return false\n  }\n  try {\n    const content = JSON.parse(fs.readFileSync(path, 'utf-8')) || {}\n    return !!content.workspaces\n  } catch {\n    return false\n  }\n}\n\nfunction hasRootFile(root: string): boolean {\n  return ROOT_FILES.some((file) => fs.existsSync(join(root, file)))\n}\n\nfunction hasPackageJSON(root: string) {\n  const path = join(root, 'package.json')\n  return fs.existsSync(path)\n}\n\n/**\n * Search up for the nearest `package.json`\n */\nexport function searchForPackageRoot(\n  current: string,\n  root: string = current,\n): string {\n  if (hasPackageJSON(current)) return current\n\n  const dir = dirname(current)\n  // reach the fs root\n  if (!dir || dir === current) return root\n\n  return searchForPackageRoot(dir, root)\n}\n\n/**\n * Search up for the nearest workspace root\n */\nexport function searchForWorkspaceRoot(\n  current: string,\n  root: string = searchForPackageRoot(current),\n): string {\n  if (hasRootFile(current)) return current\n  if (hasWorkspacePackageJSON(current)) return current\n\n  const dir = dirname(current)\n  // reach the fs root\n  if (!dir || dir === current) return root\n\n  return searchForWorkspaceRoot(dir, root)\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/send.ts",
    "content": "import type {\n  IncomingMessage,\n  OutgoingHttpHeaders,\n  ServerResponse,\n} from 'node:http'\nimport path from 'node:path'\nimport convertSourceMap from 'convert-source-map'\nimport getEtag from 'etag'\nimport type { SourceMap } from 'rolldown'\nimport MagicString from 'magic-string'\nimport { createDebugger, removeTimestampQuery } from '../utils'\nimport { getCodeWithSourcemap } from './sourcemap'\n\nconst debug = createDebugger('vite:send', {\n  onlyWhenFocused: true,\n})\n\nconst alias: Record<string, string | undefined> = {\n  js: 'text/javascript',\n  css: 'text/css',\n  html: 'text/html',\n  json: 'application/json',\n}\n\nexport interface SendOptions {\n  etag?: string\n  cacheControl?: string\n  headers?: OutgoingHttpHeaders\n  map?: SourceMap | { mappings: '' } | null\n}\n\nexport function send(\n  req: IncomingMessage,\n  res: ServerResponse,\n  content: string | Buffer,\n  type: string,\n  options: SendOptions,\n): void {\n  const {\n    etag = getEtag(content, { weak: true }),\n    cacheControl = 'no-cache',\n    headers,\n    map,\n  } = options\n\n  if (res.writableEnded) {\n    return\n  }\n\n  if (req.headers['if-none-match'] === etag) {\n    res.statusCode = 304\n    res.end()\n    return\n  }\n\n  res.setHeader('Content-Type', alias[type] || type)\n  res.setHeader('Cache-Control', cacheControl)\n  res.setHeader('Etag', etag)\n\n  if (headers) {\n    for (const name in headers) {\n      res.setHeader(name, headers[name]!)\n    }\n  }\n\n  // inject source map reference\n  if (map && 'version' in map && map.mappings) {\n    if (type === 'js' || type === 'css') {\n      content = getCodeWithSourcemap(type, content.toString(), map)\n    }\n  }\n  // inject fallback sourcemap for js for improved debugging\n  // https://github.com/vitejs/vite/pull/13514#issuecomment-1592431496\n  else if (type === 'js' && (!map || map.mappings !== '')) {\n    const code = content.toString()\n    // if the code has existing inline sourcemap, assume it's correct and skip\n    if (convertSourceMap.mapFileCommentRegex.test(code)) {\n      debug?.(`Skipped injecting fallback sourcemap for ${req.url}`)\n    } else {\n      const urlWithoutTimestamp = removeTimestampQuery(req.url!)\n      const ms = new MagicString(code)\n      content = getCodeWithSourcemap(\n        type,\n        code,\n        ms.generateMap({\n          source: path.basename(urlWithoutTimestamp),\n          hires: 'boundary',\n          includeContent: true,\n        }) as SourceMap,\n      )\n    }\n  }\n\n  res.statusCode = 200\n  if (req.method === 'HEAD') {\n    res.end()\n  } else {\n    res.end(content)\n  }\n  return\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/sourcemap.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport fsp from 'node:fs/promises'\nimport convertSourceMap from 'convert-source-map'\nimport type { ExistingRawSourceMap, SourceMap } from 'rolldown'\nimport type { Logger } from '../logger'\nimport { blankReplacer, createDebugger } from '../utils'\nimport { cleanUrl } from '../../shared/utils'\n\nconst debug = createDebugger('vite:sourcemap', {\n  onlyWhenFocused: true,\n})\n\n// Virtual modules should be prefixed with a null byte to avoid a\n// false positive \"missing source\" warning. We also check for certain\n// prefixes used for special handling in esbuildDepPlugin.\nconst virtualSourceRE = /^(?:dep:|browser-external:|virtual:)|\\0/\n\ninterface SourceMapLike {\n  sources: string[]\n  sourcesContent?: (string | null)[]\n  sourceRoot?: string\n}\n\nasync function computeSourceRoute(map: SourceMapLike, file: string) {\n  let sourceRoot: string | undefined\n  try {\n    // The source root is undefined for virtual modules and permission errors.\n    sourceRoot = await fsp.realpath(\n      path.resolve(path.dirname(file), map.sourceRoot || ''),\n    )\n  } catch {}\n  return sourceRoot\n}\n\nexport async function injectSourcesContent(\n  map: SourceMapLike,\n  file: string,\n  logger: Logger,\n): Promise<void> {\n  let sourceRootPromise: Promise<string | undefined>\n\n  const missingSources: string[] = []\n  const sourcesContent = map.sourcesContent || []\n  const sourcesContentPromises: Promise<void>[] = []\n  for (let index = 0; index < map.sources.length; index++) {\n    const sourcePath = map.sources[index]\n    if (\n      sourcesContent[index] == null &&\n      sourcePath &&\n      !virtualSourceRE.test(sourcePath)\n    ) {\n      sourcesContentPromises.push(\n        (async () => {\n          // inject content from source file when sourcesContent is null\n          sourceRootPromise ??= computeSourceRoute(map, file)\n          const sourceRoot = await sourceRootPromise\n          let resolvedSourcePath = cleanUrl(decodeURI(sourcePath))\n          if (sourceRoot) {\n            resolvedSourcePath = path.resolve(sourceRoot, resolvedSourcePath)\n          }\n\n          sourcesContent[index] = await fsp\n            .readFile(resolvedSourcePath, 'utf-8')\n            .catch(() => {\n              missingSources.push(resolvedSourcePath)\n              return null\n            })\n        })(),\n      )\n    }\n  }\n\n  await Promise.all(sourcesContentPromises)\n\n  map.sourcesContent = sourcesContent\n\n  // Use this command…\n  //    DEBUG=\"vite:sourcemap\" vite build\n  // …to log the missing sources.\n  if (missingSources.length) {\n    logger.warnOnce(`Sourcemap for \"${file}\" points to missing source files`)\n    debug?.(`Missing sources:\\n  ` + missingSources.join(`\\n  `))\n  }\n}\n\nexport function genSourceMapUrl(map: SourceMap | string): string {\n  if (typeof map !== 'string') {\n    map = JSON.stringify(map)\n  }\n  return `data:application/json;base64,${Buffer.from(map).toString('base64')}`\n}\n\nexport function getCodeWithSourcemap(\n  type: 'js' | 'css',\n  code: string,\n  map: SourceMap,\n): string {\n  if (debug) {\n    code += `\\n/*${JSON.stringify(map, null, 2).replace(/\\*\\//g, '*\\\\/')}*/\\n`\n  }\n\n  if (type === 'js') {\n    code += `\\n//# sourceMappingURL=${genSourceMapUrl(map)}`\n  } else if (type === 'css') {\n    code += `\\n/*# sourceMappingURL=${genSourceMapUrl(map)} */`\n  }\n\n  return code\n}\n\nexport function applySourcemapIgnoreList(\n  map: ExistingRawSourceMap,\n  sourcemapPath: string,\n  sourcemapIgnoreList: (sourcePath: string, sourcemapPath: string) => boolean,\n  logger?: Logger,\n): void {\n  let { x_google_ignoreList } = map\n  if (x_google_ignoreList === undefined) {\n    x_google_ignoreList = []\n  }\n  if (map.sources) {\n    for (\n      let sourcesIndex = 0;\n      sourcesIndex < map.sources.length;\n      ++sourcesIndex\n    ) {\n      const sourcePath = map.sources[sourcesIndex]\n      if (!sourcePath) continue\n\n      const ignoreList = sourcemapIgnoreList(\n        path.isAbsolute(sourcePath)\n          ? sourcePath\n          : path.resolve(path.dirname(sourcemapPath), sourcePath),\n        sourcemapPath,\n      )\n      if (logger && typeof ignoreList !== 'boolean') {\n        logger.warn('sourcemapIgnoreList function must return a boolean.')\n      }\n\n      if (ignoreList && !x_google_ignoreList.includes(sourcesIndex)) {\n        x_google_ignoreList.push(sourcesIndex)\n      }\n    }\n\n    if (x_google_ignoreList.length > 0) {\n      if (!map.x_google_ignoreList)\n        map.x_google_ignoreList = x_google_ignoreList\n    }\n  }\n}\n\nexport function extractSourcemapFromFile(\n  code: string,\n  filePath: string,\n): { code: string; map: SourceMap } | undefined {\n  const map = (\n    convertSourceMap.fromSource(code) ||\n    convertSourceMap.fromMapFileSource(\n      code,\n      createConvertSourceMapReadMap(filePath),\n    )\n  )?.toObject()\n\n  if (map) {\n    return {\n      code: code.replace(convertSourceMap.mapFileCommentRegex, blankReplacer),\n      map,\n    }\n  }\n}\n\nfunction createConvertSourceMapReadMap(originalFileName: string) {\n  return (filename: string) => {\n    return fs.readFileSync(\n      path.resolve(path.dirname(originalFileName), filename),\n      'utf-8',\n    )\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/transformRequest.ts",
    "content": "import fsp from 'node:fs/promises'\nimport path from 'node:path'\nimport { performance } from 'node:perf_hooks'\nimport getEtag from 'etag'\nimport MagicString from 'magic-string'\nimport { init, parse as parseImports } from 'es-module-lexer'\nimport type {\n  ModuleType,\n  PartialResolvedId,\n  SourceDescription,\n  SourceMap,\n} from 'rolldown'\nimport colors from 'picocolors'\nimport type { EnvironmentModuleNode } from '../server/moduleGraph'\nimport {\n  createDebugger,\n  ensureWatchedFile,\n  injectQuery,\n  isObject,\n  monotonicDateNow,\n  prettifyUrl,\n  removeImportQuery,\n  removeTimestampQuery,\n  stripBase,\n  timeFrom,\n} from '../utils'\nimport { ssrTransform } from '../ssr/ssrTransform'\nimport { checkPublicFile } from '../publicDir'\nimport { cleanUrl, slash, unwrapId } from '../../shared/utils'\nimport {\n  applySourcemapIgnoreList,\n  extractSourcemapFromFile,\n  injectSourcesContent,\n} from './sourcemap'\nimport { isFileLoadingAllowed } from './middlewares/static'\nimport { throwClosedServerError } from './pluginContainer'\nimport type { DevEnvironment } from './environment'\n\nexport const ERR_LOAD_URL = 'ERR_LOAD_URL'\nexport const ERR_LOAD_PUBLIC_URL = 'ERR_LOAD_PUBLIC_URL'\nexport const ERR_DENIED_ID = 'ERR_DENIED_ID'\n\nconst debugLoad = createDebugger('vite:load')\nconst debugTransform = createDebugger('vite:transform')\nconst debugCache = createDebugger('vite:cache')\n\nexport interface TransformResult {\n  code: string\n  map: SourceMap | { mappings: '' } | null\n  ssr?: boolean\n  etag?: string\n  deps?: string[]\n  dynamicDeps?: string[]\n}\n\nexport interface TransformOptions {\n  /**\n   * @deprecated inferred from environment\n   */\n  ssr?: boolean\n}\n\nexport interface TransformOptionsInternal {\n  /**\n   * @internal\n   */\n  allowId?: (id: string) => boolean\n}\n\n// TODO: This function could be moved to the DevEnvironment class.\n// It was already using private fields from the server before, and it now does\n// the same with environment._closing, environment._pendingRequests and\n// environment._registerRequestProcessing. Maybe it makes sense to keep it in\n// separate file to preserve the history or keep the DevEnvironment class cleaner,\n// but conceptually this is: `environment.transformRequest(url, options)`\n\nexport function transformRequest(\n  environment: DevEnvironment,\n  url: string,\n  options: TransformOptionsInternal = {},\n): Promise<TransformResult | null> {\n  if (environment._closing && environment.config.dev.recoverable)\n    throwClosedServerError()\n\n  // This module may get invalidated while we are processing it. For example\n  // when a full page reload is needed after the re-processing of pre-bundled\n  // dependencies when a missing dep is discovered. We save the current time\n  // to compare it to the last invalidation performed to know if we should\n  // cache the result of the transformation or we should discard it as stale.\n  //\n  // A module can be invalidated due to:\n  // 1. A full reload because of pre-bundling newly discovered deps\n  // 2. A full reload after a config change\n  // 3. The file that generated the module changed\n  // 4. Invalidation for a virtual module\n  //\n  // For 1 and 2, a new request for this module will be issued after\n  // the invalidation as part of the browser reloading the page. For 3 and 4\n  // there may not be a new request right away because of HMR handling.\n  // In all cases, the next time this module is requested, it should be\n  // re-processed.\n  //\n  // We save the timestamp when we start processing and compare it with the\n  // last time this module is invalidated\n  const timestamp = monotonicDateNow()\n\n  url = removeTimestampQuery(url)\n\n  const pending = environment._pendingRequests.get(url)\n  if (pending) {\n    return environment.moduleGraph.getModuleByUrl(url).then((module) => {\n      if (!module || pending.timestamp > module.lastInvalidationTimestamp) {\n        // The pending request is still valid, we can safely reuse its result\n        return pending.request\n      } else {\n        // Request 1 for module A     (pending.timestamp)\n        // Invalidate module A        (module.lastInvalidationTimestamp)\n        // Request 2 for module A     (timestamp)\n\n        // First request has been invalidated, abort it to clear the cache,\n        // then perform a new doTransform.\n        pending.abort()\n        return transformRequest(environment, url, options)\n      }\n    })\n  }\n\n  const request = doTransform(environment, url, options, timestamp)\n\n  // Avoid clearing the cache of future requests if aborted\n  let cleared = false\n  const clearCache = () => {\n    if (!cleared) {\n      environment._pendingRequests.delete(url)\n      cleared = true\n    }\n  }\n\n  // Cache the request and clear it once processing is done\n  environment._pendingRequests.set(url, {\n    request,\n    timestamp,\n    abort: clearCache,\n  })\n\n  return request.finally(clearCache)\n}\n\nasync function doTransform(\n  environment: DevEnvironment,\n  url: string,\n  options: TransformOptionsInternal,\n  timestamp: number,\n) {\n  const { pluginContainer } = environment\n\n  let module = await environment.moduleGraph.getModuleByUrl(url)\n  if (module) {\n    // try use cache from url\n    const cached = await getCachedTransformResult(\n      environment,\n      url,\n      module,\n      timestamp,\n    )\n    if (cached) return cached\n  }\n\n  const resolved = module\n    ? undefined\n    : ((await pluginContainer.resolveId(url, undefined)) ?? undefined)\n\n  // resolve\n  const id = module?.id ?? resolved?.id ?? url\n\n  module ??= environment.moduleGraph.getModuleById(id)\n  if (module) {\n    // if a different url maps to an existing loaded id,  make sure we relate this url to the id\n    await environment.moduleGraph._ensureEntryFromUrl(url, undefined, resolved)\n    // try use cache from id\n    const cached = await getCachedTransformResult(\n      environment,\n      url,\n      module,\n      timestamp,\n    )\n    if (cached) return cached\n  }\n\n  const result = loadAndTransform(\n    environment,\n    id,\n    url,\n    options,\n    timestamp,\n    module,\n    resolved,\n  )\n\n  const { depsOptimizer } = environment\n  if (!depsOptimizer?.isOptimizedDepFile(id)) {\n    environment._registerRequestProcessing(id, () => result)\n  }\n\n  return result\n}\n\nasync function getCachedTransformResult(\n  environment: DevEnvironment,\n  url: string,\n  module: EnvironmentModuleNode,\n  timestamp: number,\n) {\n  const prettyUrl = debugCache ? prettifyUrl(url, environment.config.root) : ''\n\n  // tries to handle soft invalidation of the module if available,\n  // returns a boolean true is successful, or false if no handling is needed\n  const softInvalidatedTransformResult = await handleModuleSoftInvalidation(\n    environment,\n    module,\n    timestamp,\n  )\n  if (softInvalidatedTransformResult) {\n    debugCache?.(`[memory-hmr] ${prettyUrl}`)\n    return softInvalidatedTransformResult\n  }\n\n  // check if we have a fresh cache\n  const cached = module.transformResult\n  if (cached) {\n    debugCache?.(`[memory] ${prettyUrl}`)\n    return cached\n  }\n}\n\nasync function loadAndTransform(\n  environment: DevEnvironment,\n  id: string,\n  url: string,\n  options: TransformOptionsInternal,\n  timestamp: number,\n  mod?: EnvironmentModuleNode,\n  resolved?: PartialResolvedId,\n) {\n  const { config, pluginContainer, logger } = environment\n  const prettyUrl =\n    debugLoad || debugTransform ? prettifyUrl(url, config.root) : ''\n\n  const moduleGraph = environment.moduleGraph\n\n  if (options.allowId && !options.allowId(id)) {\n    const err: any = new Error(`Denied ID ${id}`)\n    err.code = ERR_DENIED_ID\n    err.id = id\n    throw err\n  }\n\n  let code: string | null = null\n  let map: SourceDescription['map'] = null\n  let moduleType: ModuleType | undefined\n\n  // load\n  const loadStart = debugLoad ? performance.now() : 0\n  const loadResult = await pluginContainer.load(id)\n\n  if (loadResult == null) {\n    const file = cleanUrl(id)\n\n    // try fallback loading it from fs as string\n    // if the file is a binary, there should be a plugin that already loaded it\n    // as string\n    // only try the fallback if access is allowed, skip for out of root url\n    // like /service-worker.js or /api/users\n    if (\n      environment.config.consumer === 'server' ||\n      isFileLoadingAllowed(environment.getTopLevelConfig(), slash(file))\n    ) {\n      try {\n        code = await fsp.readFile(file, 'utf-8')\n        debugLoad?.(`${timeFrom(loadStart)} [fs] ${prettyUrl}`)\n      } catch (e) {\n        if (e.code !== 'ENOENT' && e.code !== 'EISDIR') {\n          throw e\n        }\n      }\n      if (code != null && environment.pluginContainer.watcher) {\n        ensureWatchedFile(\n          environment.pluginContainer.watcher,\n          file,\n          config.root,\n        )\n      }\n    }\n    if (code) {\n      try {\n        const extracted = extractSourcemapFromFile(code, file)\n        if (extracted) {\n          code = extracted.code\n          map = extracted.map\n        }\n      } catch (e) {\n        logger.warn(`Failed to load source map for ${file}.\\n${e}`, {\n          timestamp: true,\n        })\n      }\n    }\n  } else {\n    debugLoad?.(`${timeFrom(loadStart)} [plugin] ${prettyUrl}`)\n    if (isObject(loadResult)) {\n      code = loadResult.code\n      map = loadResult.map\n      moduleType = loadResult.moduleType\n    } else {\n      code = loadResult\n    }\n  }\n  if (code == null) {\n    const isPublicFile = checkPublicFile(url, environment.getTopLevelConfig())\n    let publicDirName = path.relative(config.root, config.publicDir)\n    if (publicDirName[0] !== '.') publicDirName = '/' + publicDirName\n    const msg = isPublicFile\n      ? `This file is in ${publicDirName} and will be copied as-is during ` +\n        `build without going through the plugin transforms, and therefore ` +\n        `should not be imported from source code. It can only be referenced ` +\n        `via HTML tags.`\n      : `Does the file exist?`\n    const importerMod: EnvironmentModuleNode | undefined =\n      moduleGraph.idToModuleMap.get(id)?.importers.values().next().value\n    const importer = importerMod?.file || importerMod?.url\n    const err: any = new Error(\n      `Failed to load url ${url} (resolved id: ${id})${\n        importer ? ` in ${importer}` : ''\n      }. ${msg}`,\n    )\n    err.code = isPublicFile ? ERR_LOAD_PUBLIC_URL : ERR_LOAD_URL\n    throw err\n  }\n  if (moduleType === undefined) {\n    const guessedModuleType = getModuleTypeFromId(id)\n    if (guessedModuleType && guessedModuleType !== 'js') {\n      moduleType = guessedModuleType\n    }\n  }\n\n  if (environment._closing && environment.config.dev.recoverable)\n    throwClosedServerError()\n\n  // ensure module in graph after successful load\n  mod ??= await moduleGraph._ensureEntryFromUrl(url, undefined, resolved)\n\n  // transform\n  const transformStart = debugTransform ? performance.now() : 0\n  const transformResult = await pluginContainer.transform(code, id, {\n    inMap: map,\n    moduleType,\n  })\n  const originalCode = code\n  if (transformResult.code === originalCode) {\n    // no transform applied, keep code as-is\n    debugTransform?.(\n      timeFrom(transformStart) + colors.dim(` [skipped] ${prettyUrl}`),\n    )\n  } else {\n    debugTransform?.(`${timeFrom(transformStart)} ${prettyUrl}`)\n    code = transformResult.code!\n    map = transformResult.map\n  }\n\n  let normalizedMap: SourceMap | { mappings: '' } | null\n  if (typeof map === 'string') {\n    normalizedMap = JSON.parse(map)\n  } else if (map) {\n    normalizedMap = map as SourceMap | { mappings: '' }\n  } else {\n    normalizedMap = null\n  }\n\n  if (normalizedMap && 'version' in normalizedMap && mod.file) {\n    if (normalizedMap.mappings) {\n      await injectSourcesContent(normalizedMap, mod.file, logger)\n    }\n\n    const sourcemapPath = `${mod.file}.map`\n    applySourcemapIgnoreList(\n      normalizedMap,\n      sourcemapPath,\n      config.server.sourcemapIgnoreList,\n      logger,\n    )\n\n    if (path.isAbsolute(mod.file)) {\n      let modDirname\n      for (\n        let sourcesIndex = 0;\n        sourcesIndex < normalizedMap.sources.length;\n        ++sourcesIndex\n      ) {\n        const sourcePath = normalizedMap.sources[sourcesIndex]\n        if (sourcePath) {\n          // Rewrite sources to relative paths to give debuggers the chance\n          // to resolve and display them in a meaningful way (rather than\n          // with absolute paths).\n          if (path.isAbsolute(sourcePath)) {\n            modDirname ??= path.dirname(mod.file)\n            normalizedMap.sources[sourcesIndex] = path.relative(\n              modDirname,\n              sourcePath,\n            )\n          }\n        }\n      }\n    }\n  }\n\n  if (environment._closing && environment.config.dev.recoverable)\n    throwClosedServerError()\n\n  const topLevelConfig = environment.getTopLevelConfig()\n  const result = environment.config.dev.moduleRunnerTransform\n    ? await ssrTransform(code, normalizedMap, url, originalCode, {\n        json: {\n          stringify:\n            topLevelConfig.json.stringify === true &&\n            topLevelConfig.json.namedExports !== true,\n        },\n      })\n    : ({\n        code,\n        map: normalizedMap,\n        etag: getEtag(code, { weak: true }),\n      } satisfies TransformResult)\n\n  // Only cache the result if the module wasn't invalidated while it was\n  // being processed, so it is re-processed next time if it is stale\n  if (timestamp > mod.lastInvalidationTimestamp)\n    moduleGraph.updateModuleTransformResult(mod, result)\n\n  return result\n}\n\n/**\n * When a module is soft-invalidated, we can preserve its previous `transformResult` and\n * return similar code to before:\n *\n * - Client: We need to transform the import specifiers with new timestamps\n * - SSR: We don't need to change anything as `ssrLoadModule` controls it\n */\nasync function handleModuleSoftInvalidation(\n  environment: DevEnvironment,\n  mod: EnvironmentModuleNode,\n  timestamp: number,\n) {\n  const transformResult = mod.invalidationState\n\n  // Reset invalidation state\n  mod.invalidationState = undefined\n\n  // Skip if not soft-invalidated\n  if (!transformResult || transformResult === 'HARD_INVALIDATED') return\n\n  if (mod.transformResult) {\n    throw new Error(\n      `Internal server error: Soft-invalidated module \"${mod.url}\" should not have existing transform result`,\n    )\n  }\n\n  let result: TransformResult\n  // For SSR soft-invalidation, no transformation is needed\n  if (transformResult.ssr) {\n    result = transformResult\n  }\n  // We need to transform each imports with new timestamps if available\n  else {\n    await init\n    const source = transformResult.code\n    const s = new MagicString(source)\n    const [imports] = parseImports(source, mod.id || undefined)\n\n    for (const imp of imports) {\n      let rawUrl = source.slice(imp.s, imp.e)\n      if (rawUrl === 'import.meta') continue\n\n      const hasQuotes = rawUrl[0] === '\"' || rawUrl[0] === \"'\"\n      if (hasQuotes) {\n        rawUrl = rawUrl.slice(1, -1)\n      }\n\n      const urlWithoutTimestamp = removeTimestampQuery(rawUrl)\n      // hmrUrl must be derived the same way as importAnalysis\n      const hmrUrl = unwrapId(\n        stripBase(\n          removeImportQuery(urlWithoutTimestamp),\n          environment.config.base,\n        ),\n      )\n      for (const importedMod of mod.importedModules) {\n        if (importedMod.url !== hmrUrl) continue\n        if (importedMod.lastHMRTimestamp > 0) {\n          const replacedUrl = injectQuery(\n            urlWithoutTimestamp,\n            `t=${importedMod.lastHMRTimestamp}`,\n          )\n          const start = hasQuotes ? imp.s + 1 : imp.s\n          const end = hasQuotes ? imp.e - 1 : imp.e\n          s.overwrite(start, end, replacedUrl)\n        }\n\n        if (imp.d === -1 && environment.config.dev.preTransformRequests) {\n          // pre-transform known direct imports\n          environment.warmupRequest(hmrUrl)\n        }\n\n        break\n      }\n    }\n\n    // Update `transformResult` with new code. We don't have to update the sourcemap\n    // as the timestamp changes doesn't affect the code lines (stable).\n    const code = s.toString()\n    result = {\n      ...transformResult,\n      code,\n      etag: getEtag(code, { weak: true }),\n    }\n  }\n\n  // Only cache the result if the module wasn't invalidated while it was\n  // being processed, so it is re-processed next time if it is stale\n  if (timestamp > mod.lastInvalidationTimestamp)\n    environment.moduleGraph.updateModuleTransformResult(mod, result)\n\n  return result\n}\n\n// https://github.com/rolldown/rolldown/blob/cc66f4b7189dfb3a248608d02f5962edb09b11f8/crates/rolldown/src/utils/normalize_options.rs#L95-L111\nconst defaultModuleTypes: Record<string, ModuleType | undefined> = {\n  js: 'js',\n  mjs: 'js',\n  cjs: 'js',\n  jsx: 'jsx',\n  ts: 'ts',\n  mts: 'ts',\n  cts: 'ts',\n  tsx: 'tsx',\n  json: 'json',\n  txt: 'text',\n  css: 'css',\n}\n\n// https://github.com/rolldown/rolldown/blob/bf53a100edf1780d5a5aa41f0bc0459c5696543e/crates/rolldown/src/utils/load_source.rs#L53-L89\nexport function getModuleTypeFromId(id: string): ModuleType | undefined {\n  let pos = -1\n  while ((pos = id.indexOf('.', pos + 1)) >= 0) {\n    const ext = id.slice(pos + 1)\n    const moduleType = defaultModuleTypes[ext]\n    if (moduleType) {\n      return moduleType\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/warmup.ts",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport colors from 'picocolors'\nimport { glob, isDynamicPattern } from 'tinyglobby'\nimport { FS_PREFIX } from '../constants'\nimport { normalizePath } from '../utils'\nimport type { ViteDevServer } from '../index'\nimport type { DevEnvironment } from './environment'\n\nexport function warmupFiles(\n  server: ViteDevServer,\n  environment: DevEnvironment,\n): void {\n  const { root } = server.config\n  mapFiles(environment.config.dev.warmup, root).then((files) => {\n    for (const file of files) {\n      warmupFile(server, environment, file)\n    }\n  })\n}\n\nasync function warmupFile(\n  server: ViteDevServer,\n  environment: DevEnvironment,\n  file: string,\n) {\n  // transform html with the `transformIndexHtml` hook as Vite internals would\n  // pre-transform the imported JS modules linked. this may cause `transformIndexHtml`\n  // plugins to be executed twice, but that's probably fine.\n  if (file.endsWith('.html')) {\n    const url = htmlFileToUrl(file, server.config.root)\n    if (url) {\n      try {\n        const html = await fs.readFile(file, 'utf-8')\n        await server.transformIndexHtml(url, html)\n      } catch (e) {\n        // Unexpected error, log the issue but avoid an unhandled exception\n        environment.logger.error(\n          `Pre-transform error (${colors.cyan(file)}): ${e.message}`,\n          {\n            error: e,\n            timestamp: true,\n          },\n        )\n      }\n    }\n  }\n  // for other files, pass it through `transformRequest` with warmup\n  else {\n    const url = fileToUrl(file, server.config.root)\n    await environment.warmupRequest(url)\n  }\n}\n\nfunction htmlFileToUrl(file: string, root: string) {\n  const url = path.relative(root, file)\n  // out of root, ignore file\n  if (url[0] === '.') return\n  // file within root, create root-relative url\n  return '/' + normalizePath(url)\n}\n\nfunction fileToUrl(file: string, root: string) {\n  const url = path.relative(root, file)\n  // out of root, use /@fs/ prefix\n  if (url[0] === '.') {\n    return path.posix.join(FS_PREFIX, normalizePath(file))\n  }\n  // file within root, create root-relative url\n  return '/' + normalizePath(url)\n}\n\nasync function mapFiles(files: string[], root: string) {\n  if (!files.length) return []\n\n  const result: string[] = []\n  const globs: string[] = []\n  for (const file of files) {\n    if (isDynamicPattern(file)) {\n      globs.push(file)\n    } else {\n      if (path.isAbsolute(file)) {\n        result.push(file)\n      } else {\n        result.push(path.resolve(root, file))\n      }\n    }\n  }\n  if (globs.length) {\n    result.push(\n      ...(await glob(globs, {\n        absolute: true,\n        cwd: root,\n        expandDirectories: false,\n        ignore: ['**/.git/**', '**/node_modules/**'],\n      })),\n    )\n  }\n  return result\n}\n"
  },
  {
    "path": "packages/vite/src/node/server/ws.ts",
    "content": "import path from 'node:path'\nimport type { IncomingMessage, Server } from 'node:http'\nimport { STATUS_CODES, createServer as createHttpServer } from 'node:http'\nimport type { ServerOptions as HttpsServerOptions } from 'node:https'\nimport { createServer as createHttpsServer } from 'node:https'\nimport type { Socket } from 'node:net'\nimport type { Duplex } from 'node:stream'\nimport crypto from 'node:crypto'\nimport colors from 'picocolors'\nimport type { WebSocket as WebSocketRaw } from 'ws'\nimport { WebSocketServer as WebSocketServerRaw_ } from 'ws'\nimport { isHostAllowed } from 'host-validation-middleware'\nimport type { WebSocket as WebSocketTypes } from '#dep-types/ws'\nimport type {\n  ErrorPayload,\n  FullReloadPayload,\n  HotPayload,\n} from '#types/hmrPayload'\nimport type { InferCustomEventPayload } from '#types/customEvent'\nimport type { ResolvedConfig } from '..'\nimport { isObject } from '../utils'\nimport type { NormalizedHotChannel, NormalizedHotChannelClient } from './hmr'\nimport { normalizeHotChannel } from './hmr'\nimport type { HttpServer } from '.'\n\n/* In Bun, the `ws` module is overridden to hook into the native code. Using the bundled `js` version\n * of `ws` will not work as Bun's req.socket does not allow reading/writing to the underlying socket.\n */\nconst WebSocketServerRaw = process.versions.bun\n  ? // @ts-expect-error: Bun defines `import.meta.require`\n    import.meta.require('ws').WebSocketServer\n  : WebSocketServerRaw_\n\nexport const HMR_HEADER = 'vite-hmr'\n\nexport type WebSocketCustomListener<T> = (\n  data: T,\n  client: WebSocketClient,\n) => void\n\nexport const isWebSocketServer: unique symbol = Symbol('isWebSocketServer')\n\nexport interface WebSocketServer extends NormalizedHotChannel {\n  /**\n   * Handle custom event emitted by `import.meta.hot.send`\n   */\n  on: WebSocketTypes.Server['on'] & {\n    <T extends string>(\n      event: T,\n      listener: WebSocketCustomListener<InferCustomEventPayload<T>>,\n    ): void\n  }\n  /**\n   * Unregister event listener.\n   */\n  off: WebSocketTypes.Server['off'] & {\n    (event: string, listener: Function): void\n  }\n  /**\n   * Listen on port and host\n   */\n  listen(): void\n  /**\n   * Disconnect all clients and terminate the server.\n   */\n  close(): Promise<void>\n\n  [isWebSocketServer]: true\n  /**\n   * Get all connected clients.\n   */\n  clients: Set<WebSocketClient>\n}\n\nexport interface WebSocketClient extends NormalizedHotChannelClient {\n  /**\n   * The raw WebSocket instance\n   * @advanced\n   */\n  socket: WebSocketTypes\n}\n\nconst wsServerEvents = [\n  'connection',\n  'error',\n  'headers',\n  'listening',\n  'message',\n]\n\nfunction noop() {\n  // noop\n}\n\n// we only allow websockets to be connected if it has a valid token\n// this is to prevent untrusted origins to connect to the server\n// for example, Cross-site WebSocket hijacking\n//\n// we should check the token before calling wss.handleUpgrade\n// otherwise untrusted ws clients will be included in wss.clients\n//\n// using the query params means the token might be logged out in server or middleware logs\n// but we assume that is not an issue since the token is regenerated for each process\nfunction hasValidToken(config: ResolvedConfig, url: URL) {\n  const token = url.searchParams.get('token')\n  if (!token) return false\n\n  try {\n    const isValidToken = crypto.timingSafeEqual(\n      Buffer.from(token),\n      Buffer.from(config.webSocketToken),\n    )\n    return isValidToken\n  } catch {} // an error is thrown when the length is incorrect\n  return false\n}\n\nexport function createWebSocketServer(\n  server: HttpServer | null,\n  config: ResolvedConfig,\n  httpsOptions?: HttpsServerOptions,\n): WebSocketServer {\n  if (config.server.ws === false) {\n    return {\n      [isWebSocketServer]: true,\n      get clients() {\n        return new Set<WebSocketClient>()\n      },\n      async close() {\n        // noop\n      },\n      on: noop as any as WebSocketServer['on'],\n      off: noop as any as WebSocketServer['off'],\n      setInvokeHandler: noop,\n      handleInvoke: async () => ({\n        error: {\n          name: 'TransportError',\n          message: 'handleInvoke not implemented',\n          stack: new Error().stack,\n        },\n      }),\n      listen: noop,\n      send: noop,\n    }\n  }\n\n  let wsHttpServer: Server | undefined = undefined\n\n  const hmr = isObject(config.server.hmr) && config.server.hmr\n  const hmrServer = hmr && hmr.server\n  const hmrPort = hmr && hmr.port\n  // TODO: the main server port may not have been chosen yet as it may use the next available\n  const portsAreCompatible = !hmrPort || hmrPort === config.server.port\n  const wsServer = hmrServer || (portsAreCompatible && server)\n  let hmrServerWsListener: (\n    req: InstanceType<typeof IncomingMessage>,\n    socket: Duplex,\n    head: Buffer,\n  ) => void\n  const customListeners = new Map<string, Set<WebSocketCustomListener<any>>>()\n  const clientsMap = new WeakMap<WebSocketRaw, WebSocketClient>()\n  const port = hmrPort || 24678\n  const host = (hmr && hmr.host) || undefined\n  const allowedHosts =\n    config.server.allowedHosts === true\n      ? config.server.allowedHosts\n      : Object.freeze([...config.server.allowedHosts]) // Freeze the array to allow caching\n\n  const shouldHandle = (req: IncomingMessage) => {\n    const protocol = req.headers['sec-websocket-protocol']!\n    // vite-ping is allowed to connect from anywhere\n    // because it needs to be connected before the client fetches the new `/@vite/client`\n    // this is fine because vite-ping does not receive / send any meaningful data\n    if (protocol === 'vite-ping') return true\n\n    if (\n      allowedHosts !== true &&\n      !isHostAllowed(req.headers.host, allowedHosts)\n    ) {\n      return false\n    }\n\n    if (config.legacy?.skipWebSocketTokenCheck) {\n      return true\n    }\n\n    // If the Origin header is set, this request might be coming from a browser.\n    // Browsers always sets the Origin header for WebSocket connections.\n    if (req.headers.origin) {\n      const parsedUrl = new URL(`http://example.com${req.url!}`)\n      return hasValidToken(config, parsedUrl)\n    }\n\n    // We allow non-browser requests to connect without a token\n    // for backward compat and convenience\n    // This is fine because if you can sent a request without the SOP limitation,\n    // you can also send a normal HTTP request to the server.\n    return true\n  }\n  const handleUpgrade = (\n    req: IncomingMessage,\n    socket: Duplex,\n    head: Buffer,\n    isPing: boolean,\n  ) => {\n    wss.handleUpgrade(req, socket as Socket, head, (ws) => {\n      // vite-ping is allowed to connect from anywhere\n      // we close the connection immediately without connection event\n      // so that the client does not get included in `wss.clients`\n      if (isPing) {\n        ws.close(/* Normal Closure */ 1000)\n        return\n      }\n      wss.emit('connection', ws, req)\n    })\n  }\n  const wss: WebSocketServerRaw_ = new WebSocketServerRaw({ noServer: true })\n  wss.shouldHandle = shouldHandle\n\n  if (wsServer) {\n    let hmrBase = config.base\n    const hmrPath = hmr ? hmr.path : undefined\n    if (hmrPath) {\n      hmrBase = path.posix.join(hmrBase, hmrPath)\n    }\n    hmrServerWsListener = (req, socket, head) => {\n      const protocol = req.headers['sec-websocket-protocol']!\n      const parsedUrl = new URL(`http://example.com${req.url!}`)\n      if (\n        [HMR_HEADER, 'vite-ping'].includes(protocol) &&\n        parsedUrl.pathname === hmrBase\n      ) {\n        handleUpgrade(req, socket as Socket, head, protocol === 'vite-ping')\n      }\n    }\n    wsServer.on('upgrade', hmrServerWsListener)\n  } else {\n    // http server request handler keeps the same with\n    // https://github.com/websockets/ws/blob/45e17acea791d865df6b255a55182e9c42e5877a/lib/websocket-server.js#L88-L96\n    const route = ((_, res) => {\n      const statusCode = 426\n      const body = STATUS_CODES[statusCode]\n      if (!body)\n        throw new Error(`No body text found for the ${statusCode} status code`)\n\n      res.writeHead(statusCode, {\n        'Content-Length': body.length,\n        'Content-Type': 'text/plain',\n      })\n      res.end(body)\n    }) as Parameters<typeof createHttpServer>[1]\n    // vite dev server in middleware mode\n    // need to call ws listen manually\n    if (httpsOptions) {\n      wsHttpServer = createHttpsServer(httpsOptions, route)\n    } else {\n      wsHttpServer = createHttpServer(route)\n    }\n    wsHttpServer.on('upgrade', (req, socket, head) => {\n      const protocol = req.headers['sec-websocket-protocol']!\n      if (protocol === 'vite-ping' && server && !server.listening) {\n        // reject connection to tell the vite/client that the server is not ready\n        // if the http server is not listening\n        // because the ws server listens before the http server listens\n        req.destroy()\n        return\n      }\n      handleUpgrade(req, socket as Socket, head, protocol === 'vite-ping')\n    })\n    wsHttpServer.on('error', (e: Error & { code: string; port: number }) => {\n      if (e.code === 'EADDRINUSE') {\n        config.logger.error(\n          colors.red(\n            `WebSocket server error: Port ${e.port} is already in use`,\n          ),\n          { error: e },\n        )\n      } else {\n        config.logger.error(\n          colors.red(`WebSocket server error:\\n${e.stack || e.message}`),\n          { error: e },\n        )\n      }\n    })\n  }\n\n  const emitCustomEvent = <T extends string>(\n    event: T,\n    data: InferCustomEventPayload<T>,\n    socket: WebSocketRaw,\n  ) => {\n    const listeners = customListeners.get(event)\n    if (!listeners?.size) return\n\n    const client = getSocketClient(socket)\n    for (const listener of listeners) {\n      listener(data, client)\n    }\n  }\n\n  wss.on('connection', (socket) => {\n    socket.on('message', (raw) => {\n      if (!customListeners.size) return\n      let parsed: any\n      try {\n        parsed = JSON.parse(String(raw))\n      } catch {}\n      if (!parsed || parsed.type !== 'custom' || !parsed.event) return\n      emitCustomEvent(parsed.event, parsed.data, socket)\n    })\n    socket.on('error', (err) => {\n      config.logger.error(`${colors.red(`ws error:`)}\\n${err.stack}`, {\n        timestamp: true,\n        error: err,\n      })\n    })\n    socket.on('close', () => {\n      emitCustomEvent('vite:client:disconnect', undefined, socket)\n    })\n\n    emitCustomEvent('vite:client:connect', undefined, socket)\n\n    socket.send(JSON.stringify({ type: 'connected' }))\n    if (bufferedMessage) {\n      socket.send(JSON.stringify(bufferedMessage))\n      bufferedMessage = null\n    }\n  })\n\n  wss.on('error', (e: Error & { code: string; port: number }) => {\n    if (e.code === 'EADDRINUSE') {\n      config.logger.error(\n        colors.red(`WebSocket server error: Port ${e.port} is already in use`),\n        { error: e },\n      )\n    } else {\n      config.logger.error(\n        colors.red(`WebSocket server error:\\n${e.stack || e.message}`),\n        { error: e },\n      )\n    }\n  })\n\n  // Provide a wrapper to the ws client so we can send messages in JSON format\n  // To be consistent with server.ws.send\n  function getSocketClient(socket: WebSocketRaw) {\n    if (!clientsMap.has(socket)) {\n      clientsMap.set(socket, {\n        send: (...args: any[]) => {\n          let payload: HotPayload\n          if (typeof args[0] === 'string') {\n            payload = {\n              type: 'custom',\n              event: args[0],\n              data: args[1],\n            }\n          } else {\n            payload = args[0]\n          }\n          socket.send(JSON.stringify(payload))\n        },\n        socket,\n      })\n    }\n    return clientsMap.get(socket)!\n  }\n\n  // On page reloads, if a file fails to compile and returns 500, the server\n  // sends the error payload before the client connection is established.\n  // If we have no open clients, buffer the error and send it to the next\n  // connected client.\n  // The same thing may happen when the optimizer runs fast enough to\n  // finish the bundling before the client connects.\n  let bufferedMessage: ErrorPayload | FullReloadPayload | null = null\n\n  const normalizedHotChannel = normalizeHotChannel(\n    {\n      send(payload) {\n        if (\n          (payload.type === 'error' || payload.type === 'full-reload') &&\n          !wss.clients.size\n        ) {\n          bufferedMessage = payload\n          return\n        }\n\n        const stringified = JSON.stringify(payload)\n        wss.clients.forEach((client) => {\n          // readyState 1 means the connection is open\n          if (client.readyState === 1) {\n            client.send(stringified)\n          }\n        })\n      },\n      on(event: string, fn: any) {\n        if (!customListeners.has(event)) {\n          customListeners.set(event, new Set())\n        }\n        customListeners.get(event)!.add(fn)\n      },\n      off(event: string, fn: any) {\n        customListeners.get(event)?.delete(fn)\n      },\n      listen() {\n        wsHttpServer?.listen(port, host)\n      },\n      close() {\n        // should remove listener if hmr.server is set\n        // otherwise the old listener swallows all WebSocket connections\n        if (hmrServerWsListener && wsServer) {\n          wsServer.off('upgrade', hmrServerWsListener)\n        }\n        return new Promise<void>((resolve, reject) => {\n          wss.clients.forEach((client) => {\n            client.terminate()\n          })\n          wss.close((err) => {\n            if (err) {\n              reject(err)\n            } else {\n              if (wsHttpServer) {\n                wsHttpServer.close((err) => {\n                  if (err) {\n                    reject(err)\n                  } else {\n                    resolve()\n                  }\n                })\n              } else {\n                resolve()\n              }\n            }\n          })\n        })\n      },\n    },\n    config.server.hmr !== false,\n    // Don't normalize client as we already handles the send, and to keep `.socket`\n    false,\n  )\n  return {\n    ...normalizedHotChannel,\n\n    on: ((event: string, fn: any) => {\n      if (wsServerEvents.includes(event)) {\n        wss.on(event, fn)\n        return\n      }\n      normalizedHotChannel.on(event, fn)\n    }) as WebSocketServer['on'],\n    off: ((event: string, fn: any) => {\n      if (wsServerEvents.includes(event)) {\n        wss.off(event, fn)\n        return\n      }\n      normalizedHotChannel.off(event, fn)\n    }) as WebSocketServer['off'],\n    async close() {\n      await normalizedHotChannel.close()\n    },\n\n    [isWebSocketServer]: true,\n    get clients() {\n      return new Set(Array.from(wss.clients).map(getSocketClient))\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/shortcuts.ts",
    "content": "import readline from 'node:readline'\nimport colors from 'picocolors'\nimport { restartServerWithUrls } from './server'\nimport type { ViteDevServer } from './server'\nimport { isDevServer } from './utils'\nimport type { PreviewServer } from './preview'\nimport { openBrowser } from './server/openBrowser'\n\nexport type ShortcutsState<Server = ViteDevServer | PreviewServer> = {\n  rl: readline.Interface\n  options: BindCLIShortcutsOptions<Server>\n}\n\nexport type BindCLIShortcutsOptions<Server = ViteDevServer | PreviewServer> = {\n  /**\n   * Print a one-line shortcuts \"help\" hint to the terminal\n   */\n  print?: boolean\n  /**\n   * Custom shortcuts to run when a key is pressed. These shortcuts take priority\n   * over the default shortcuts if they have the same keys (except the `h` key).\n   * To disable a default shortcut, define the same key but with `action: undefined`.\n   */\n  customShortcuts?: CLIShortcut<Server>[]\n}\n\nexport type CLIShortcut<Server = ViteDevServer | PreviewServer> = {\n  key: string\n  description: string\n  action?(server: Server): void | Promise<void>\n}\n\nexport function bindCLIShortcuts<Server extends ViteDevServer | PreviewServer>(\n  server: Server,\n  opts?: BindCLIShortcutsOptions<Server>,\n  enabled: boolean = process.stdin.isTTY && !process.env.CI,\n): void {\n  if (!server.httpServer || !enabled) {\n    return\n  }\n\n  const isDev = isDevServer(server)\n\n  // Merge shortcuts: new at top, existing updated in place (keeps manual > plugin order)\n  const previousShortcuts =\n    server._shortcutsState?.options.customShortcuts ?? []\n  const newShortcuts = opts?.customShortcuts ?? []\n  const previousKeys = new Set(previousShortcuts.map((s) => s.key))\n  const customShortcuts: CLIShortcut<ViteDevServer | PreviewServer>[] = [\n    ...newShortcuts.filter((s) => !previousKeys.has(s.key)),\n    ...previousShortcuts.map(\n      (s) => newShortcuts.find((n) => n.key === s.key) ?? s,\n    ),\n  ]\n\n  const newOptions: BindCLIShortcutsOptions<Server> = {\n    ...opts,\n    customShortcuts,\n  }\n\n  if (opts?.print) {\n    server.config.logger.info(\n      colors.dim(colors.green('  ➜')) +\n        colors.dim('  press ') +\n        colors.bold('h + enter') +\n        colors.dim(' to show help'),\n    )\n  }\n\n  const shortcuts = customShortcuts.concat(\n    (isDev\n      ? BASE_DEV_SHORTCUTS\n      : BASE_PREVIEW_SHORTCUTS) as CLIShortcut<Server>[],\n  )\n\n  let actionRunning = false\n\n  const onInput = async (input: string) => {\n    if (actionRunning) return\n\n    input = input.trim().toLocaleLowerCase()\n    if (input === 'h') {\n      const loggedKeys = new Set<string>()\n      server.config.logger.info('\\n  Shortcuts')\n\n      for (const shortcut of shortcuts) {\n        if (loggedKeys.has(shortcut.key)) continue\n        loggedKeys.add(shortcut.key)\n\n        if (shortcut.action == null) continue\n\n        server.config.logger.info(\n          colors.dim('  press ') +\n            colors.bold(`${shortcut.key} + enter`) +\n            colors.dim(` to ${shortcut.description}`),\n        )\n      }\n\n      return\n    }\n\n    const shortcut = shortcuts.find((shortcut) => shortcut.key === input)\n    if (!shortcut || shortcut.action == null) return\n\n    actionRunning = true\n    await shortcut.action(server)\n    actionRunning = false\n  }\n\n  if (!server._shortcutsState) {\n    ;(server._shortcutsState as unknown as ShortcutsState<Server>) = {\n      rl: readline.createInterface({ input: process.stdin }),\n      options: newOptions,\n    }\n    server.httpServer.on('close', () => {\n      // Skip if detached during restart (readline is reused)\n      if (server._shortcutsState) server._shortcutsState.rl.close()\n    })\n  } else {\n    server._shortcutsState.rl.removeAllListeners('line')\n    ;(server._shortcutsState.options as BindCLIShortcutsOptions<Server>) =\n      newOptions\n  }\n\n  server._shortcutsState!.rl.on('line', onInput)\n}\n\nconst BASE_DEV_SHORTCUTS: CLIShortcut<ViteDevServer>[] = [\n  {\n    key: 'r',\n    description: 'restart the server',\n    async action(server) {\n      await restartServerWithUrls(server)\n    },\n  },\n  {\n    key: 'u',\n    description: 'show server url',\n    action(server) {\n      server.config.logger.info('')\n      server.printUrls()\n    },\n  },\n  {\n    key: 'o',\n    description: 'open in browser',\n    action(server) {\n      server.openBrowser()\n    },\n  },\n  {\n    key: 'c',\n    description: 'clear console',\n    action(server) {\n      server.config.logger.clearScreen('error')\n    },\n  },\n  {\n    key: 'q',\n    description: 'quit',\n    async action(server) {\n      try {\n        await server.close()\n      } finally {\n        process.exit()\n      }\n    },\n  },\n]\n\nconst BASE_PREVIEW_SHORTCUTS: CLIShortcut<PreviewServer>[] = [\n  {\n    key: 'o',\n    description: 'open in browser',\n    action(server) {\n      const url =\n        server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0]\n      if (url) {\n        openBrowser(url, true, server.config.logger)\n      } else {\n        server.config.logger.warn('No URL available to open in browser')\n      }\n    },\n  },\n  {\n    key: 'q',\n    description: 'quit',\n    async action(server) {\n      try {\n        await server.close()\n      } finally {\n        process.exit()\n      }\n    },\n  },\n]\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/__snapshots__/ssrLoadModule.spec.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`parse error 1`] = `\n{\n  \"frame\": \"\nExpected \";\" but found \"code\"\n1  |  invalid code\n   |          ^\n2  |  \n\",\n  \"id\": \"<root>/fixtures/errors/syntax-error.ts\",\n  \"loc\": {\n    \"column\": 8,\n    \"file\": \"<root>/fixtures/errors/syntax-error.ts\",\n    \"line\": 1,\n  },\n  \"message\": \"Transform failed with 1 error:\n<root>/fixtures/errors/syntax-error.ts:1:8: ERROR: Expected \";\" but found \"code\"\",\n}\n`;\n\nexports[`parse error 2`] = `\n{\n  \"frame\": \"1  |  invalid code\n   |          ^\n2  |  \",\n  \"id\": \"/fixtures/errors/syntax-error.js\",\n  \"loc\": {\n    \"column\": 8,\n    \"file\": \"/fixtures/errors/syntax-error.js\",\n    \"line\": 1,\n  },\n  \"message\": \"Parse failure: Expected ';', '}' or <eof>\nAt file: /fixtures/errors/syntax-error.js:1:8\",\n}\n`;\n\nexports[`parse error 3`] = `\n{\n  \"frame\": \"\nExpected \";\" but found \"code\"\n1  |  invalid code\n   |          ^\n2  |  \n\",\n  \"id\": \"<root>/fixtures/errors/syntax-error.ts\",\n  \"loc\": {\n    \"column\": 8,\n    \"file\": \"<root>/fixtures/errors/syntax-error.ts\",\n    \"line\": 1,\n  },\n  \"message\": \"Transform failed with 1 error:\n<root>/fixtures/errors/syntax-error.ts:1:8: ERROR: Expected \";\" but found \"code\"\",\n}\n`;\n\nexports[`parse error 4`] = `\n{\n  \"frame\": \"1  |  invalid code\n   |          ^\n2  |  \",\n  \"id\": \"/fixtures/errors/syntax-error.js\",\n  \"loc\": {\n    \"column\": 8,\n    \"file\": \"/fixtures/errors/syntax-error.js\",\n    \"line\": 1,\n  },\n  \"message\": \"Parse failure: Expected ';', '}' or <eof>\nAt file: /fixtures/errors/syntax-error.js:1:8\",\n}\n`;\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/bundled-with-sourcemaps/bundle.js",
    "content": "function covered$1() {\n  return 'First'\n}\n\nfunction uncovered$1() {\n  return 'Uncovered'\n}\n\nvar first = /*#__PURE__*/ Object.freeze({\n  __proto__: null,\n  covered: covered$1,\n  uncovered: uncovered$1,\n})\n\nfunction covered() {\n  return 'Second'\n}\n\nfunction uncovered() {\n  return 'Uncovered'\n}\n\nvar second = /*#__PURE__*/ Object.freeze({\n  __proto__: null,\n  covered: covered,\n  uncovered: uncovered,\n})\n\nexport { first, second }\n//# sourceMappingURL=bundle.js.map\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/errors/syntax-error-dep.js",
    "content": "import './syntax-error.js'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/errors/syntax-error-dep.ts",
    "content": "import './syntax-error.ts'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/errors/syntax-error.js",
    "content": "invalid code\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/errors/syntax-error.ts",
    "content": "invalid code\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/file-url/test space.js",
    "content": "export const msg = 'works'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/file-url/test.js",
    "content": "export const msg = 'works'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/global/export.js",
    "content": "export const global = 'ok'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/global/test.js",
    "content": "export default global\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/json/test.json",
    "content": "{\n  \"hello\": \"this is json\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/modules/has-error.js",
    "content": "throw new Error()\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/modules/has-invalid-import.js",
    "content": "import { foo } from './non-existent.js'\n\nexport const hello = 'world'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/modules/import-meta.js",
    "content": "export const dirname = import.meta.dirname\nexport const filename = import.meta.filename\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/multi-source-sourcemaps/dist.js",
    "content": "// nested-directory/nested-file.js\nvar nested_file_default =\n  'Nested file will trigger edge case that used to break sourcemaps'\n\n// entrypoint.js\nfunction entrypoint() {\n  console.log(nested_file_default)\n  throw new Error('Hello world')\n}\nexport { entrypoint }\n//# sourceMappingURL=dist.js.map\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/multi-source-sourcemaps/entrypoint.js",
    "content": "/*\n * You can rebuild this with:\n * - rm -f ./dist.js ./dist.js.map\n * - npx esbuild --bundle entrypoint.js --outfile=dist.js --sourcemap --format=esm\n */\n\nimport nested from './nested-directory/nested-file'\n\nexport function entrypoint() {\n  console.log(nested)\n  throw new Error('Hello world')\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/multi-source-sourcemaps/nested-directory/nested-file.js",
    "content": "export default 'Nested file will trigger edge case that used to break sourcemaps'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/named-overwrite-all/dep1.js",
    "content": "export const a = 'dep1-a'\nexport const b = 'dep1-b'\nexport const c = 'dep1-c'\nexport const d = 'dep1-d'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/named-overwrite-all/dep2.js",
    "content": "export const d = 'dep2-d'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/fixtures/named-overwrite-all/main.js",
    "content": "export const a = 'main-a'\nexport * from './dep1.js'\nexport const c = 'main-c'\nexport * from './dep2.js'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/ssrLoadModule.spec.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport { stripVTControlCharacters } from 'node:util'\nimport { expect, onTestFinished, test, vi } from 'vitest'\nimport { createServer } from '../../server'\nimport { DevEnvironment } from '../../server/environment'\nimport { normalizePath } from '../../utils'\n\nconst root = fileURLToPath(new URL('./', import.meta.url))\n\nasync function createDevServer() {\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'silent',\n    optimizeDeps: {\n      noDiscovery: true,\n    },\n  })\n  await server.environments.ssr.pluginContainer.buildStart({})\n  return server\n}\n\ntest('ssrLoad', async () => {\n  expect.assertions(1)\n  const server = await createDevServer()\n  const moduleRelativePath = '/fixtures/modules/has-invalid-import.js'\n  const moduleAbsolutePath = normalizePath(path.join(root, moduleRelativePath))\n  try {\n    await server.ssrLoadModule(moduleRelativePath)\n  } catch (e) {\n    expect(e.message).toBe(\n      `Failed to load url ./non-existent.js (resolved id: ./non-existent.js) in ${moduleAbsolutePath}. Does the file exist?`,\n    )\n  }\n})\n\ntest('error has same instance', async () => {\n  expect.assertions(3)\n  const s = Symbol()\n\n  const server = await createDevServer()\n  try {\n    await server.ssrLoadModule('/fixtures/modules/has-error.js')\n  } catch (e) {\n    expect(e[s]).toBeUndefined()\n    e[s] = true\n    expect(e[s]).toBe(true)\n  }\n\n  try {\n    await server.ssrLoadModule('/fixtures/modules/has-error.js')\n  } catch (e) {\n    expect(e[s]).toBe(true)\n  }\n})\n\ntest('import.meta.filename/dirname returns same value with Node', async () => {\n  const server = await createDevServer()\n  const moduleRelativePath = '/fixtures/modules/import-meta.js'\n  const filename = path.resolve(root, '.' + moduleRelativePath)\n\n  const viteValue = await server.ssrLoadModule(moduleRelativePath)\n  expect(viteValue.dirname).toBe(path.dirname(filename))\n  expect(viteValue.filename).toBe(filename)\n})\n\ntest('virtual module invalidation simple', async () => {\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'silent',\n    optimizeDeps: {\n      noDiscovery: true,\n    },\n    plugins: [\n      {\n        name: 'virtual-test',\n        resolveId(id) {\n          if (id === 'virtual:test') {\n            return '\\0virtual:test'\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:test') {\n            return `\n              globalThis.__virtual_test_state ??= 0;\n              globalThis.__virtual_test_state++;\n              export default globalThis.__virtual_test_state;\n            `\n          }\n        },\n      },\n    ],\n  })\n  await server.environments.ssr.pluginContainer.buildStart({})\n\n  const mod1 = await server.ssrLoadModule('virtual:test')\n  expect(mod1.default).toEqual(1)\n  const mod2 = await server.ssrLoadModule('virtual:test')\n  expect(mod2.default).toEqual(1)\n\n  const modNode = server.moduleGraph.getModuleById('\\0virtual:test')\n  server.moduleGraph.invalidateModule(modNode!)\n\n  const mod3 = await server.ssrLoadModule('virtual:test')\n  expect(mod3.default).toEqual(2)\n})\n\ntest('virtual module invalidation nested', async () => {\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'silent',\n    optimizeDeps: {\n      noDiscovery: true,\n    },\n    plugins: [\n      {\n        name: 'test-virtual',\n        resolveId(id) {\n          if (id === 'virtual:test') {\n            return '\\0virtual:test'\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:test') {\n            return `\n              import testDep from \"virtual:test-dep\";\n              export default testDep;\n            `\n          }\n        },\n      },\n      {\n        name: 'test-virtual-dep',\n        resolveId(id) {\n          if (id === 'virtual:test-dep') {\n            return '\\0virtual:test-dep'\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:test-dep') {\n            return `\n              globalThis.__virtual_test_state2 ??= 0;\n              globalThis.__virtual_test_state2++;\n              export default globalThis.__virtual_test_state2;\n            `\n          }\n        },\n      },\n    ],\n  })\n  await server.environments.ssr.pluginContainer.buildStart({})\n\n  const mod1 = await server.ssrLoadModule('virtual:test')\n  expect(mod1.default).toEqual(1)\n  const mod2 = await server.ssrLoadModule('virtual:test')\n  expect(mod2.default).toEqual(1)\n\n  server.moduleGraph.invalidateModule(\n    server.moduleGraph.getModuleById('\\0virtual:test')!,\n  )\n  server.moduleGraph.invalidateModule(\n    server.moduleGraph.getModuleById('\\0virtual:test-dep')!,\n  )\n\n  const mod3 = await server.ssrLoadModule('virtual:test')\n  expect(mod3.default).toEqual(2)\n})\n\ntest('can export global', async () => {\n  const server = await createDevServer()\n  const mod = await server.ssrLoadModule('/fixtures/global/export.js')\n  expect(mod.global).toBe('ok')\n})\n\ntest('can access nodejs global', async () => {\n  const server = await createDevServer()\n  const mod = await server.ssrLoadModule('/fixtures/global/test.js')\n  expect(mod.default).toBe(globalThis)\n})\n\n// skip for now as rolldown returns different error message from esbuild\n// related: https://github.com/oxc-project/oxc/issues/7261\n// (rolldown does not set the properties passed from Oxc)\ntest.skip('parse error', async () => {\n  const server = await createDevServer()\n\n  function stripRoot(s?: string) {\n    return (s || '').replace(server.config.root, '<root>')\n  }\n\n  for (const file of [\n    '/fixtures/errors/syntax-error.ts',\n    '/fixtures/errors/syntax-error.js',\n    '/fixtures/errors/syntax-error-dep.ts',\n    '/fixtures/errors/syntax-error-dep.js',\n  ]) {\n    try {\n      await server.ssrLoadModule(file)\n    } catch (e) {\n      expect(e).toBeInstanceOf(Error)\n      expect({\n        message: stripRoot(e.message),\n        frame: stripVTControlCharacters(e.frame || ''),\n        id: stripRoot(e.id),\n        loc: e.loc && {\n          file: stripRoot(e.loc.file),\n          column: e.loc.column,\n          line: e.loc.line,\n        },\n      }).toMatchSnapshot()\n      continue\n    }\n    expect.unreachable()\n  }\n})\n\ntest('json', async () => {\n  const server = await createDevServer()\n  const mod = await server.ssrLoadModule('/fixtures/json/test.json')\n  expect(mod).toMatchInlineSnapshot(`\n    {\n      \"default\": {\n        \"hello\": \"this is json\",\n      },\n      \"hello\": \"this is json\",\n    }\n  `)\n\n  const source = fs.readFileSync(\n    path.join(root, 'fixtures/json/test.json'),\n    'utf-8',\n  )\n  const json = await server.ssrTransform(\n    `export default ${source}`,\n    null,\n    '/test.json',\n  )\n  expect(json?.code.length).toMatchInlineSnapshot(`165`)\n})\n\ntest('file url', async () => {\n  const server = await createDevServer()\n\n  const mod = await server.ssrLoadModule(\n    new URL('./fixtures/file-url/test.js', import.meta.url).href,\n  )\n  expect(mod.msg).toBe('works')\n\n  const modWithSpace = await server.ssrLoadModule(\n    new URL('./fixtures/file-url/test space.js', import.meta.url).href,\n  )\n  expect(modWithSpace.msg).toBe('works')\n})\n\ntest('plugin error', async () => {\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'error',\n    plugins: [\n      {\n        name: 'test-plugin',\n        resolveId(source) {\n          if (source === 'virtual:test') {\n            return '\\0' + source\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:test') {\n            return this.error('test-error')\n          }\n        },\n      },\n    ],\n  })\n  onTestFinished(() => server.close())\n\n  const spy = vi\n    .spyOn(server.config.logger, 'error')\n    .mockImplementation(() => {})\n  try {\n    await server.ssrLoadModule('virtual:test')\n    expect.unreachable()\n  } catch {}\n  expect(\n    stripVTControlCharacters(spy.mock.lastCall![0])\n      .split('\\n')\n      .slice(0, 2)\n      .join('\\n'),\n  ).toMatchInlineSnapshot(`\n    \"Error when evaluating SSR module virtual:test: test-error\n      Plugin: test-plugin\"\n  `)\n})\n\ntest('named exports overwrite export all', async () => {\n  const server = await createDevServer()\n  const mod = await server.ssrLoadModule(\n    './fixtures/named-overwrite-all/main.js',\n  )\n\n  // ESM spec doesn't allow conflicting `export *` and such duplicate exports are removed (in this case \"d\"),\n  // but this is likely not possible to support due to Vite dev SSR's lazy nature.\n  // [Node]\n  //   $ node -e 'import(\"./packages/vite/src/node/ssr/__tests__/fixtures/named-overwrite-all/main.js\").then(console.log)'\n  //   [Module: null prototype] { a: 'main-a', b: 'dep1-b', c: 'main-c' }\n  // [Rollup]\n  //   Conflicting namespaces: \"main.js\" re-exports \"d\" from one of the modules \"dep1.js\" and \"dep2.js\" (will be ignored).\n  expect(mod).toMatchInlineSnapshot(`\n    {\n      \"a\": \"main-a\",\n      \"b\": \"dep1-b\",\n      \"c\": \"main-c\",\n      \"d\": \"dep1-d\",\n    }\n  `)\n})\n\ntest('throws when ssr environment is not runnable', async () => {\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'silent',\n    optimizeDeps: {\n      noDiscovery: true,\n    },\n    environments: {\n      ssr: {\n        dev: {\n          createEnvironment: (name, config) =>\n            new DevEnvironment(name, config, { hot: false }),\n        },\n      },\n    },\n  })\n  onTestFinished(() => server.close())\n\n  await expect(\n    server.ssrLoadModule('/fixtures/modules/has-invalid-import.js'),\n  ).rejects.toThrow(\n    \"ssrLoadModule requires the 'ssr' environment to be a runnable environment.\",\n  )\n})\n\ntest('buildStart before transform', async () => {\n  const fn = vi.fn()\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'error',\n    plugins: [\n      {\n        name: 'test-plugin',\n        async buildStart() {\n          fn('buildStart:in')\n          await new Promise((r) => setTimeout(r, 200))\n          fn('buildStart:out')\n        },\n        resolveId(source) {\n          if (source === 'virtual:test') {\n            fn('resolveId')\n            return '\\0' + source\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:test') {\n            fn('load')\n            return `export default 'ok'`\n          }\n        },\n        transform(code, id) {\n          if (id === '\\0virtual:test') {\n            fn('transform')\n            return code\n          }\n        },\n      },\n    ],\n  })\n  onTestFinished(() => server.close())\n  await server.pluginContainer.buildStart({})\n\n  const mod = await server.ssrLoadModule('virtual:test')\n  expect(mod.default).toBe('ok')\n  expect(fn.mock.calls).toMatchInlineSnapshot(`\n    [\n      [\n        \"buildStart:in\",\n      ],\n      [\n        \"buildStart:out\",\n      ],\n      [\n        \"resolveId\",\n      ],\n      [\n        \"load\",\n      ],\n      [\n        \"transform\",\n      ],\n    ]\n  `)\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/ssrStacktrace.spec.ts",
    "content": "import { fileURLToPath } from 'node:url'\nimport { expect, test } from 'vitest'\nimport { createServer } from '../../server'\n\nconst root = fileURLToPath(new URL('./', import.meta.url))\n\nasync function createDevServer() {\n  const server = await createServer({\n    configFile: false,\n    root,\n    logLevel: 'silent',\n    optimizeDeps: {\n      noDiscovery: true,\n    },\n  })\n  await server.environments.ssr.pluginContainer.buildStart({})\n  return server\n}\n\ntest('call rewriteStacktrace twice', async () => {\n  const server = await createDevServer()\n  for (let i = 0; i < 2; i++) {\n    try {\n      await server.ssrLoadModule('/fixtures/modules/has-error.js')\n    } catch (e: any) {\n      server.ssrFixStacktrace(e)\n    }\n  }\n})\n\ntest('outputs message when stacktrace appears to be already rewritten', async () => {\n  const server = await createDevServer()\n  try {\n    await server.ssrLoadModule('/fixtures/modules/has-error.js')\n  } catch (e: any) {\n    // Manually craft an already-rewritten stacktrace with invalid line/column\n    // that will trigger the alreadyRewritten flag\n    e.stack = e.stack.replace(\n      /fixtures\\/modules\\/has-error\\.js:\\d+:\\d+/,\n      'fixtures/modules/has-error.js:1:1',\n    )\n    server.ssrFixStacktrace(e)\n    expect(e.message).toContain(\n      'The stacktrace appears to be already rewritten by something else',\n    )\n  }\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { assert, expect, test } from 'vitest'\nimport type { SourceMap } from 'rolldown'\nimport { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping'\nimport { transformWithEsbuild } from '../../plugins/esbuild'\nimport { ssrTransform } from '../ssrTransform'\nimport { createServer } from '../..'\n\nconst ssrTransformSimple = async (code: string, url = '') =>\n  ssrTransform(code, null, url, code)\nconst ssrTransformSimpleCode = async (code: string, url?: string) =>\n  (await ssrTransformSimple(code, url))?.code\n\ntest('default import', async () => {\n  expect(\n    await ssrTransformSimpleCode(`import foo from 'vue';console.log(foo.bar)`),\n  ).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"default\"]});\n    console.log(__vite_ssr_import_0__.default.bar)\"\n  `,\n  )\n})\n\ntest('named import', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import { ref } from 'vue';function foo() { return ref(0) }`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"ref\"]});\n    function foo() { return (0,__vite_ssr_import_0__.ref)(0) }\"\n  `,\n  )\n})\n\ntest('named import: arbitrary module namespace specifier', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import { \"some thing\" as ref } from 'vue';function foo() { return ref(0) }`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"some thing\"]});\n    function foo() { return (0,__vite_ssr_import_0__[\"some thing\"])(0) }\"\n  `,\n  )\n})\n\ntest('namespace import', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import * as vue from 'vue';function foo() { return vue.ref(0) }`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\");\n    function foo() { return __vite_ssr_import_0__.ref(0) }\"\n  `,\n  )\n})\n\ntest('export function declaration', async () => {\n  expect(\n    await ssrTransformSimpleCode(`export function foo() {}`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"foo\", () => { try { return foo } catch {} });\n    function foo() {}\"\n  `,\n  )\n})\n\ntest('export class declaration', async () => {\n  expect(\n    await ssrTransformSimpleCode(`export class foo {}`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"foo\", () => { try { return foo } catch {} });\n    class foo {}\"\n  `,\n  )\n})\n\ntest('export var declaration', async () => {\n  expect(\n    await ssrTransformSimpleCode(`export const a = 1, b = 2`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"a\", () => { try { return a } catch {} });\n    __vite_ssr_exportName__(\"b\", () => { try { return b } catch {} });\n    const a = 1, b = 2\"\n  `,\n  )\n})\n\ntest('export named', async () => {\n  expect(\n    await ssrTransformSimpleCode(`const a = 1, b = 2; export { a, b as c }`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"a\", () => { try { return a } catch {} });\n    __vite_ssr_exportName__(\"c\", () => { try { return b } catch {} });\n    const a = 1, b = 2; \"\n  `,\n  )\n})\n\ntest('export named from', async () => {\n  expect(\n    await ssrTransformSimpleCode(`export { ref, computed as c } from 'vue'`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"ref\", () => { try { return __vite_ssr_import_0__.ref } catch {} });\n    __vite_ssr_exportName__(\"c\", () => { try { return __vite_ssr_import_0__.computed } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"ref\",\"computed\"]});\n    \"\n  `,\n  )\n})\n\ntest('named exports of imported binding', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import {createApp} from 'vue';export {createApp}`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"createApp\", () => { try { return __vite_ssr_import_0__.createApp } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"createApp\"]});\n    \"\n  `,\n  )\n})\n\ntest('export * from', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `export * from 'vue'\\n` + `export * from 'react'`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\");\n    __vite_ssr_exportAll__(__vite_ssr_import_0__);\n    ;const __vite_ssr_import_1__ = await __vite_ssr_import__(\"react\");\n    __vite_ssr_exportAll__(__vite_ssr_import_1__);\n\n    \"\n  `)\n})\n\ntest('export * as from', async () => {\n  expect(\n    await ssrTransformSimpleCode(`export * as foo from 'vue'`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"foo\", () => { try { return __vite_ssr_import_0__ } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\");\n    \"\n  `,\n  )\n})\n\ntest('re-export by imported name', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\\\nimport * as foo from 'foo'\nexport * as foo from 'foo'\n`),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"foo\", () => { try { return __vite_ssr_import_1__ } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\");\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"foo\");\n\n\n    \"\n  `)\n\n  expect(\n    await ssrTransformSimpleCode(`\\\nimport { foo } from 'foo'\nexport { foo } from 'foo'\n`),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"foo\", () => { try { return __vite_ssr_import_1__.foo } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"foo\"]});\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"foo\"]});\n\n\n    \"\n  `)\n\n  expect(\n    await ssrTransformSimpleCode(`\\\nimport { foo } from 'foo'\nexport { foo as foo } from 'foo'\n`),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"foo\", () => { try { return __vite_ssr_import_1__.foo } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"foo\"]});\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"foo\"]});\n\n\n    \"\n  `)\n})\n\ntest('export * as from arbitrary module namespace identifier', async () => {\n  expect(\n    await ssrTransformSimpleCode(`export * as \"arbitrary string\" from 'vue'`),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"arbitrary string\", () => { try { return __vite_ssr_import_0__ } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\");\n    \"\n  `,\n  )\n})\n\ntest('export as arbitrary module namespace identifier', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `const something = \"Something\";export { something as \"arbitrary string\" };`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"arbitrary string\", () => { try { return something } catch {} });\n    const something = \"Something\";\"\n  `,\n  )\n})\n\ntest('export as from arbitrary module namespace identifier', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `export { \"arbitrary string2\" as \"arbitrary string\" } from 'vue';`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"arbitrary string\", () => { try { return __vite_ssr_import_0__[\"arbitrary string2\"] } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"arbitrary string2\"]});\n    \"\n  `,\n  )\n})\n\ntest('export default', async () => {\n  expect(await ssrTransformSimpleCode(`export default {}`))\n    .toMatchInlineSnapshot(`\n      \"__vite_ssr_exportName__(\"default\", () => { try { return __vite_ssr_export_default__ } catch {} });\n      const __vite_ssr_export_default__ = {}\"\n    `)\n})\n\ntest('export then import minified', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `export * from 'vue';import {createApp} from 'vue';`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\");\n    __vite_ssr_exportAll__(__vite_ssr_import_0__);\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"createApp\"]});\n    \"\n  `)\n})\n\ntest('hoist import to top', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `path.resolve('server.js');import path from 'node:path';`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"node:path\", {\"importedNames\":[\"default\"]});\n    __vite_ssr_import_0__.default.resolve('server.js');\"\n  `,\n  )\n})\n\ntest('whitespace between imports does not trigger hoisting', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import { dirname } from 'node:path';\\n\\n\\nimport fs from 'node:fs';`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"node:path\", {\"importedNames\":[\"dirname\"]});\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"node:fs\", {\"importedNames\":[\"default\"]});\n\n\n\n    \"\n  `)\n})\n\ntest('import.meta', async () => {\n  expect(\n    await ssrTransformSimpleCode(`console.log(import.meta.url)`),\n  ).toMatchInlineSnapshot(`\"console.log(__vite_ssr_import_meta__.url)\"`)\n})\n\ntest('dynamic import', async () => {\n  const result = await ssrTransformSimple(\n    `export const i = () => import('./foo')`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"__vite_ssr_exportName__(\"i\", () => { try { return i } catch {} });\n    const i = () => __vite_ssr_dynamic_import__('./foo')\"\n  `,\n  )\n  expect(result?.deps).toEqual([])\n  expect(result?.dynamicDeps).toEqual(['./foo'])\n})\n\ntest('do not rewrite method definition', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';class A { fn() { fn() } }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    class A { fn() { (0,__vite_ssr_import_0__.fn)() } }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\ntest('do not rewrite when variable is in scope', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';function A(){ const fn = () => {}; return { fn }; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    function A(){ const fn = () => {}; return { fn }; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\n// #5472\ntest('do not rewrite when variable is in scope with object destructuring', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    function A(){ let {fn, test} = {fn: 'foo', test: 'bar'}; return { fn }; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\n// #5472\ntest('do not rewrite when variable is in scope with array destructuring', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    function A(){ let [fn, test] = ['foo', 'bar']; return { fn }; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\n// #5727\ntest('rewrite variable in string interpolation in function nested arguments', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';function A({foo = \\`test\\${fn}\\`} = {}){ return {}; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    function A({foo = \\`test\\${__vite_ssr_import_0__.fn}\\`} = {}){ return {}; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\n// #6520\ntest('rewrite variables in default value of destructuring params', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';function A({foo = fn}){ return {}; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    function A({foo = __vite_ssr_import_0__.fn}){ return {}; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\ntest('do not rewrite when function declaration is in scope', async () => {\n  const result = await ssrTransformSimple(\n    `import { fn } from 'vue';function A(){ function fn() {}; return { fn }; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"fn\"]});\n    function A(){ function fn() {}; return { fn }; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\n// #16452\ntest('do not rewrite when function expression is in scope', async () => {\n  const result = await ssrTransformSimple(\n    `import {fn} from './vue';var a = function() { return function fn() { console.log(fn) } }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./vue\", {\"importedNames\":[\"fn\"]});\n    var a = function() { return function fn() { console.log(fn) } }\"\n  `,\n  )\n})\n\n// #16452\ntest('do not rewrite when function expression is in global scope', async () => {\n  const result = await ssrTransformSimple(\n    `import {fn} from './vue';foo(function fn(a = fn) { console.log(fn) })`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./vue\", {\"importedNames\":[\"fn\"]});\n    foo(function fn(a = fn) { console.log(fn) })\"\n  `,\n  )\n})\n\ntest('do not rewrite when class declaration is in scope', async () => {\n  const result = await ssrTransformSimple(\n    `import { cls } from 'vue';function A(){ class cls {} return { cls }; }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"cls\"]});\n    function A(){ class cls {} return { cls }; }\"\n  `,\n  )\n  expect(result?.deps).toEqual(['vue'])\n})\n\ntest('do not rewrite when class expression is in scope', async () => {\n  const result = await ssrTransformSimple(\n    `import { cls } from './vue';var a = function() { return class cls { constructor() { console.log(cls) } } }`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./vue\", {\"importedNames\":[\"cls\"]});\n    var a = function() { return class cls { constructor() { console.log(cls) } } }\"\n  `,\n  )\n})\n\ntest('do not rewrite when class expression is in global scope', async () => {\n  const result = await ssrTransformSimple(\n    `import { cls } from './vue';foo(class cls { constructor() { console.log(cls) } })`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./vue\", {\"importedNames\":[\"cls\"]});\n    foo(class cls { constructor() { console.log(cls) } })\"\n  `,\n  )\n})\n\ntest('do not rewrite catch clause', async () => {\n  const result = await ssrTransformSimple(\n    `import {error} from './dependency';try {} catch(error) {}`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./dependency\", {\"importedNames\":[\"error\"]});\n    try {} catch(error) {}\"\n  `,\n  )\n  expect(result?.deps).toEqual(['./dependency'])\n})\n\n// #2221\ntest('should declare variable for imported super class', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import { Foo } from './dependency';` + `class A extends Foo {}`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./dependency\", {\"importedNames\":[\"Foo\"]});\n    const Foo = __vite_ssr_import_0__.Foo;\n    class A extends Foo {}\"\n  `)\n\n  // exported classes: should prepend the declaration at root level, before the\n  // first class that uses the binding\n  expect(\n    await ssrTransformSimpleCode(\n      `import { Foo } from './dependency';` +\n        `export default class A extends Foo {}\\n` +\n        `export class B extends Foo {}`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"default\", () => { try { return A } catch {} });\n    __vite_ssr_exportName__(\"B\", () => { try { return B } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./dependency\", {\"importedNames\":[\"Foo\"]});\n    const Foo = __vite_ssr_import_0__.Foo;\n    class A extends Foo {};\n    class B extends Foo {}\"\n  `)\n})\n\n// #4049\ntest('should handle default export variants', async () => {\n  // default anonymous functions\n  expect(await ssrTransformSimpleCode(`export default function() {}\\n`))\n    .toMatchInlineSnapshot(`\n      \"__vite_ssr_exportName__(\"default\", () => { try { return __vite_ssr_export_default__ } catch {} });\n      const __vite_ssr_export_default__ = function() {}\n      \"\n    `)\n  // default anonymous class\n  expect(await ssrTransformSimpleCode(`export default class {}\\n`))\n    .toMatchInlineSnapshot(`\n      \"__vite_ssr_exportName__(\"default\", () => { try { return __vite_ssr_export_default__ } catch {} });\n      const __vite_ssr_export_default__ = class {}\n      \"\n    `)\n  // default named functions\n  expect(\n    await ssrTransformSimpleCode(\n      `export default function foo() {}\\n` +\n        `foo.prototype = Object.prototype;`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"default\", () => { try { return foo } catch {} });\n    function foo() {};\n    foo.prototype = Object.prototype;\"\n  `)\n  // default named classes\n  expect(\n    await ssrTransformSimpleCode(\n      `export default class A {}\\n` + `export class B extends A {}`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"default\", () => { try { return A } catch {} });\n    __vite_ssr_exportName__(\"B\", () => { try { return B } catch {} });\n    class A {};\n    class B extends A {}\"\n  `)\n})\n\ntest('sourcemap source', async () => {\n  const map = (\n    await ssrTransform(\n      `export const a = 1`,\n      null,\n      'input.js',\n      'export const a = 1 /* */',\n    )\n  )?.map as SourceMap\n\n  expect(map?.sources).toStrictEqual(['input.js'])\n  expect(map?.sourcesContent).toStrictEqual(['export const a = 1 /* */'])\n})\n\ntest('sourcemap is correct for hoisted imports', async () => {\n  const code = `\\n\\n\\nconsole.log(foo, bar);\\nimport { foo } from 'vue';\\nimport { bar } from 'vue2';`\n  const result = (await ssrTransform(code, null, 'input.js', code))!\n\n  expect(result.code).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"foo\"]});\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"vue2\", {\"importedNames\":[\"bar\"]});\n\n\n\n    console.log((0,__vite_ssr_import_0__.foo), (0,__vite_ssr_import_1__.bar));\n\n    \"\n  `)\n\n  const traceMap = new TraceMap(result.map as any)\n  expect(originalPositionFor(traceMap, { line: 1, column: 0 })).toStrictEqual({\n    source: 'input.js',\n    line: 5,\n    column: 0,\n    name: null,\n  })\n  expect(originalPositionFor(traceMap, { line: 2, column: 0 })).toStrictEqual({\n    source: 'input.js',\n    line: 6,\n    column: 0,\n    name: null,\n  })\n})\n\ntest('sourcemap with multiple sources', async () => {\n  const code = readFixture('bundle.js')\n  const map = readFixture('bundle.js.map')\n\n  const result = await ssrTransform(code, JSON.parse(map), '', code)\n  assert(result?.map)\n\n  const { sources } = result.map as SourceMap\n  expect(sources).toContain('./first.ts')\n  expect(sources).toContain('./second.ts')\n\n  function readFixture(filename: string) {\n    const url = new URL(\n      `./fixtures/bundled-with-sourcemaps/${filename}`,\n      import.meta.url,\n    )\n\n    return readFileSync(fileURLToPath(url), 'utf8')\n  }\n})\n\ntest('sourcemap with multiple sources and nested paths', async () => {\n  const code = readFixture('dist.js')\n  const map = readFixture('dist.js.map')\n\n  const result = await ssrTransform(code, JSON.parse(map), '', code)\n  assert(result?.map)\n\n  const { sources } = result.map as SourceMap\n  expect(sources).toMatchInlineSnapshot(`\n    [\n      \"nested-directory/nested-file.js\",\n      \"entrypoint.js\",\n    ]\n  `)\n\n  function readFixture(filename: string) {\n    const url = new URL(\n      `./fixtures/multi-source-sourcemaps/${filename}`,\n      import.meta.url,\n    )\n\n    return readFileSync(fileURLToPath(url), 'utf8')\n  }\n})\n\ntest('overwrite bindings', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `import { inject } from 'vue';` +\n        `const a = { inject }\\n` +\n        `const b = { test: inject }\\n` +\n        `function c() { const { test: inject } = { test: true }; console.log(inject) }\\n` +\n        `const d = inject\\n` +\n        `function f() {  console.log(inject) }\\n` +\n        `function e() { const { inject } = { inject: true } }\\n` +\n        `function g() { const f = () => { const inject = true }; console.log(inject) }\\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"inject\"]});\n    const a = { inject: __vite_ssr_import_0__.inject };\n    const b = { test: __vite_ssr_import_0__.inject };\n    function c() { const { test: inject } = { test: true }; console.log(inject) }\n    const d = __vite_ssr_import_0__.inject;\n    function f() {  console.log((0,__vite_ssr_import_0__.inject)) }\n    function e() { const { inject } = { inject: true } }\n    function g() { const f = () => { const inject = true }; console.log((0,__vite_ssr_import_0__.inject)) }\n    \"\n  `)\n})\n\ntest('Empty array pattern', async () => {\n  expect(\n    await ssrTransformSimpleCode(`const [, LHS, RHS] = inMatch;`),\n  ).toMatchInlineSnapshot(`\"const [, LHS, RHS] = inMatch;\"`)\n})\n\ntest('function argument destructure', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport { foo, bar } from 'foo'\nconst a = ({ _ = foo() }) => {}\nfunction b({ _ = bar() }) {}\nfunction c({ _ = bar() + foo() }) {}\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"foo\",\"bar\"]});\n\n\n    const a = ({ _ = (0,__vite_ssr_import_0__.foo)() }) => {};\n    function b({ _ = (0,__vite_ssr_import_0__.bar)() }) {}\n    function c({ _ = (0,__vite_ssr_import_0__.bar)() + (0,__vite_ssr_import_0__.foo)() }) {}\n    \"\n  `)\n})\n\ntest('object destructure alias', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport { n } from 'foo'\nconst a = () => {\n  const { type: n = 'bar' } = {}\n  console.log(n)\n}\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"n\"]});\n\n\n    const a = () => {\n      const { type: n = 'bar' } = {};\n      console.log(n)\n    }\n    \"\n  `)\n\n  // #9585\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport { n, m } from 'foo'\nconst foo = {}\n\n{\n  const { [n]: m } = foo\n}\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"n\",\"m\"]});\n\n\n    const foo = {};\n\n    {\n      const { [__vite_ssr_import_0__.n]: m } = foo\n    }\n    \"\n  `)\n})\n\ntest('nested object destructure alias', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport { remove, add, get, set, rest, objRest } from 'vue'\n\nfunction a() {\n  const {\n    o: { remove },\n    a: { b: { c: [ add ] }},\n    d: [{ get }, set, ...rest],\n    ...objRest\n  } = foo\n\n  remove()\n  add()\n  get()\n  set()\n  rest()\n  objRest()\n}\n\nremove()\nadd()\nget()\nset()\nrest()\nobjRest()\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"remove\",\"add\",\"get\",\"set\",\"rest\",\"objRest\"]});\n\n\n\n    function a() {\n      const {\n        o: { remove },\n        a: { b: { c: [ add ] }},\n        d: [{ get }, set, ...rest],\n        ...objRest\n      } = foo;\n\n      remove();\n      add();\n      get();\n      set();\n      rest();\n      objRest()\n    }\n\n    (0,__vite_ssr_import_0__.remove)();\n    (0,__vite_ssr_import_0__.add)();\n    (0,__vite_ssr_import_0__.get)();\n    (0,__vite_ssr_import_0__.set)();\n    (0,__vite_ssr_import_0__.rest)();\n    (0,__vite_ssr_import_0__.objRest)()\n    \"\n  `)\n})\n\ntest('object props and methods', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport foo from 'foo'\n\nconst bar = 'bar'\n\nconst obj = {\n  foo() {},\n  [foo]() {},\n  [bar]() {},\n  foo: () => {},\n  [foo]: () => {},\n  [bar]: () => {},\n  bar(foo) {}\n}\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"default\"]});\n\n\n\n    const bar = 'bar';\n\n    const obj = {\n      foo() {},\n      [__vite_ssr_import_0__.default]() {},\n      [bar]() {},\n      foo: () => {},\n      [__vite_ssr_import_0__.default]: () => {},\n      [bar]: () => {},\n      bar(foo) {}\n    }\n    \"\n  `)\n})\n\ntest('class props', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport { remove, add } from 'vue'\n\nclass A {\n  remove = 1\n  add = null\n}\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"remove\",\"add\"]});\n\n\n\n    const add = __vite_ssr_import_0__.add;\n    const remove = __vite_ssr_import_0__.remove;\n    class A {\n      remove = 1\n      add = null\n    }\n    \"\n  `)\n})\n\ntest('class methods', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport foo from 'foo'\n\nconst bar = 'bar'\n\nclass A {\n  foo() {}\n  [foo]() {}\n  [bar]() {}\n  #foo() {}\n  bar(foo) {}\n}\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"default\"]});\n\n\n\n    const bar = 'bar';\n\n    class A {\n      foo() {}\n      [__vite_ssr_import_0__.default]() {}\n      [bar]() {}\n      #foo() {}\n      bar(foo) {}\n    }\n    \"\n  `)\n})\n\ntest('declare scope', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nimport { aaa, bbb, ccc, ddd } from 'vue'\n\nfunction foobar() {\n  ddd()\n\n  const aaa = () => {\n    bbb(ccc)\n    ddd()\n  }\n  const bbb = () => {\n    console.log('hi')\n  }\n  const ccc = 1\n  function ddd() {}\n\n  aaa()\n  bbb()\n  ccc()\n}\n\naaa()\nbbb()\n`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"vue\", {\"importedNames\":[\"aaa\",\"bbb\",\"ccc\",\"ddd\"]});\n\n\n\n    function foobar() {\n      ddd();\n\n      const aaa = () => {\n        bbb(ccc);\n        ddd()\n      };\n      const bbb = () => {\n        console.log('hi')\n      };\n      const ccc = 1;\n      function ddd() {}\n\n      aaa();\n      bbb();\n      ccc()\n    }\n\n    (0,__vite_ssr_import_0__.aaa)();\n    (0,__vite_ssr_import_0__.bbb)()\n    \"\n  `)\n})\n\ntest('jsx', async () => {\n  const code = `\n  import React from 'react'\n  import { Foo, Slot } from 'foo'\n\n  function Bar({ Slot = <Foo /> }) {\n    return (\n      <>\n        <Slot />\n      </>\n    )\n  }\n  `\n  const id = '/foo.jsx'\n  const result = await transformWithEsbuild(code, id)\n  expect(await ssrTransformSimpleCode(result.code, '/foo.jsx'))\n    .toMatchInlineSnapshot(`\n      \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"react\", {\"importedNames\":[\"default\"]});\n      const __vite_ssr_import_1__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"Foo\",\"Slot\"]});\n\n\n      function Bar({ Slot: Slot2 = /* @__PURE__ */ __vite_ssr_import_0__.default.createElement((0,__vite_ssr_import_1__.Foo), null) }) {\n        return /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(__vite_ssr_import_0__.default.Fragment, null, /* @__PURE__ */ __vite_ssr_import_0__.default.createElement(Slot2, null));\n      }\n      \"\n    `)\n})\n\ntest('continuous exports', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `\nexport function fn1() {\n}export function fn2() {\n}\n        `,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"fn1\", () => { try { return fn1 } catch {} });\n    __vite_ssr_exportName__(\"fn2\", () => { try { return fn2 } catch {} });\n\n    function fn1() {\n    };function fn2() {\n    }\n            \"\n  `)\n})\n\n// https://github.com/vitest-dev/vitest/issues/1141\ntest('export default expression', async () => {\n  // esbuild transform result of following TS code\n  // export default <MyFn> function getRandom() {\n  //   return Math.random()\n  // }\n  const code = `\nexport default (function getRandom() {\n  return Math.random();\n});\n`.trim()\n\n  expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"default\", () => { try { return __vite_ssr_export_default__ } catch {} });\n    const __vite_ssr_export_default__ = (function getRandom() {\n      return Math.random();\n    });\"\n  `)\n\n  expect(await ssrTransformSimpleCode(`export default (class A {});`))\n    .toMatchInlineSnapshot(`\n      \"__vite_ssr_exportName__(\"default\", () => { try { return __vite_ssr_export_default__ } catch {} });\n      const __vite_ssr_export_default__ = (class A {});\"\n    `)\n})\n\n// #8002\ntest('with hashbang', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `#!/usr/bin/env node\nconsole.log(\"it can parse the hashbang\")`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"#!/usr/bin/env node\n    console.log(\"it can parse the hashbang\")\"\n  `)\n})\n\ntest('import hoisted after hashbang', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `#!/usr/bin/env node\nconsole.log(foo);\nimport foo from \"foo\"`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"#!/usr/bin/env node\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"default\"]});\n    console.log((0,__vite_ssr_import_0__.default));\n    \"\n  `)\n})\n\ntest('identity function helper injected after hashbang', async () => {\n  expect(\n    await ssrTransformSimpleCode(\n      `#!/usr/bin/env node\nimport { foo } from \"foo\"\nfoo()`,\n    ),\n  ).toMatchInlineSnapshot(`\n    \"#!/usr/bin/env node\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foo\", {\"importedNames\":[\"foo\"]});\n\n    (0,__vite_ssr_import_0__.foo)()\"\n  `)\n})\n\n// #10289\ntest('track scope by class, function, condition blocks', async () => {\n  const code = `\nimport { foo, bar } from 'foobar'\nif (false) {\n  const foo = 'foo'\n  console.log(foo)\n} else if (false) {\n  const [bar] = ['bar']\n  console.log(bar)\n} else {\n  console.log(foo)\n  console.log(bar)\n}\nexport class Test {\n  constructor() {\n    if (false) {\n      const foo = 'foo'\n      console.log(foo)\n    } else if (false) {\n      const [bar] = ['bar']\n      console.log(bar)\n    } else {\n      console.log(foo)\n      console.log(bar)\n    }\n  }\n};`.trim()\n\n  expect(await ssrTransformSimpleCode(code)).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"Test\", () => { try { return Test } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foobar\", {\"importedNames\":[\"foo\",\"bar\"]});\n\n    if (false) {\n      const foo = 'foo';\n      console.log(foo)\n    } else if (false) {\n      const [bar] = ['bar'];\n      console.log(bar)\n    } else {\n      console.log((0,__vite_ssr_import_0__.foo));\n      console.log((0,__vite_ssr_import_0__.bar))\n    };\n    class Test {\n      constructor() {\n        if (false) {\n          const foo = 'foo';\n          console.log(foo)\n        } else if (false) {\n          const [bar] = ['bar'];\n          console.log(bar)\n        } else {\n          console.log((0,__vite_ssr_import_0__.foo));\n          console.log((0,__vite_ssr_import_0__.bar))\n        }\n      }\n    };;\"\n  `)\n})\n\n// #10386\ntest('track var scope by function', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\nimport { foo, bar } from 'foobar'\nfunction test() {\n  if (true) {\n    var foo = () => { var why = 'would' }, bar = 'someone'\n  }\n  return [foo, bar]\n}`),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foobar\", {\"importedNames\":[\"foo\",\"bar\"]});\n\n\n    function test() {\n      if (true) {\n        var foo = () => { var why = 'would' }, bar = 'someone'\n      };\n      return [foo, bar]\n    }\"\n  `)\n})\n\n// #11806\ntest('track scope by blocks', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\nimport { foo, bar, baz } from 'foobar'\nfunction test() {\n  [foo];\n  {\n    let foo = 10;\n    let bar = 10;\n  }\n  try {} catch (baz){ baz };\n  return bar;\n}`),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"foobar\", {\"importedNames\":[\"foo\",\"bar\",\"baz\"]});\n\n\n    function test() {\n      [__vite_ssr_import_0__.foo];\n      {\n        let foo = 10;\n        let bar = 10;\n      }\n      try {} catch (baz){ baz };;\n      return __vite_ssr_import_0__.bar;\n    }\"\n  `)\n})\n\ntest('track scope in for loops', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\nimport { test } from './test.js'\n\nfor (const test of tests) {\n  console.log(test)\n}\n\nfor (let test = 0; test < 10; test++) {\n  console.log(test)\n}\n\nfor (const test in tests) {\n  console.log(test)\n}`),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./test.js\", {\"importedNames\":[\"test\"]});\n\n\n\n    for (const test of tests) {\n      console.log(test)\n    };\n\n    for (let test = 0; test < 10; test++) {\n      console.log(test)\n    };\n\n    for (const test in tests) {\n      console.log(test)\n    }\"\n  `)\n})\n\ntest('avoid binding ClassExpression', async () => {\n  const result = await ssrTransformSimple(\n    `\nimport Foo, { Bar } from './foo';\n\nconsole.log(Foo, Bar);\nconst obj = {\n  foo: class Foo {},\n  bar: class Bar {}\n}\nconst Baz = class extends Foo {}\n`,\n  )\n  expect(result?.code).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./foo\", {\"importedNames\":[\"default\",\"Bar\"]});\n\n\n\n    console.log((0,__vite_ssr_import_0__.default), (0,__vite_ssr_import_0__.Bar));\n    const obj = {\n      foo: class Foo {},\n      bar: class Bar {}\n    };\n    const Baz = class extends __vite_ssr_import_0__.default {}\n    \"\n  `)\n})\n\ntest('import assertion attribute', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\nimport * as foo from './foo.json' with { type: 'json' };\nimport('./bar.json', { with: { type: 'json' } });\n`),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./foo.json\");\n\n\n    __vite_ssr_dynamic_import__('./bar.json', { with: { type: 'json' } });\n    \"\n  `)\n})\n\ntest('import and export ordering', async () => {\n  // Given all imported modules logs `mod ${mod}` on execution,\n  // and `foo` is `bar`, the logging order should be:\n  // \"mod a\", \"mod foo\", \"mod b\", \"bar1\", \"bar2\"\n  expect(\n    await ssrTransformSimpleCode(`\nconsole.log(foo + 1)\nexport * from './a'\nimport { foo } from './foo'\nexport * from './b'\nconsole.log(foo + 2)\n  `),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./a\");\n    __vite_ssr_exportAll__(__vite_ssr_import_0__);\n    ;const __vite_ssr_import_1__ = await __vite_ssr_import__(\"./foo\", {\"importedNames\":[\"foo\"]});\n    const __vite_ssr_import_2__ = await __vite_ssr_import__(\"./b\");\n    __vite_ssr_exportAll__(__vite_ssr_import_2__);\n    ;\n    console.log(__vite_ssr_import_1__.foo + 1);\n\n\n\n    console.log(__vite_ssr_import_1__.foo + 2)\n      \"\n  `)\n})\n\ntest('identity function is declared before used', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\nimport { foo } from './foo'\nexport default foo()\nexport * as bar from './bar'\nconsole.log(bar)\n  `),\n  ).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"default\", () => { try { return __vite_ssr_export_default__ } catch {} });\n    __vite_ssr_exportName__(\"bar\", () => { try { return __vite_ssr_import_1__ } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./foo\", {\"importedNames\":[\"foo\"]});\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"./bar\");\n    ;\n\n    const __vite_ssr_export_default__ = (0,__vite_ssr_import_0__.foo)();\n\n    console.log(bar)\n      \"\n  `)\n})\n\ntest('repro', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\\\nimport 'x'\nimport 'y'\n  `),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"x\");\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"y\");\n\n\n      \"\n  `)\n})\n\ntest('inject semicolon for (0, ...) wrapper', async () => {\n  expect(\n    await ssrTransformSimpleCode(`\nimport { f } from './f'\n\nlet x = 0;\n\nx\nf()\n\nif (1)\n  x\nf()\n\nif (1)\n  x\nelse\n  x\nf()\n\n\nlet y = x\nf()\n\nx /*;;*/ /*;;*/\nf()\n\nfunction z() {\n  x\n  f()\n\n  if (1) {\n    x\n    f()\n  }\n}\n\nlet a = {}\nf()\n\nlet b = () => {}\nf()\n\nfunction c() {\n}\nf()\n\nclass D {\n}\nf()\n\n{\n  x\n}\nf()\n\nswitch (1) {\n  case 1:\n    x\n    f()\n    break\n}\n\nif(0){}f()\n\nif(0){}else{}f()\n\nswitch(1){}f()\n\n{}f(1)\n`),\n  ).toMatchInlineSnapshot(`\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"./f\", {\"importedNames\":[\"f\"]});\n\n\n\n    let x = 0;\n\n    x;\n    (0,__vite_ssr_import_0__.f)();\n\n    if (1)\n      x;\n    (0,__vite_ssr_import_0__.f)();\n\n    if (1)\n      x\n    else\n      x;\n    (0,__vite_ssr_import_0__.f)();\n\n\n    let y = x;\n    (0,__vite_ssr_import_0__.f)();\n\n    x; /*;;*/ /*;;*/\n    (0,__vite_ssr_import_0__.f)();\n\n    function z() {\n      x;\n      (0,__vite_ssr_import_0__.f)();\n\n      if (1) {\n        x;\n        (0,__vite_ssr_import_0__.f)()\n      }\n    }\n\n    let a = {};\n    (0,__vite_ssr_import_0__.f)();\n\n    let b = () => {};\n    (0,__vite_ssr_import_0__.f)();\n\n    function c() {\n    }\n    (0,__vite_ssr_import_0__.f)();\n\n    class D {\n    }\n    (0,__vite_ssr_import_0__.f)();\n\n    {\n      x\n    }\n    (0,__vite_ssr_import_0__.f)();\n\n    switch (1) {\n      case 1:\n        x;\n        (0,__vite_ssr_import_0__.f)();\n        break\n    };\n\n    if(0){};(0,__vite_ssr_import_0__.f)();\n\n    if(0){}else{};(0,__vite_ssr_import_0__.f)();\n\n    switch(1){};(0,__vite_ssr_import_0__.f)();\n\n    {}(0,__vite_ssr_import_0__.f)(1)\n    \"\n  `)\n})\n\ntest('does not break minified code', async () => {\n  // Based on https://unpkg.com/@headlessui/vue@1.7.23/dist/components/transitions/transition.js\n  expect(\n    await ssrTransformSimpleCode(\n      `import O from 'a';\nconst c = () => {\n  if(true){return}O(1,{})\n}`,\n    ),\n  ).toMatchInlineSnapshot(\n    `\n    \"const __vite_ssr_import_0__ = await __vite_ssr_import__(\"a\", {\"importedNames\":[\"default\"]});\n\n    const c = () => {\n      if(true){return};(0,__vite_ssr_import_0__.default)(1,{})\n    }\"\n  `,\n  )\n})\n\ntest('combine mappings', async () => {\n  const server = await createServer({\n    configFile: false,\n    envDir: false,\n    logLevel: 'error',\n    plugins: [\n      {\n        name: 'test-mappings',\n        resolveId(source) {\n          if (source.startsWith('virtual:test-mappings')) {\n            return '\\0' + source\n          }\n        },\n        load(id) {\n          if (id.startsWith('\\0virtual:test-mappings')) {\n            const code = `export default \"test\";\\n`\n            if (id === '\\0virtual:test-mappings:empty') {\n              return { code, map: { mappings: '' } }\n            }\n            if (id === '\\0virtual:test-mappings:null') {\n              return { code, map: null }\n            }\n          }\n        },\n      },\n    ],\n  })\n\n  {\n    const result = await server.environments.ssr.transformRequest(\n      'virtual:test-mappings:empty',\n    )\n    expect(result?.map).toMatchInlineSnapshot(`\n      {\n        \"mappings\": \"\",\n      }\n    `)\n    const mod = await server.ssrLoadModule('virtual:test-mappings:empty')\n    expect(mod).toMatchInlineSnapshot(`\n      {\n        \"default\": \"test\",\n      }\n    `)\n  }\n\n  {\n    const result = await server.environments.ssr.transformRequest(\n      'virtual:test-mappings:null',\n    )\n    expect(result?.map).toMatchInlineSnapshot(`\n      SourceMap {\n        \"file\": undefined,\n        \"mappings\": \";AAAA,mCAAc,CAAC,CAAC,IAAI,CAAC;\",\n        \"names\": [],\n        \"sources\": [\n          \"virtual:test-mappings:null\",\n        ],\n        \"sourcesContent\": [\n          \"export default \"test\";\n      \",\n        ],\n        \"version\": 3,\n      }\n    `)\n    const mod = await server.ssrLoadModule('virtual:test-mappings:null')\n    expect(mod).toMatchInlineSnapshot(`\n      {\n        \"default\": \"test\",\n      }\n    `)\n  }\n})\n\ntest('deps', async () => {\n  const result = await ssrTransformSimple(`\\\nimport a from \"a\";\nexport { b } from \"b\";\nexport * from \"c\";\nexport * as d from \"d\";\nimport(\"e\")\nexport * as A from \"a\";\n`)\n  expect(result?.code).toMatchInlineSnapshot(`\n    \"__vite_ssr_exportName__(\"b\", () => { try { return __vite_ssr_import_1__.b } catch {} });\n    __vite_ssr_exportName__(\"d\", () => { try { return __vite_ssr_import_3__ } catch {} });\n    __vite_ssr_exportName__(\"A\", () => { try { return __vite_ssr_import_4__ } catch {} });\n    const __vite_ssr_import_0__ = await __vite_ssr_import__(\"a\", {\"importedNames\":[\"default\"]});\n    const __vite_ssr_import_1__ = await __vite_ssr_import__(\"b\", {\"importedNames\":[\"b\"]});\n    const __vite_ssr_import_2__ = await __vite_ssr_import__(\"c\");\n    __vite_ssr_exportAll__(__vite_ssr_import_2__);\n    const __vite_ssr_import_3__ = await __vite_ssr_import__(\"d\");\n    const __vite_ssr_import_4__ = await __vite_ssr_import__(\"a\");\n\n\n\n\n    __vite_ssr_dynamic_import__(\"e\");\n\n    \"\n  `)\n  expect({\n    deps: result?.deps,\n    dynamicDeps: result?.dynamicDeps,\n  }).toMatchInlineSnapshot(`\n    {\n      \"deps\": [\n        \"a\",\n        \"b\",\n        \"c\",\n        \"d\",\n      ],\n      \"dynamicDeps\": [\n        \"e\",\n      ],\n    }\n  `)\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/fetchModule.ts",
    "content": "import { pathToFileURL } from 'node:url'\nimport type { FetchResult } from 'vite/module-runner'\nimport type { EnvironmentModuleNode, TransformResult } from '..'\nimport { tryNodeResolve } from '../plugins/resolve'\nimport { isBuiltin, isExternalUrl, isFilePathESM } from '../utils'\nimport { unwrapId } from '../../shared/utils'\nimport {\n  MODULE_RUNNER_SOURCEMAPPING_SOURCE,\n  SOURCEMAPPING_URL,\n} from '../../shared/constants'\nimport { genSourceMapUrl } from '../server/sourcemap'\nimport type { DevEnvironment } from '../server/environment'\n\nexport interface FetchModuleOptions {\n  cached?: boolean\n  inlineSourceMap?: boolean\n  startOffset?: number\n}\n\n/**\n * Fetch module information for Vite runner.\n * @experimental\n */\nexport async function fetchModule(\n  environment: DevEnvironment,\n  url: string,\n  importer?: string,\n  options: FetchModuleOptions = {},\n): Promise<FetchResult> {\n  if (\n    url.startsWith('data:') ||\n    isBuiltin(environment.config.resolve.builtins, url)\n  ) {\n    return { externalize: url, type: 'builtin' }\n  }\n\n  // handle file urls from not statically analyzable dynamic import\n  const isFileUrl = url.startsWith('file://')\n\n  if (isExternalUrl(url) && !isFileUrl) {\n    return { externalize: url, type: 'network' }\n  }\n\n  // if there is no importer, the file is an entry point\n  // entry points are always internalized\n  if (!isFileUrl && importer && url[0] !== '.' && url[0] !== '/') {\n    const { isProduction, root } = environment.config\n    const { externalConditions, dedupe, preserveSymlinks } =\n      environment.config.resolve\n\n    const resolved = tryNodeResolve(url, importer, {\n      mainFields: ['main'],\n      conditions: externalConditions,\n      externalConditions,\n      external: [],\n      noExternal: [],\n      extensions: ['.js', '.cjs', '.json'],\n      dedupe,\n      preserveSymlinks,\n      tsconfigPaths: false,\n      isBuild: false,\n      isProduction,\n      root,\n      packageCache: environment.config.packageCache,\n      builtins: environment.config.resolve.builtins,\n    })\n    if (!resolved) {\n      const err: any = new Error(\n        `Cannot find module '${url}' imported from '${importer}'`,\n      )\n      err.code = 'ERR_MODULE_NOT_FOUND'\n      throw err\n    }\n    const file = pathToFileURL(resolved.id).toString()\n    const type = isFilePathESM(resolved.id, environment.config.packageCache)\n      ? 'module'\n      : 'commonjs'\n    return { externalize: file, type }\n  }\n\n  url = unwrapId(url)\n\n  const mod = await environment.moduleGraph.ensureEntryFromUrl(url)\n  const cached = !!mod.transformResult\n\n  // if url is already cached, we can just confirm it's also cached on the server\n  if (options.cached && cached) {\n    return { cache: true }\n  }\n\n  let result = await environment.transformRequest(url)\n\n  if (!result) {\n    throw new Error(\n      `[vite] transform failed for module '${url}'${\n        importer ? ` imported from '${importer}'` : ''\n      }.`,\n    )\n  }\n\n  if (options.inlineSourceMap !== false) {\n    result = inlineSourceMap(mod, result, options.startOffset)\n  }\n\n  // remove shebang\n  if (result.code[0] === '#')\n    result.code = result.code.replace(/^#!.*/, (s) => ' '.repeat(s.length))\n\n  return {\n    code: result.code,\n    file: mod.file,\n    id: mod.id!,\n    url: mod.url,\n    invalidate: !cached,\n  }\n}\n\nconst OTHER_SOURCE_MAP_REGEXP = new RegExp(\n  `//# ${SOURCEMAPPING_URL}=data:application/json[^,]+base64,([A-Za-z0-9+/=]+)$`,\n  'gm',\n)\n\nfunction inlineSourceMap(\n  mod: EnvironmentModuleNode,\n  result: TransformResult,\n  startOffset: number | undefined,\n) {\n  const map = result.map\n  let code = result.code\n\n  if (\n    !map ||\n    !('version' in map) ||\n    code.includes(MODULE_RUNNER_SOURCEMAPPING_SOURCE)\n  )\n    return result\n\n  // to reduce the payload size, we only inline vite node source map, because it's also the only one we use\n  OTHER_SOURCE_MAP_REGEXP.lastIndex = 0\n  if (OTHER_SOURCE_MAP_REGEXP.test(code))\n    code = code.replace(OTHER_SOURCE_MAP_REGEXP, '')\n\n  const sourceMap = startOffset\n    ? Object.assign({}, map, {\n        mappings: ';'.repeat(startOffset) + map.mappings,\n      })\n    : map\n  result.code = `${code.trimEnd()}\\n//# sourceURL=${\n    mod.id\n  }\\n${MODULE_RUNNER_SOURCEMAPPING_SOURCE}\\n//# ${SOURCEMAPPING_URL}=${genSourceMapUrl(sourceMap)}\\n`\n\n  return result\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/index.ts",
    "content": "import type { DepOptimizationConfig } from '../optimizer'\nimport { mergeWithDefaults } from '../utils'\n\nexport type SSRTarget = 'node' | 'webworker'\n\nexport type SsrDepOptimizationConfig = DepOptimizationConfig\n\nexport interface SSROptions {\n  noExternal?: string | RegExp | (string | RegExp)[] | true\n  external?: string[] | true\n\n  /**\n   * Define the target for the ssr build. The browser field in package.json\n   * is ignored for node but used if webworker is the target\n   * This option will be removed in a future major version\n   * @default 'node'\n   */\n  target?: SSRTarget\n\n  /**\n   * Control over which dependencies are optimized during SSR and esbuild options\n   * During build:\n   *   no external CJS dependencies are optimized by default\n   * During dev:\n   *   explicit no external CJS dependencies are optimized by default\n   * @experimental\n   */\n  optimizeDeps?: SsrDepOptimizationConfig\n\n  resolve?: {\n    /**\n     * Conditions that are used in the plugin pipeline. The default value is the root config's `resolve.conditions`.\n     *\n     * Use this to override the default ssr conditions for the ssr build.\n     *\n     * @default rootConfig.resolve.conditions\n     */\n    conditions?: string[]\n\n    /**\n     * Conditions that are used during ssr import (including `ssrLoadModule`) of externalized dependencies.\n     *\n     * @default ['node', 'module-sync']\n     */\n    externalConditions?: string[]\n\n    mainFields?: string[]\n  }\n}\n\nexport interface ResolvedSSROptions extends SSROptions {\n  target: SSRTarget\n  optimizeDeps: SsrDepOptimizationConfig\n}\n\nconst _ssrConfigDefaults = Object.freeze({\n  // noExternal\n  // external\n  target: 'node',\n  optimizeDeps: {},\n  // resolve\n} satisfies SSROptions)\nexport const ssrConfigDefaults: Readonly<Partial<SSROptions>> =\n  _ssrConfigDefaults\n\nexport function resolveSSROptions(\n  ssr: SSROptions | undefined,\n  preserveSymlinks: boolean,\n): ResolvedSSROptions {\n  const defaults = mergeWithDefaults(_ssrConfigDefaults, {\n    optimizeDeps: { esbuildOptions: { preserveSymlinks } },\n  } satisfies SSROptions)\n  return mergeWithDefaults(defaults, ssr ?? {})\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runnerImport.ts",
    "content": "import type { InlineConfig } from '../config'\nimport { resolveConfig } from '../config'\nimport { createRunnableDevEnvironment } from '../server/environments/runnableEnvironment'\nimport { mergeConfig } from '../utils'\n\ninterface RunnerImportResult<T> {\n  module: T\n  dependencies: string[]\n}\n\n/**\n * Import any file using the default Vite environment.\n * @experimental\n */\nexport async function runnerImport<T>(\n  moduleId: string,\n  inlineConfig?: InlineConfig,\n): Promise<RunnerImportResult<T>> {\n  const isModuleSyncConditionEnabled = (await import('#module-sync-enabled'))\n    .default\n  const config = await resolveConfig(\n    mergeConfig(inlineConfig || {}, {\n      configFile: false,\n      envDir: false,\n      cacheDir: process.cwd(),\n      environments: {\n        inline: {\n          consumer: 'server',\n          dev: {\n            moduleRunnerTransform: true,\n          },\n          resolve: {\n            external: true,\n            mainFields: [],\n            conditions: [\n              'node',\n              ...(isModuleSyncConditionEnabled ? ['module-sync'] : []),\n            ],\n          },\n        },\n      },\n    } satisfies InlineConfig),\n    'serve',\n  )\n  const environment = createRunnableDevEnvironment('inline', config, {\n    runnerOptions: {\n      hmr: {\n        logger: false,\n      },\n    },\n    hot: false,\n  })\n  await environment.init()\n  try {\n    const module = await environment.runner.import(moduleId)\n    const modules = [\n      ...environment.runner.evaluatedModules.urlToIdModuleMap.values(),\n    ]\n    const dependencies = modules\n      .filter((m) => {\n        // ignore all externalized modules\n        if (!m.meta || 'externalize' in m.meta) {\n          return false\n        }\n        // ignore the current module\n        return m.exports !== module\n      })\n      .map((m) => m.file)\n    return {\n      module,\n      dependencies,\n    }\n  } finally {\n    await environment.close()\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/a.ts",
    "content": "export const a = 'a'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/assets/placeholder.txt",
    "content": ""
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/assets.js",
    "content": "export { default as mov } from './assets/placeholder.mov'\nexport { default as txt } from './assets/placeholder.txt'\nexport { default as png } from './assets/placeholder.png'\nexport { default as webp } from './assets/placeholder.webp'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/b.ts",
    "content": "export const b = 'b'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/basic.js",
    "content": "export const name = 'basic'\n\nexport const meta = import.meta\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/builtin-import.ts",
    "content": "import { basename } from 'node:path'\n\nexport default basename('/foo/bar/baz.txt')\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/c.ts",
    "content": "export { a as c } from './a'\n\nimport.meta.hot?.accept(() => {\n  console.log('accept c')\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/circular/circular-a.js",
    "content": "export { b } from './circular-b'\nexport const a = 'a'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/circular/circular-b.js",
    "content": "export { a } from './circular-a'\nexport const b = 'b'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/circular/circular-index.js",
    "content": "export { a } from './circular-a'\nexport { b } from './circular-b'\n\n// since there is no .accept, it does full reload\nimport.meta.hot.on('vite:beforeFullReload', () => {\n  console.log('full reload')\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cjs-external/index.cjs",
    "content": "module.exports = {\n  hello: () => 'world',\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cjs-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/cjs-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"commonjs\",\n  \"main\": \"index.cjs\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cjs-external-existing.js",
    "content": "import { hello } from '@vitejs/cjs-external'\n\nexport const result = hello()\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cjs-external-non-existing.js",
    "content": "import { nonExisting } from '@vitejs/cjs-external'\n\nconsole.log(nonExisting)\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic/action.js",
    "content": "export function someAction() {}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic/entry-cyclic.js",
    "content": "export default async function main() {\n  await import('./entry.js')\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic/entry.js",
    "content": "export async function setupCyclic() {\n  const mod = await import('./entry-cyclic.js')\n  await mod.default()\n}\n\nexport async function importAction(id) {\n  return await import(/* @vite-ignore */ id)\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/README.md",
    "content": "- `test1` - `test5`\n\nCyclic import example based on https://github.com/vitejs/vite/issues/14048#issuecomment-2354774156\n\n```mermaid\nflowchart TD\n    B(dep1.js) -->|dep1| A(index.js)\n    A -->|dep1| C(dep2.js)\n    C -->|dep2| A\n    A -->|dep1, dep2| entry.js\n```\n\n---\n\n- `test6`\n\n```mermaid\nflowchart TD\n    A(dep1.js) -->|dep1| B\n    B(dep2.js) -->|dep2| A\n    A -->|dep1| C(index.js)\n```\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep1.js",
    "content": "export const dep1 = { ok: true }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/dep2.js",
    "content": "import { dep1 } from './index.js'\nexport const dep2 = { ok: dep1.ok }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test1/index.js",
    "content": "import { dep1 } from './dep1.js'\nexport { dep1 }\n\nimport { dep2 } from './dep2.js'\nexport { dep2 }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep1.js",
    "content": "export const dep1 = { ok: true }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/dep2.js",
    "content": "import { dep1 } from './index.js'\nexport const dep2 = { ok: dep1.ok }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test2/index.js",
    "content": "export { dep1 } from './dep1.js'\nexport { dep2 } from './dep2.js'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep1.js",
    "content": "export const dep1 = { ok: true }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/dep2.js",
    "content": "import { dep1 } from './index.js'\nexport const dep2 = { ok: dep1.ok }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test3/index.js",
    "content": "import { dep1 } from './dep1.js'\nimport { dep2 } from './dep2.js'\nexport { dep1 }\nexport { dep2 }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep1.js",
    "content": "export const dep1 = { ok: true }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/dep2.js",
    "content": "import { dep1 } from './index.js'\nexport const dep2 = { ok: dep1.ok }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test4/index.js",
    "content": "export * from './dep1.js'\nexport * from './dep2.js'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep1.js",
    "content": "export const dep1 = { ok: true }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/dep2.js",
    "content": "import { dep1 } from './index.js'\nexport const dep2 = { ok: dep1.ok }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/index.js",
    "content": "import { dep2 } from './dep2.js'\nexport { dep2 }\n\nimport { dep1 } from './dep1.js'\nexport { dep1 }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test6/dep1.js",
    "content": "import { dep2 } from './dep2.js'\nexport const dep1 = 'dep1: ' + dep2\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test6/dep2.js",
    "content": "import { dep1 } from './dep1.js'\nexport const dep2 = 'dep2: ' + dep1\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test6/index.js",
    "content": "import { dep1 } from './dep1.js'\nexport { dep1 }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test7/Ion.js",
    "content": "export { IonTypes } from './IonTypes.js'\nimport * as dom from './dom/index.js'\nexport { dom }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test7/IonTypes.js",
    "content": "export const IonTypes = {\n  BLOB: 'Blob',\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test7/README.md",
    "content": "reproduction from https://github.com/vitest-dev/vitest/issues/4143#issuecomment-1724526796\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test7/dom/Blob.js",
    "content": "import { IonTypes } from '../Ion.js'\nexport const Blob = IonTypes.BLOB\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test7/dom/index.js",
    "content": "export { Blob } from './Blob.js'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test9/dep.js",
    "content": "import dep from './index.js'\nexport default dep\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test9/index.js",
    "content": "import dep from './dep.js'\nexport default dep\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/d.ts",
    "content": "export { c as d } from './c'\n\nimport.meta.hot?.accept(() => {\n  console.log('accept d')\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/default-string.ts",
    "content": "const str: string = 'hello world'\n\nexport default str\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/dynamic-import.js",
    "content": "import path from 'node:path'\nimport * as staticModule from './simple'\nimport { pathToFileURL } from 'node:url'\n\nexport const initialize = async () => {\n  const nameRelative = './simple'\n  const nameAbsolute = '/fixtures/simple'\n  const nameAbsoluteExtension = '/fixtures/simple.js'\n  const absolutePath = path.join(import.meta.dirname, 'simple.js')\n  const fileUrl = pathToFileURL(absolutePath)\n  return {\n    dynamicProcessed: await import('./simple'),\n    dynamicRelative: await import(nameRelative),\n    dynamicAbsolute: await import(nameAbsolute),\n    dynamicAbsoluteExtension: await import(nameAbsoluteExtension),\n    dynamicAbsoluteFull: await import(\n      (process.platform === 'win32' ? '/@fs/' : '') + absolutePath\n    ),\n    dynamicFileUrl: await import(fileUrl),\n    static: staticModule,\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/esm-external/index.mjs",
    "content": "export const hello = () => 'world'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/esm-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/esm-external\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\",\n  \"main\": \"index.mjs\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/esm-external-existing.js",
    "content": "import { hello } from '@vitejs/esm-external'\n\nexport const result = hello()\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/esm-external-non-existing.js",
    "content": "import { nonExisting } from '@vitejs/esm-external'\n\nconsole.log(nonExisting)\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/execution-order-re-export/dep1.js",
    "content": "console.log('dep1')\nexport {}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/execution-order-re-export/dep2.js",
    "content": "console.log('dep2')\nexport {}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/execution-order-re-export/index.js",
    "content": "export * from './dep1.js'\nimport './dep2.js'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/has-error-deep.ts",
    "content": "function crash(message: string) {\n  throw new Error(message)\n}\n\nexport function main(): void {\n  crash('crash')\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/has-error-first-comment.ts",
    "content": "// comment\nthrow new Error('__TEST__')\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/has-error-first.js",
    "content": "throw new Error('__TEST__')\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/has-error.js",
    "content": "// comment\nthrow new Error('module error')\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/hmr.js",
    "content": "export const hmr = import.meta.hot\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/import-external.ts",
    "content": "import 'tinyglobby'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/installed.js",
    "content": "export * from 'tinyspy'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/invalid-package/deps/test-dep-invalid-exports/package.json",
    "content": "{\n  \"name\": \"test-dep-invalid-exports\",\n  \"private\": true\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/invalid-package/test.js",
    "content": "export async function test() {\n  try {\n    const result = await import('test-dep-invalid-exports')\n    return { ok: true, data: result }\n  } catch (e) {\n    return { ok: false, data: e }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/package.json",
    "content": "{\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test1/dep.js",
    "content": "export default function f() {\n  return 0\n}\n\nf = () => 1\n\nf = () => 2\n\nexport function update() {\n  f = () => 3\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test1/index.js",
    "content": "import f, { update } from './dep.js'\n\nconst x = f()\nupdate()\nconst y = f()\nexport default [x, y]\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test2/dep.js",
    "content": "function f() {\n  return 0\n}\n\nf = () => 1\n\nexport default f\n\nf = () => 2\n\nexport function update() {\n  f = () => 3\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test2/index.js",
    "content": "import f, { update } from './dep.js'\n\nconst x = f()\nupdate()\nconst y = f()\nexport default [x, y]\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test3/dep.js",
    "content": "function f() {\n  return 0\n}\n\nf = () => 1\n\nexport { f as default }\n\nf = () => 2\n\nexport function update() {\n  f = () => 3\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test3/index.js",
    "content": "import f, { update } from './dep.js'\n\nconst x = f()\nupdate()\nconst y = f()\nexport default [x, y]\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test4/dep.js",
    "content": "export default class C {\n  static f = () => 0\n}\n\nC = class {\n  static f = () => 1\n}\n\nC = class {\n  static f = () => 2\n}\n\nexport function update() {\n  C = class {\n    static f = () => 3\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/live-binding/test4/index.js",
    "content": "import C, { update } from './dep.js'\n\nconst x = C.f()\nupdate()\nconst y = C.f()\nexport default [x, y]\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/native.js",
    "content": "export { existsSync } from 'node:fs'\n// eslint-disable-next-line n/prefer-node-protocol -- testing that importing without node prefix works\nexport { readdirSync } from 'fs'\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/no-this/importee.js",
    "content": "export function foo() {\n  return this\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/no-this/importer.js",
    "content": "import { foo } from './importee.js'\n\nexport const result = foo()\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/oxc-runtime-helper.ts",
    "content": "function html(strings: TemplateStringsArray, ...values: unknown[]) {\n  return strings.join('')\n}\nexport const result = html`<script>\n  console.log('hi')\n</script>`\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/pre-source-mapped-file.js",
    "content": "import 'node:path'\nexport default function testStack() {\n  innerTestStack()\n}\nimport 'node:util'\nfunction innerTestStack() {\n  throw new Error('__TEST_STACK_TRANSPILED_INLINE__')\n}\n//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidHJhbnNwaWxlZC1pbmxpbmUudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAnbm9kZTpwYXRoJ1xuXG5leHBvcnQgdHlwZSBEdW1teSA9IHtcbiAgZm9vOiBcImZvb1wiLFxufVxuXG4vKipcbiAqIGR1bW15XG4gKiBkdW1teVxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB0ZXN0U3RhY2soKSB7XG4gIGlubmVyVGVzdFN0YWNrKClcbn1cblxuaW1wb3J0ICdub2RlOnV0aWwnXG5cbi8qKlxuICogYmFyXG4gKiBiYXJcbiAqL1xuZnVuY3Rpb24gaW5uZXJUZXN0U3RhY2soKSB7XG4gIHRocm93IG5ldyBFcnJvcignX19URVNUX1NUQUNLX1RSQU5TUElMRURfSU5MSU5FX18nKVxufSJdLAogICJtYXBwaW5ncyI6ICJBQUFBLE9BQU87QUFVUCx3QkFBd0IsWUFBWTtBQUNsQyxpQkFBZTtBQUNqQjtBQUVBLE9BQU87QUFNUCxTQUFTLGlCQUFpQjtBQUN4QixRQUFNLElBQUksTUFBTSxrQ0FBa0M7QUFDcEQ7IiwKICAibmFtZXMiOiBbXQp9Cg==\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/simple.js",
    "content": "export const test = 'I am initialized'\n\nimport.meta.hot?.accept()\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/string-literal-sourcemap.ts",
    "content": "// This file contains sourceMappingURL pattern in string literals\n// which should not crash the module runner\n\nconst text = '//# sourceMappingURL=data:application/json;base64,invalidbase64'\n\nexport function getMessage() {\n  return text\n}\n\nexport function throwError() {\n  throw new Error('Test error for stacktrace')\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/test.css",
    "content": ".test {\n  color: red;\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/test.module.css",
    "content": ".test {\n  color: red;\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/throws-error-method.ts",
    "content": "interface Foo {\n  bar: string\n}\n\nexport function throwError(foo?: Foo): void {\n  throw new Error('method error')\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/top-level-object.js",
    "content": "const Object = 'my-object'\nexport { Object }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/virtual.js",
    "content": "import { msg as msg0 } from 'virtual0:test'\nimport { msg } from 'virtual:test'\n\nexport { msg0, msg }\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/worker.invoke.mjs",
    "content": "// @ts-check\n\nimport { BroadcastChannel, parentPort } from 'node:worker_threads'\nimport {\n  ESModulesEvaluator,\n  ModuleRunner,\n  createNodeImportMeta,\n} from 'vite/module-runner'\nimport { createBirpc } from 'birpc'\n\nif (!parentPort) {\n  throw new Error('File \"worker.js\" must be run in a worker thread')\n}\n\n/** @type {import('worker_threads').MessagePort} */\nconst pPort = parentPort\n\n/** @type {import('birpc').BirpcReturn<{ invoke: (data: any) => any }>} */\nconst rpc = createBirpc(\n  {},\n  {\n    post: (data) => pPort.postMessage(data),\n    on: (data) => pPort.on('message', data),\n  },\n)\n\nconst runner = new ModuleRunner(\n  {\n    transport: {\n      invoke(data) {\n        return rpc.invoke(data)\n      },\n    },\n    createImportMeta: createNodeImportMeta,\n    hmr: false,\n  },\n  new ESModulesEvaluator(),\n)\n\nconst channel = new BroadcastChannel('vite-worker:invoke')\nchannel.onmessage = async (message) => {\n  try {\n    const mod = await runner.import(message.data.id)\n    channel.postMessage({ result: mod.default })\n  } catch (e) {\n    channel.postMessage({ error: e.stack })\n  }\n}\nparentPort.postMessage('ready')\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/fixtures/worker.mjs",
    "content": "// @ts-check\n\nimport { BroadcastChannel, parentPort } from 'node:worker_threads'\nimport {\n  ESModulesEvaluator,\n  ModuleRunner,\n  createNodeImportMeta,\n} from 'vite/module-runner'\n\nif (!parentPort) {\n  throw new Error('File \"worker.js\" must be run in a worker thread')\n}\n\n/** @type {import('worker_threads').MessagePort} */\nconst pPort = parentPort\n\n/** @type {import('vite/module-runner').ModuleRunnerTransport} */\nconst messagePortTransport = {\n  connect({ onMessage, onDisconnection }) {\n    pPort.on('message', onMessage)\n    pPort.on('close', onDisconnection)\n  },\n  send(data) {\n    pPort.postMessage(data)\n  },\n}\n\nconst runner = new ModuleRunner(\n  {\n    transport: messagePortTransport,\n    createImportMeta: createNodeImportMeta,\n  },\n  new ESModulesEvaluator(),\n)\n\nconst channel = new BroadcastChannel('vite-worker')\nchannel.onmessage = async (message) => {\n  try {\n    const mod = await runner.import(message.data.id)\n    channel.postMessage({ result: mod.default })\n  } catch (e) {\n    channel.postMessage({ error: e.stack })\n  }\n}\nparentPort.postMessage('ready')\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/package.json",
    "content": "{\n  \"name\": \"@vitejs/unit-runtime\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"engines\": {\n    \"node\": \"^20.19.0 || >=22.12.0\"\n  },\n  \"dependencies\": {\n    \"@vitejs/cjs-external\": \"link:./fixtures/cjs-external\",\n    \"@vitejs/esm-external\": \"link:./fixtures/esm-external\",\n    \"test-dep-invalid-exports\": \"file:./fixtures/invalid-package/deps/test-dep-invalid-exports\",\n    \"tinyspy\": \"2.2.0\",\n    \"birpc\": \"^0.2.19\"\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/server-hmr.spec.ts",
    "content": "import { describe, expect } from 'vitest'\nimport { createModuleRunnerTester } from './utils'\n\ndescribe(\n  'module runner hmr works as expected',\n  async () => {\n    const it = await createModuleRunnerTester({\n      server: {\n        // override watch options because it's disabled by default\n        watch: {},\n      },\n    })\n\n    it('hmr options are defined', async ({ runner }) => {\n      expect(runner.hmrClient).toBeDefined()\n\n      const mod = await runner.import('/fixtures/hmr.js')\n      expect(mod).toHaveProperty('hmr')\n      expect(mod.hmr).toHaveProperty('accept')\n    })\n\n    it('correctly populates hmr client', async ({ runner }) => {\n      const mod = await runner.import('/fixtures/d')\n      expect(mod.d).toBe('a')\n\n      const fixtureC = '/fixtures/c.ts'\n      const fixtureD = '/fixtures/d.ts'\n\n      expect(runner.hmrClient!.hotModulesMap.size).toBe(2)\n      expect(runner.hmrClient!.dataMap.size).toBe(2)\n      expect(runner.hmrClient!.ctxToListenersMap.size).toBe(2)\n\n      for (const fixture of [fixtureC, fixtureD]) {\n        expect(runner.hmrClient!.hotModulesMap.has(fixture)).toBe(true)\n        expect(runner.hmrClient!.dataMap.has(fixture)).toBe(true)\n        expect(runner.hmrClient!.ctxToListenersMap.has(fixture)).toBe(true)\n      }\n    })\n  },\n  process.env.CI ? 50_00 : 5_000,\n)\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/server-no-hmr.spec.ts",
    "content": "import { describe, expect } from 'vitest'\nimport { createModuleRunnerTester } from './utils'\n\ndescribe('module runner hmr works as expected', async () => {\n  const it = await createModuleRunnerTester({\n    server: {\n      // override watch options because it's disabled by default\n      watch: {},\n      hmr: false,\n    },\n  })\n\n  it(\"hmr client is not defined if it's disabled\", async ({ runner }) => {\n    expect(runner.hmrClient).toBeUndefined()\n\n    const mod = await runner.import('/fixtures/hmr.js')\n    expect(mod).toHaveProperty('hmr')\n    expect(mod.hmr).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/server-runtime.spec.ts",
    "content": "import { existsSync, readdirSync } from 'node:fs'\nimport { posix, win32 } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { describe, expect, vi } from 'vitest'\nimport { isWindows } from '../../../../shared/utils'\nimport type { ExternalFetchResult } from '../../../../shared/invokeMethods'\nimport { createModuleRunnerTester } from './utils'\n\nconst _URL = URL\n\ndescribe('module runner initialization', async () => {\n  const it = await createModuleRunnerTester({\n    resolve: {\n      external: ['tinyglobby'],\n      noExternal: ['@oxc-project/runtime'],\n    },\n  })\n\n  it('correctly runs ssr code', async ({ runner }) => {\n    const mod = await runner.import('/fixtures/simple.js')\n    expect(mod.test).toEqual('I am initialized')\n\n    // loads the same module if id is a file url\n    const fileUrl = new _URL('./fixtures/simple.js', import.meta.url)\n    const mod2 = await runner.import(fileUrl.toString())\n    expect(mod).toBe(mod2)\n\n    // loads the same module if id is a file path\n    const filePath = fileURLToPath(fileUrl)\n    const mod3 = await runner.import(filePath)\n    expect(mod).toBe(mod3)\n  })\n\n  it('can load virtual modules as an entry point', async ({ runner }) => {\n    const mod = await runner.import('virtual:test')\n    expect(mod.msg).toBe('virtual')\n\n    // already resolved id works similar to `transformRequest`\n    expect(await runner.import(`\\0virtual:normal`)).toMatchInlineSnapshot(`\n      {\n        \"default\": \"ok\",\n      }\n    `)\n\n    // escaped virtual module id works\n    expect(await runner.import(`/@id/__x00__virtual:normal`))\n      .toMatchInlineSnapshot(`\n      {\n        \"default\": \"ok\",\n      }\n    `)\n\n    // timestamp query works\n    expect(await runner.import(`virtual:normal?t=${Date.now()}`))\n      .toMatchInlineSnapshot(`\n      {\n        \"default\": \"ok\",\n      }\n    `)\n\n    // other arbitrary queries don't work\n    await expect(() =>\n      runner.import('virtual:normal?abcd=1234'),\n    ).rejects.toMatchObject({\n      message: expect.stringContaining(\n        'Failed to load url virtual:normal?abcd=1234',\n      ),\n    })\n  })\n\n  it('css is loaded correctly', async ({ runner }) => {\n    const css = await runner.import('/fixtures/test.css')\n    expect(css.default).toBe(undefined)\n    const module = await runner.import('/fixtures/test.module.css')\n    expect(module).toMatchObject({\n      default: {\n        test: expect.stringMatching(/^_test_/),\n      },\n      test: expect.stringMatching(/^_test_/),\n    })\n  })\n\n  it('assets are loaded correctly', async ({ runner }) => {\n    const assets = await runner.import('/fixtures/assets.js')\n    expect(assets).toMatchObject({\n      mov: '/fixtures/assets/placeholder.mov',\n      txt: '/fixtures/assets/placeholder.txt',\n      png: '/fixtures/assets/placeholder.png',\n      webp: '/fixtures/assets/placeholder.webp',\n    })\n  })\n\n  it('ids with Vite queries are loaded correctly', async ({ runner }) => {\n    const raw = await runner.import('/fixtures/simple.js?raw')\n    expect(raw.default).toMatchInlineSnapshot(`\n      \"export const test = 'I am initialized'\n\n      import.meta.hot?.accept()\n      \"\n    `)\n    const url = await runner.import('/fixtures/simple.js?url')\n    expect(url.default).toMatchInlineSnapshot(`\"/fixtures/simple.js\"`)\n    const inline = await runner.import('/fixtures/test.css?inline')\n    expect(inline.default).toMatchInlineSnapshot(`\n      \".test {\n        color: red;\n      }\n      \"\n    `)\n  })\n\n  it('modules with query strings are treated as different modules', async ({\n    runner,\n  }) => {\n    const modSimple = await runner.import('/fixtures/simple.js')\n    const modUrl = await runner.import('/fixtures/simple.js?url')\n    expect(modSimple).not.toBe(modUrl)\n    expect(modUrl.default).toBe('/fixtures/simple.js')\n  })\n\n  it('exports is not modifiable', async ({ runner }) => {\n    const mod = await runner.import('/fixtures/simple.js')\n    expect(Object.isSealed(mod)).toBe(true)\n    expect(() => {\n      mod.test = 'I am modified'\n    }).toThrowErrorMatchingInlineSnapshot(\n      `[TypeError: Cannot set property test of [object Module] which has only a getter]`,\n    )\n    expect(() => {\n      delete mod.test\n    }).toThrowErrorMatchingInlineSnapshot(\n      `[TypeError: Cannot delete property 'test' of [object Module]]`,\n    )\n    expect(() => {\n      Object.defineProperty(mod, 'test', { value: 'I am modified' })\n    }).toThrowErrorMatchingInlineSnapshot(\n      `[TypeError: Cannot redefine property: test]`,\n    )\n    expect(() => {\n      mod.other = 'I am added'\n    }).toThrowErrorMatchingInlineSnapshot(\n      `[TypeError: Cannot add property other, object is not extensible]`,\n    )\n  })\n\n  it('throws the same error', async ({ runner }) => {\n    expect.assertions(3)\n    const s = Symbol()\n    try {\n      await runner.import('/fixtures/has-error.js')\n    } catch (e) {\n      expect(e[s]).toBeUndefined()\n      e[s] = true\n      expect(e[s]).toBe(true)\n    }\n\n    try {\n      await runner.import('/fixtures/has-error.js')\n    } catch (e) {\n      expect(e[s]).toBe(true)\n    }\n  })\n\n  it('importing external cjs library checks exports', async ({ runner }) => {\n    await expect(() => runner.import('/fixtures/cjs-external-non-existing.js'))\n      .rejects.toThrowErrorMatchingInlineSnapshot(`\n      [SyntaxError: [vite] Named export 'nonExisting' not found. The requested module '@vitejs/cjs-external' is a CommonJS module, which may not support all module.exports as named exports.\n      CommonJS modules can always be imported via the default export, for example using:\n\n      import pkg from '@vitejs/cjs-external';\n      const {nonExisting} = pkg;\n      ]\n    `)\n    // subsequent imports of the same external package should not throw if imports are correct\n    await expect(\n      runner.import('/fixtures/cjs-external-existing.js'),\n    ).resolves.toMatchObject({\n      result: 'world',\n    })\n  })\n\n  it('importing external esm library checks exports', async ({ runner }) => {\n    await expect(() =>\n      runner.import('/fixtures/esm-external-non-existing.js'),\n    ).rejects.toThrowErrorMatchingInlineSnapshot(\n      `[SyntaxError: [vite] The requested module '@vitejs/esm-external' does not provide an export named 'nonExisting']`,\n    )\n    // subsequent imports of the same external package should not throw if imports are correct\n    await expect(\n      runner.import('/fixtures/esm-external-existing.js'),\n    ).resolves.toMatchObject({\n      result: 'world',\n    })\n  })\n\n  it(\"dynamic import doesn't produce duplicates\", async ({ runner }) => {\n    const mod = await runner.import('/fixtures/dynamic-import.js')\n    const modules = await mod.initialize()\n    // toBe checks that objects are actually the same, not just structurally\n    // using toEqual here would be a mistake because it check the structural difference\n    expect(modules.static).toBe(modules.dynamicProcessed)\n    expect(modules.static).toBe(modules.dynamicRelative)\n    expect(modules.static).toBe(modules.dynamicAbsolute)\n    expect(modules.static).toBe(modules.dynamicAbsoluteExtension)\n    expect(modules.static).toBe(modules.dynamicAbsoluteFull)\n    expect(modules.static).toBe(modules.dynamicFileUrl)\n  })\n\n  it('correctly imports a virtual module', async ({ runner }) => {\n    const mod = await runner.import('/fixtures/virtual.js')\n    expect(mod.msg0).toBe('virtual0')\n    expect(mod.msg).toBe('virtual')\n  })\n\n  it('importing package from node_modules', async ({ runner }) => {\n    const mod = (await runner.import(\n      '/fixtures/installed.js',\n    )) as typeof import('tinyspy')\n    const fn = mod.spy()\n    fn()\n    expect(fn.called).toBe(true)\n  })\n\n  it('importing native node package', async ({ runner }) => {\n    const mod = await runner.import('/fixtures/native.js')\n    expect(mod.readdirSync).toBe(readdirSync)\n    expect(mod.existsSync).toBe(existsSync)\n  })\n\n  it('correctly resolves module url', async ({ runner, server }) => {\n    const { meta } = await runner.import('/fixtures/basic')\n    const basicUrl = new _URL('./fixtures/basic.js', import.meta.url).toString()\n    expect(meta.url).toBe(basicUrl)\n\n    const filename = meta.filename!\n    const dirname = meta.dirname!\n\n    if (isWindows) {\n      const cwd = process.cwd()\n      const drive = `${cwd[0].toUpperCase()}:\\\\`\n      const root = server.config.root.replace(/\\\\/g, '/')\n\n      expect(filename.startsWith(drive)).toBe(true)\n      expect(dirname.startsWith(drive)).toBe(true)\n\n      expect(filename).toBe(win32.join(root, '.\\\\fixtures\\\\basic.js'))\n      expect(dirname).toBe(win32.join(root, '.\\\\fixtures'))\n    } else {\n      const root = server.config.root\n\n      expect(posix.join(root, './fixtures/basic.js')).toBe(filename)\n      expect(posix.join(root, './fixtures')).toBe(dirname)\n    }\n  })\n\n  it(`no maximum call stack error ModuleRunner.isCircularImport`, async ({\n    runner,\n  }) => {\n    // entry.js ⇔ entry-cyclic.js\n    //   ⇓\n    // action.js\n    const mod = await runner.import('/fixtures/cyclic/entry')\n    await mod.setupCyclic()\n    const action = await mod.importAction('/fixtures/cyclic/action')\n    expect(action).toBeDefined()\n  })\n\n  it('this of the exported function should be undefined', async ({\n    runner,\n  }) => {\n    const mod = await runner.import('/fixtures/no-this/importer.js')\n    expect(mod.result).toBe(undefined)\n  })\n\n  it.for([\n    '/fixtures/cyclic2/test1/index.js',\n    '/fixtures/cyclic2/test2/index.js',\n    '/fixtures/cyclic2/test3/index.js',\n    '/fixtures/cyclic2/test4/index.js',\n  ] as const)(`cyclic %s`, async (entry, { runner }) => {\n    const mod = await runner.import(entry)\n    expect({ ...mod }).toEqual({\n      dep1: {\n        ok: true,\n      },\n      dep2: {\n        ok: true,\n      },\n    })\n  })\n\n  it(`cyclic invalid 1`, async ({ runner }) => {\n    // Node also fails but with a different message\n    //   $ node packages/vite/src/node/ssr/runtime/__tests__/fixtures/cyclic2/test5/index.js\n    //   ReferenceError: Cannot access 'dep1' before initialization\n    await expect(() =>\n      runner.import('/fixtures/cyclic2/test5/index.js'),\n    ).rejects.toMatchInlineSnapshot(\n      `[TypeError: Cannot read properties of undefined (reading 'ok')]`,\n    )\n  })\n\n  it(`cyclic invalid 2`, async ({ runner }) => {\n    // It should be an error but currently `undefined` fallback.\n    expect(\n      await runner.import('/fixtures/cyclic2/test6/index.js'),\n    ).toMatchInlineSnapshot(\n      `\n      {\n        \"dep1\": \"dep1: dep2: undefined\",\n      }\n    `,\n    )\n  })\n\n  it(`cyclic with mixed import and re-export`, async ({ runner }) => {\n    const mod = await runner.import('/fixtures/cyclic2/test7/Ion.js')\n    expect(mod).toMatchInlineSnapshot(`\n      {\n        \"IonTypes\": {\n          \"BLOB\": \"Blob\",\n        },\n        \"dom\": {\n          \"Blob\": \"Blob\",\n        },\n      }\n    `)\n  })\n\n  it(`execution order with mixed import and re-export`, async ({\n    runner,\n    onTestFinished,\n  }) => {\n    const spy = vi.spyOn(console, 'log').mockImplementation(() => {})\n    onTestFinished(() => spy.mockRestore())\n\n    await runner.import('/fixtures/execution-order-re-export/index.js')\n    expect(spy.mock.calls.map((v) => v[0])).toMatchInlineSnapshot(`\n      [\n        \"dep1\",\n        \"dep2\",\n      ]\n    `)\n  })\n\n  it(`live binding (export default function f)`, async ({ runner }) => {\n    const mod = await runner.import('/fixtures/live-binding/test1/index.js')\n    expect(mod.default).toMatchInlineSnapshot(`\n      [\n        2,\n        3,\n      ]\n    `)\n  })\n\n  it(`live binding (export default f)`, async ({ runner }) => {\n    const mod = await runner.import('/fixtures/live-binding/test2/index.js')\n    expect(mod.default).toMatchInlineSnapshot(`\n      [\n        1,\n        1,\n      ]\n    `)\n  })\n\n  it(`live binding (export { f as default })`, async ({ runner }) => {\n    const mod = await runner.import('/fixtures/live-binding/test3/index.js')\n    expect(mod.default).toMatchInlineSnapshot(`\n      [\n        2,\n        3,\n      ]\n    `)\n  })\n\n  it(`live binding (export default class C)`, async ({ runner }) => {\n    const mod = await runner.import('/fixtures/live-binding/test4/index.js')\n    expect(mod.default).toMatchInlineSnapshot(`\n      [\n        2,\n        3,\n      ]\n    `)\n  })\n\n  it(`export default getter is hoisted`, async ({ runner }) => {\n    // Node error is `ReferenceError: Cannot access 'dep' before initialization`\n    // It should be an error but currently `undefined` fallback.\n    expect(\n      await runner.import('/fixtures/cyclic2/test9/index.js'),\n    ).toMatchInlineSnapshot(\n      `\n      {\n        \"default\": undefined,\n      }\n    `,\n    )\n  })\n\n  it('oxc runtime helpers are loadable', async ({ runner }) => {\n    const mod = await runner.import('/fixtures/oxc-runtime-helper.ts')\n    expect(mod.result).toMatchInlineSnapshot(`\n      \"<script>\n        console.log('hi')\n      </script>\"\n    `)\n  })\n\n  it(`handle Object variable`, async ({ runner }) => {\n    const mod = await runner.import('/fixtures/top-level-object.js')\n    expect(mod).toMatchInlineSnapshot(`\n      {\n        \"Object\": \"my-object\",\n      }\n    `)\n  })\n})\n\ndescribe('optimize-deps', async () => {\n  const it = await createModuleRunnerTester({\n    cacheDir: 'node_modules/.vite-test',\n    ssr: {\n      noExternal: true,\n      optimizeDeps: {\n        include: ['@vitejs/cjs-external'],\n      },\n    },\n  })\n\n  it('optimized dep as entry', async ({ runner }) => {\n    const mod = await runner.import('@vitejs/cjs-external')\n    expect(mod.default.hello()).toMatchInlineSnapshot(`\"world\"`)\n  })\n})\n\ndescribe('resolveId absolute path entry', async () => {\n  const it = await createModuleRunnerTester({\n    plugins: [\n      {\n        name: 'test-resolevId',\n        enforce: 'pre',\n        resolveId(source) {\n          if (\n            source ===\n            posix.join(this.environment.config.root, 'fixtures/basic.js')\n          ) {\n            return '\\0virtual:basic'\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:basic') {\n            return `export const name = \"virtual:basic\"`\n          }\n        },\n      },\n    ],\n  })\n\n  it('ssrLoadModule', async ({ server }) => {\n    const mod = await server.ssrLoadModule(\n      posix.join(server.config.root, 'fixtures/basic.js'),\n    )\n    expect(mod.name).toMatchInlineSnapshot(`\"virtual:basic\"`)\n  })\n\n  it('runner', async ({ server, runner }) => {\n    const mod = await runner.import(\n      posix.join(server.config.root, 'fixtures/basic.js'),\n    )\n    expect(mod.name).toMatchInlineSnapshot(`\"virtual:basic\"`)\n  })\n})\n\ndescribe('virtual module hmr', async () => {\n  let state = 'init'\n\n  const it = await createModuleRunnerTester({\n    plugins: [\n      {\n        name: 'test-resolevId',\n        enforce: 'pre',\n        resolveId(source) {\n          if (source === 'virtual:test') {\n            return '\\0' + source\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:test') {\n            return `export default ${JSON.stringify(state)}`\n          }\n        },\n      },\n    ],\n  })\n\n  it('full reload', async ({ server, runner }) => {\n    const mod = await runner.import('virtual:test')\n    expect(mod.default).toBe('init')\n    state = 'reloaded'\n    server.environments.ssr.moduleGraph.invalidateAll()\n    server.environments.ssr.hot.send({ type: 'full-reload' })\n    await vi.waitFor(() => {\n      const mod = runner.evaluatedModules.getModuleById('\\0virtual:test')\n      expect(mod?.exports.default).toBe('reloaded')\n    })\n  })\n\n  it(\"the external module's ID and file are resolved correctly\", async ({\n    server,\n    runner,\n  }) => {\n    await runner.import(\n      posix.join(server.config.root, 'fixtures/import-external.ts'),\n    )\n    const moduleNode = runner.evaluatedModules.getModuleByUrl('tinyglobby')!\n    const meta = moduleNode.meta as ExternalFetchResult\n    if (process.platform === 'win32') {\n      expect(meta.externalize).toMatch(/^file:\\/\\/\\/\\w:\\//) // file:///C:/\n      expect(moduleNode.id).toMatch(/^\\w:\\//) // C:/\n      expect(moduleNode.file).toMatch(/^\\w:\\//) // C:/\n    } else {\n      expect(meta.externalize).toMatch(/^file:\\/\\/\\//) // file:///\n      expect(moduleNode.id).toMatch(/^\\//) // /\n      expect(moduleNode.file).toMatch(/^\\//) // /\n    }\n  })\n})\n\ndescribe('invalid package', async () => {\n  const it = await createModuleRunnerTester({\n    environments: {\n      ssr: {\n        resolve: {\n          noExternal: true,\n        },\n      },\n    },\n  })\n\n  it('can catch resolve error on runtime', async ({ runner }) => {\n    const mod = await runner.import('./fixtures/invalid-package/test.js')\n    expect(await mod.test()).toMatchInlineSnapshot(`\n      {\n        \"data\": [Error: Failed to resolve entry for package \"test-dep-invalid-exports\". The package may have incorrect main/module/exports specified in its package.json.],\n        \"ok\": false,\n      }\n    `)\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/server-source-maps.spec.ts",
    "content": "import { runInThisContext } from 'node:vm'\nimport { resolve } from 'node:path'\nimport { describe, expect } from 'vitest'\nimport type { ViteDevServer } from '../../..'\nimport type { ModuleRunnerContext } from '../../../../module-runner'\nimport { ESModulesEvaluator } from '../../../../module-runner'\nimport {\n  createFixtureEditor,\n  createModuleRunnerTester,\n  resolvePath,\n} from './utils'\n\ndescribe('module runner initialization', async () => {\n  const it = await createModuleRunnerTester(\n    {},\n    {\n      sourcemapInterceptor: 'prepareStackTrace',\n    },\n  )\n\n  const getError = async (cb: () => void): Promise<Error> => {\n    try {\n      await cb()\n      expect.unreachable()\n    } catch (err) {\n      return err\n    }\n  }\n  const serializeStack = (server: ViteDevServer, err: Error) => {\n    return err.stack!.split('\\n')[1].replace(server.config.root, '<root>')\n  }\n  const serializeStackDeep = (server: ViteDevServer, err: Error) => {\n    return err\n      .stack!.split('\\n')\n      .map((s) => s.replace(server.config.root, '<root>'))\n  }\n\n  it('source maps are correctly applied to stack traces', async ({\n    runner,\n    server,\n  }) => {\n    expect.assertions(3)\n    const topLevelError = await getError(() =>\n      runner.import('/fixtures/has-error.js'),\n    )\n    expect(serializeStack(server, topLevelError)).toBe(\n      '    at <root>/fixtures/has-error.js:2:7',\n    )\n\n    const methodError = await getError(async () => {\n      const mod = await runner.import('/fixtures/throws-error-method.ts')\n      mod.throwError()\n    })\n    expect(serializeStack(server, methodError)).toBe(\n      '    at Module.throwError (<root>/fixtures/throws-error-method.ts:6:9)',\n    )\n\n    const fixtureEditor = createFixtureEditor()\n\n    // simulate HMR\n    fixtureEditor.editFile(\n      resolvePath(import.meta.url, './fixtures/throws-error-method.ts'),\n      (code) => '\\n\\n\\n\\n\\n' + code + '\\n',\n    )\n    runner.evaluatedModules.clear()\n    server.environments.ssr.moduleGraph.invalidateAll()\n\n    const methodErrorNew = await getError(async () => {\n      const mod = await runner.import('/fixtures/throws-error-method.ts')\n      mod.throwError()\n    })\n\n    expect(serializeStack(server, methodErrorNew)).toBe(\n      '    at Module.throwError (<root>/fixtures/throws-error-method.ts:11:9)',\n    )\n  })\n\n  it('stacktrace column on first line', async ({ runner, server }) => {\n    // column is off by \"use strict\"\n    const topLevelError = await getError(() =>\n      runner.import('/fixtures/has-error-first.js'),\n    )\n    expect(serializeStack(server, topLevelError)).toBe(\n      '    at <root>/fixtures/has-error-first.js:1:18',\n    )\n\n    const topLevelErrorTs = await getError(() =>\n      runner.import('/fixtures/has-error-first-comment.ts'),\n    )\n    expect(serializeStack(server, topLevelErrorTs)).toBe(\n      '    at <root>/fixtures/has-error-first-comment.ts:2:7',\n    )\n  })\n\n  it('deep stacktrace', async ({ runner, server }) => {\n    const methodError = await getError(async () => {\n      const mod = await runner.import('/fixtures/has-error-deep.ts')\n      mod.main()\n    })\n    expect(serializeStackDeep(server, methodError).slice(0, 3)).toEqual([\n      'Error: crash',\n      '    at crash (<root>/fixtures/has-error-deep.ts:2:9)',\n      '    at Module.main (<root>/fixtures/has-error-deep.ts:6:3)',\n    ])\n  })\n\n  it('should not crash when sourceMappingURL pattern appears in string literals', async ({\n    runner,\n    server,\n  }) => {\n    const mod = await runner.import('/fixtures/string-literal-sourcemap.ts')\n    expect(mod.getMessage()).toBe(\n      '//# sourceMappingURL=data:application/json;base64,invalidbase64',\n    )\n    const error = await getError(() => mod.throwError())\n    expect(error.message).toBe('Test error for stacktrace')\n    expect(serializeStackDeep(server, error).slice(0, 2)).toEqual([\n      'Error: Test error for stacktrace',\n      '    at Module.throwError (<root>/fixtures/string-literal-sourcemap.ts:11:9)',\n    ])\n  })\n\n  it('should correctly pickup the url from sources', async ({\n    server,\n    runner,\n  }) => {\n    const mod = await runner.import('/fixtures/pre-source-mapped-file.js')\n    const error = await getError(() => mod.default())\n    // The error stack shows \"transpiled-inline.ts\" because it is specified in the source map's \"sources\" field.\n    // The file itself does not exist on the file system, but we should still respect \"sources\".\n    // If source maps handling breaks, the stack trace will point to \"transpiled-inline.js\" instead, which would be a bug.\n    expect(serializeStackDeep(server, error).slice(0, 3))\n      .toMatchInlineSnapshot(`\n      [\n        \"Error: __TEST_STACK_TRANSPILED_INLINE__\",\n        \"    at innerTestStack (<root>/fixtures/transpiled-inline.ts:22:9)\",\n        \"    at Module.testStack (<root>/fixtures/transpiled-inline.ts:12:3)\",\n      ]\n    `)\n  })\n})\n\ndescribe('module runner with node:vm executor', async () => {\n  class Evaluator extends ESModulesEvaluator {\n    async runInlinedModule(_: ModuleRunnerContext, __: string) {\n      // Mimics VitestModuleEvaluator\n      const initModule = runInThisContext(\n        '() => { throw new Error(\"example\")}',\n        {\n          lineOffset: 0,\n          columnOffset: -100,\n          filename: resolve(import.meta.dirname, 'fixtures/a.ts'),\n        },\n      )\n\n      initModule()\n    }\n  }\n\n  const it = await createModuleRunnerTester(\n    {},\n    {\n      sourcemapInterceptor: 'prepareStackTrace',\n      evaluator: new Evaluator(),\n    },\n  )\n\n  it('should not crash when error stacktrace contains negative column', async ({\n    runner,\n  }) => {\n    const error = await runner.import('/fixtures/a.ts').catch((err) => err)\n\n    expect(() =>\n      error.stack.includes('.stack access triggers the bug'),\n    ).not.toThrow()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/server-worker-runner.invoke.spec.ts",
    "content": "import { BroadcastChannel, Worker } from 'node:worker_threads'\nimport { afterAll, beforeAll, describe, expect, it } from 'vitest'\nimport type { BirpcReturn } from 'birpc'\nimport { createBirpc } from 'birpc'\nimport { DevEnvironment } from '../../..'\nimport { type ViteDevServer, createServer } from '../../../server'\n\ndescribe('running module runner inside a worker and using the ModuleRunnerTransport#invoke API', () => {\n  let worker: Worker\n  let server: ViteDevServer\n  let rpc: BirpcReturn<\n    unknown,\n    { invoke: (data: any) => Promise<{ result: any } | { error: any }> }\n  >\n  let handleInvoke: (data: any) => Promise<{ result: any } | { error: any }>\n\n  beforeAll(async () => {\n    worker = new Worker(\n      new URL('./fixtures/worker.invoke.mjs', import.meta.url),\n      {\n        stdout: true,\n      },\n    )\n    await new Promise<void>((resolve, reject) => {\n      worker.on('message', () => resolve())\n      worker.on('error', reject)\n    })\n    server = await createServer({\n      root: import.meta.dirname,\n      logLevel: 'error',\n      server: {\n        middlewareMode: true,\n        watch: null,\n        hmr: {\n          port: 9610,\n        },\n      },\n      environments: {\n        worker: {\n          dev: {\n            createEnvironment: (name, config) => {\n              return new DevEnvironment(name, config, {\n                hot: false,\n              })\n            },\n          },\n        },\n      },\n    })\n    handleInvoke = (data: any) =>\n      server.environments.worker.hot.handleInvoke(data)\n    rpc = createBirpc(\n      {\n        invoke: (data: any) => handleInvoke(data),\n      },\n      {\n        post: (data) => worker.postMessage(data),\n        on: (data) => worker.on('message', data),\n      },\n    )\n  })\n\n  afterAll(async () => {\n    await Promise.allSettled([server.close(), worker.terminate()])\n    rpc.$close()\n  })\n\n  async function run(id: string) {\n    const channel = new BroadcastChannel('vite-worker:invoke')\n    return new Promise<any>((resolve, reject) => {\n      channel.onmessage = (event) => {\n        try {\n          resolve(event.data)\n        } catch (e) {\n          reject(e)\n        }\n      }\n      channel.postMessage({ id })\n    })\n  }\n\n  it('correctly runs ssr code', async () => {\n    const output = await run('./fixtures/default-string.ts')\n    expect(output).toStrictEqual({\n      result: 'hello world',\n    })\n  })\n\n  it('triggers an error', async () => {\n    handleInvoke = async () => ({ error: new Error('This is an Invoke Error') })\n    const output = await run('dummy')\n    expect(output).not.toHaveProperty('result')\n    expect(output.error).toContain('Error: This is an Invoke Error')\n  })\n\n  it('triggers an unknown error', async () => {\n    handleInvoke = async () => ({ error: 'a string instead of an error' })\n    const output = await run('dummy')\n    expect(output).not.toHaveProperty('result')\n    expect(output.error).toContain('Error: Unknown invoke error')\n  })\n\n  it('resolves builtin module without server round-trip', async () => {\n    handleInvoke = (data: any) =>\n      server.environments.worker.hot.handleInvoke(data)\n\n    const output = await run('./fixtures/builtin-import.ts')\n    expect(output).toHaveProperty('result')\n    expect(output.result).toBe('baz.txt')\n    expect(output.error).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/server-worker-runner.spec.ts",
    "content": "import { BroadcastChannel, Worker } from 'node:worker_threads'\nimport { describe, expect, it, onTestFinished } from 'vitest'\nimport type { HotChannel, HotChannelListener, HotPayload } from 'vite'\nimport { DevEnvironment } from '../../..'\nimport { createServer } from '../../../server'\n\nconst createWorkerTransport = (worker: Worker): HotChannel => {\n  const handlerToWorkerListener = new WeakMap<\n    HotChannelListener,\n    (value: HotPayload) => void\n  >()\n  const client = {\n    send(payload: HotPayload) {\n      worker.postMessage(payload)\n    },\n  }\n\n  return {\n    send: (data) => worker.postMessage(data),\n    on: (event: string, handler: HotChannelListener) => {\n      // client is already connected\n      if (event === 'vite:client:connect') return\n      if (event === 'vite:client:disconnect') {\n        const listener = () => {\n          handler(undefined, client)\n        }\n        handlerToWorkerListener.set(handler, listener)\n        worker.on('exit', listener)\n        return\n      }\n\n      const listener = (value: HotPayload) => {\n        if (value.type === 'custom' && value.event === event) {\n          handler(value.data, client)\n        }\n      }\n      handlerToWorkerListener.set(handler, listener)\n      worker.on('message', listener)\n    },\n    off: (event, handler: HotChannelListener) => {\n      if (event === 'vite:client:connect') return\n      if (event === 'vite:client:disconnect') {\n        const listener = handlerToWorkerListener.get(handler)\n        if (listener) {\n          worker.off('exit', listener)\n          handlerToWorkerListener.delete(handler)\n        }\n        return\n      }\n\n      const listener = handlerToWorkerListener.get(handler)\n      if (listener) {\n        worker.off('message', listener)\n        handlerToWorkerListener.delete(handler)\n      }\n    },\n  }\n}\n\ndescribe('running module runner inside a worker', () => {\n  it('correctly runs ssr code', async () => {\n    expect.assertions(1)\n    const worker = new Worker(\n      new URL('./fixtures/worker.mjs', import.meta.url),\n      {\n        stdout: true,\n      },\n    )\n    await new Promise<void>((resolve, reject) => {\n      worker.on('message', () => resolve())\n      worker.on('error', reject)\n    })\n    const server = await createServer({\n      root: import.meta.dirname,\n      logLevel: 'error',\n      server: {\n        middlewareMode: true,\n        watch: null,\n        hmr: {\n          port: 9609,\n        },\n      },\n      environments: {\n        worker: {\n          dev: {\n            createEnvironment: (name, config) => {\n              return new DevEnvironment(name, config, {\n                hot: false,\n                transport: createWorkerTransport(worker),\n              })\n            },\n          },\n        },\n      },\n    })\n    onTestFinished(async () => {\n      await Promise.allSettled([server.close(), worker.terminate()])\n    })\n    const channel = new BroadcastChannel('vite-worker')\n    return new Promise<void>((resolve, reject) => {\n      channel.onmessage = (event) => {\n        try {\n          expect(event.data).toEqual({\n            result: 'hello world',\n          })\n        } catch (e) {\n          reject(e)\n        } finally {\n          resolve()\n        }\n      }\n      channel.postMessage({ id: './fixtures/default-string.ts' })\n    })\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/__tests__/utils.ts",
    "content": "import fs from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { TestAPI } from 'vitest'\nimport { afterEach, beforeEach, onTestFinished, test } from 'vitest'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport type { ServerModuleRunnerOptions } from '../serverModuleRunner'\nimport type { ViteDevServer } from '../../../server'\nimport type { InlineConfig } from '../../../config'\nimport { createServer } from '../../../server'\nimport { createServerModuleRunner } from '../serverModuleRunner'\nimport type { DevEnvironment } from '../../../server/environment'\n\ninterface TestClient {\n  server: ViteDevServer\n  runner: ModuleRunner\n  environment: DevEnvironment\n}\n\nexport async function createModuleRunnerTester(\n  config: InlineConfig = {},\n  runnerConfig: ServerModuleRunnerOptions = {},\n): Promise<TestAPI<TestClient>> {\n  function waitForWatcher(server: ViteDevServer) {\n    return new Promise<void>((resolve) => {\n      if ((server.watcher as any)._readyEmitted) {\n        resolve()\n      } else {\n        server.watcher.once('ready', () => resolve())\n      }\n    })\n  }\n\n  beforeEach<TestClient>(async (t) => {\n    // @ts-ignore\n    globalThis.__HMR__ = {}\n\n    t.server = await createServer({\n      root: import.meta.dirname,\n      logLevel: 'error',\n      server: {\n        middlewareMode: true,\n        watch: null,\n        ws: false,\n      },\n      ssr: {\n        external: ['@vitejs/cjs-external', '@vitejs/esm-external'],\n      },\n      optimizeDeps: {\n        disabled: true,\n        noDiscovery: true,\n        include: [],\n      },\n      plugins: [\n        {\n          name: 'vite-plugin-virtual',\n          resolveId(id) {\n            if (id === 'virtual0:test') {\n              return `\\0virtual:test`\n            }\n            if (id === 'virtual:test') {\n              return 'virtual:test'\n            }\n            if (id === 'virtual:normal') {\n              return '\\0' + id\n            }\n          },\n          load(id) {\n            if (id === `\\0virtual:test`) {\n              return `export const msg = 'virtual0'`\n            }\n            if (id === `virtual:test`) {\n              return `export const msg = 'virtual'`\n            }\n            if (id === '\\0virtual:normal') {\n              return 'export default \"ok\"'\n            }\n          },\n        },\n        ...(config.plugins ?? []),\n      ],\n      ...config,\n    })\n    t.environment = t.server.environments.ssr\n    t.runner = createServerModuleRunner(t.environment, {\n      hmr: {\n        logger: false,\n      },\n      // don't override by default so Vitest source maps are correct\n      sourcemapInterceptor: false,\n      ...runnerConfig,\n    })\n    if (config.server?.watch) {\n      await waitForWatcher(t.server)\n    }\n  })\n\n  afterEach<TestClient>(async (t) => {\n    await t.runner.close()\n    await t.server.close()\n  })\n\n  return test as TestAPI<TestClient>\n}\n\ntype FixtureEditor = {\n  editFile: (file: string, callback: (content: string) => string) => void\n}\n\nexport function createFixtureEditor(): FixtureEditor {\n  const originalFiles = new Map<string, string>()\n  onTestFinished(() => {\n    originalFiles.forEach((content, file) => {\n      fs.writeFileSync(file, content, 'utf-8')\n    })\n    originalFiles.clear()\n  })\n\n  return {\n    editFile(file, callback) {\n      const content = fs.readFileSync(file, 'utf-8')\n      if (!originalFiles.has(file)) originalFiles.set(file, content)\n      fs.writeFileSync(file, callback(content), 'utf-8')\n    },\n  }\n}\n\nexport function resolvePath(baseUrl: string, path: string): string {\n  const filename = fileURLToPath(baseUrl)\n  return resolve(dirname(filename), path).replace(/\\\\/g, '/')\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/runtime/serverModuleRunner.ts",
    "content": "import { existsSync, readFileSync } from 'node:fs'\nimport { ModuleRunner, createNodeImportMeta } from 'vite/module-runner'\nimport type {\n  ModuleEvaluator,\n  ModuleRunnerHmr,\n  ModuleRunnerOptions,\n} from 'vite/module-runner'\nimport type { HotPayload } from '#types/hmrPayload'\nimport type { DevEnvironment } from '../../server/environment'\nimport type {\n  HotChannelClient,\n  NormalizedServerHotChannel,\n} from '../../server/hmr'\nimport type { ModuleRunnerTransport } from '../../../shared/moduleRunnerTransport'\n\n/**\n * @experimental\n */\nexport interface ServerModuleRunnerOptions extends Omit<\n  ModuleRunnerOptions,\n  'root' | 'fetchModule' | 'hmr' | 'transport'\n> {\n  /**\n   * Disable HMR or configure HMR logger.\n   */\n  hmr?:\n    | false\n    | {\n        logger?: ModuleRunnerHmr['logger']\n      }\n  /**\n   * Provide a custom module evaluator. This controls how the code is executed.\n   */\n  evaluator?: ModuleEvaluator\n}\n\nfunction createHMROptions(\n  environment: DevEnvironment,\n  options: ServerModuleRunnerOptions,\n) {\n  if (environment.config.server.hmr === false || options.hmr === false) {\n    return false\n  }\n  if (!('api' in environment.hot)) return false\n  return {\n    logger: options.hmr?.logger,\n  }\n}\n\nconst prepareStackTrace = {\n  retrieveFile(id: string) {\n    if (existsSync(id)) {\n      return readFileSync(id, 'utf-8')\n    }\n  },\n}\n\nfunction resolveSourceMapOptions(options: ServerModuleRunnerOptions) {\n  if (options.sourcemapInterceptor != null) {\n    if (options.sourcemapInterceptor === 'prepareStackTrace') {\n      return prepareStackTrace\n    }\n    if (typeof options.sourcemapInterceptor === 'object') {\n      return { ...prepareStackTrace, ...options.sourcemapInterceptor }\n    }\n    return options.sourcemapInterceptor\n  }\n  if (typeof process !== 'undefined' && 'setSourceMapsEnabled' in process) {\n    return 'node'\n  }\n  return prepareStackTrace\n}\n\nexport const createServerModuleRunnerTransport = (options: {\n  channel: NormalizedServerHotChannel\n}): ModuleRunnerTransport => {\n  const hmrClient: HotChannelClient = {\n    send: (payload: HotPayload) => {\n      if (payload.type !== 'custom') {\n        throw new Error(\n          'Cannot send non-custom events from the client to the server.',\n        )\n      }\n      options.channel.send(payload)\n    },\n  }\n\n  let handler: ((data: HotPayload) => void) | undefined\n\n  return {\n    connect({ onMessage }) {\n      options.channel.api!.outsideEmitter.on('send', onMessage)\n      options.channel.api!.innerEmitter.emit(\n        'vite:client:connect',\n        undefined,\n        hmrClient,\n      )\n      onMessage({ type: 'connected' })\n      handler = onMessage\n    },\n    disconnect() {\n      if (handler) {\n        options.channel.api!.outsideEmitter.off('send', handler)\n      }\n      options.channel.api!.innerEmitter.emit(\n        'vite:client:disconnect',\n        undefined,\n        hmrClient,\n      )\n    },\n    send(payload) {\n      if (payload.type !== 'custom') {\n        throw new Error(\n          'Cannot send non-custom events from the server to the client.',\n        )\n      }\n      options.channel.api!.innerEmitter.emit(\n        payload.event,\n        payload.data,\n        hmrClient,\n      )\n    },\n  }\n}\n\n/**\n * Create an instance of the Vite SSR runtime that support HMR.\n * @experimental\n */\nexport function createServerModuleRunner(\n  environment: DevEnvironment,\n  options: ServerModuleRunnerOptions = {},\n): ModuleRunner {\n  const hmr = createHMROptions(environment, options)\n  return new ModuleRunner(\n    {\n      ...options,\n      transport: createServerModuleRunnerTransport({\n        channel: environment.hot as NormalizedServerHotChannel,\n      }),\n      hmr,\n      createImportMeta: createNodeImportMeta,\n      sourcemapInterceptor: resolveSourceMapOptions(options),\n    },\n    options.evaluator,\n  )\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/ssrManifestPlugin.ts",
    "content": "import { basename, dirname, join, relative } from 'node:path'\nimport { parse as parseImports } from 'es-module-lexer'\nimport type {\n  ParseError as EsModuleLexerParseError,\n  ImportSpecifier,\n} from 'es-module-lexer'\nimport type { OutputChunk } from 'rolldown'\nimport type { Plugin } from '../plugin'\nimport { preloadMethod } from '../plugins/importAnalysisBuild'\nimport {\n  generateCodeFrame,\n  joinUrlSegments,\n  normalizePath,\n  numberToPos,\n  sortObjectKeys,\n} from '../utils'\nimport { perEnvironmentState } from '../environment'\n\nexport function ssrManifestPlugin(): Plugin {\n  // module id => preload assets mapping\n  const getSsrManifest = perEnvironmentState(() => {\n    return {} as Record<string, string[]>\n  })\n\n  return {\n    name: 'vite:ssr-manifest',\n\n    applyToEnvironment(environment) {\n      return !!environment.config.build.ssrManifest\n    },\n\n    generateBundle(_options, bundle) {\n      const config = this.environment.config\n      const ssrManifest = getSsrManifest(this)\n      const { base } = config\n      for (const file in bundle) {\n        const chunk = bundle[file]\n        if (chunk.type === 'chunk') {\n          for (const id in chunk.modules) {\n            const normalizedId = normalizePath(relative(config.root, id))\n            const mappedChunks =\n              ssrManifest[normalizedId] ?? (ssrManifest[normalizedId] = [])\n            if (!chunk.isEntry) {\n              mappedChunks.push(joinUrlSegments(base, chunk.fileName))\n              // <link> tags for entry chunks are already generated in static HTML,\n              // so we only need to record info for non-entry chunks.\n              chunk.viteMetadata!.importedCss.forEach((file) => {\n                mappedChunks.push(joinUrlSegments(base, file))\n              })\n            }\n            chunk.viteMetadata!.importedAssets.forEach((file) => {\n              mappedChunks.push(joinUrlSegments(base, file))\n            })\n          }\n          if (chunk.code.includes(preloadMethod)) {\n            // generate css deps map\n            const code = chunk.code\n            let imports: ImportSpecifier[] = []\n            try {\n              imports = parseImports(code)[0].filter((i) => i.n && i.d > -1)\n            } catch (_e: unknown) {\n              const e = _e as EsModuleLexerParseError\n              const loc = numberToPos(code, e.idx)\n              this.error({\n                name: e.name,\n                message: e.message,\n                stack: e.stack,\n                cause: e.cause,\n                pos: e.idx,\n                loc: { ...loc, file: chunk.fileName },\n                frame: generateCodeFrame(code, loc),\n              })\n            }\n            if (imports.length) {\n              for (let index = 0; index < imports.length; index++) {\n                const { s: start, e: end, n: name } = imports[index]\n                // check the chunk being imported\n                const url = code.slice(start, end)\n                const deps: string[] = []\n                const ownerFilename = chunk.fileName\n                // literal import - trace direct imports and add to deps\n                const analyzed: Set<string> = new Set<string>()\n                const addDeps = (filename: string) => {\n                  if (filename === ownerFilename) return\n                  if (analyzed.has(filename)) return\n                  analyzed.add(filename)\n                  const chunk = bundle[filename] as OutputChunk | undefined\n                  if (chunk) {\n                    chunk.viteMetadata!.importedCss.forEach((file) => {\n                      deps.push(joinUrlSegments(base, file))\n                    })\n                    chunk.imports.forEach(addDeps)\n                  }\n                }\n                const normalizedFile = normalizePath(\n                  join(dirname(chunk.fileName), url.slice(1, -1)),\n                )\n                addDeps(normalizedFile)\n                ssrManifest[basename(name!)] = deps\n              }\n            }\n          }\n        }\n      }\n\n      this.emitFile({\n        fileName:\n          typeof config.build.ssrManifest === 'string'\n            ? config.build.ssrManifest\n            : '.vite/ssr-manifest.json',\n        type: 'asset',\n        source: JSON.stringify(sortObjectKeys(ssrManifest), undefined, 2),\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/ssrModuleLoader.ts",
    "content": "import colors from 'picocolors'\nimport type { EvaluatedModuleNode } from 'vite/module-runner'\nimport {\n  ESModulesEvaluator,\n  ModuleRunner,\n  createNodeImportMeta,\n} from 'vite/module-runner'\nimport type { ViteDevServer } from '../server'\nimport { unwrapId } from '../../shared/utils'\nimport type { DevEnvironment } from '../server/environment'\nimport type { NormalizedServerHotChannel } from '../server/hmr'\nimport { buildErrorMessage } from '../server/middlewares/error'\nimport { isRunnableDevEnvironment } from '../../node'\nimport { ssrFixStacktrace } from './ssrStacktrace'\nimport { createServerModuleRunnerTransport } from './runtime/serverModuleRunner'\n\ntype SSRModule = Record<string, any>\n\nexport async function ssrLoadModule(\n  url: string,\n  server: ViteDevServer,\n  fixStacktrace?: boolean,\n): Promise<SSRModule> {\n  const environment = server.environments.ssr\n  if (!isRunnableDevEnvironment(environment)) {\n    throw new Error(\n      `ssrLoadModule requires the 'ssr' environment to be a runnable environment.`,\n    )\n  }\n  server._ssrCompatModuleRunner ||= new SSRCompatModuleRunner(environment)\n  url = unwrapId(url)\n\n  return instantiateModule(\n    url,\n    server._ssrCompatModuleRunner,\n    environment,\n    fixStacktrace,\n  )\n}\n\nasync function instantiateModule(\n  url: string,\n  runner: ModuleRunner,\n  environment: DevEnvironment,\n  fixStacktrace?: boolean,\n): Promise<SSRModule> {\n  const mod = await environment.moduleGraph.ensureEntryFromUrl(url)\n\n  if (mod.ssrError) {\n    throw mod.ssrError\n  }\n\n  try {\n    return await runner.import(url)\n  } catch (e: any) {\n    if (e.stack && fixStacktrace) {\n      ssrFixStacktrace(e, environment.moduleGraph)\n    }\n\n    environment.logger.error(\n      buildErrorMessage(e, [\n        colors.red(`Error when evaluating SSR module ${url}: ${e.message}`),\n      ]),\n      {\n        timestamp: true,\n        clear: environment.config.clearScreen,\n        error: e,\n      },\n    )\n\n    throw e\n  }\n}\n\nclass SSRCompatModuleRunner extends ModuleRunner {\n  constructor(private environment: DevEnvironment) {\n    super(\n      {\n        transport: createServerModuleRunnerTransport({\n          channel: environment.hot as NormalizedServerHotChannel,\n        }),\n        createImportMeta: createNodeImportMeta,\n        sourcemapInterceptor: false,\n        hmr: false,\n      },\n      new ESModulesEvaluator(),\n    )\n  }\n\n  protected override async directRequest(\n    url: string,\n    mod: EvaluatedModuleNode,\n    callstack: string[],\n  ): Promise<any> {\n    const id = mod.meta && 'id' in mod.meta && mod.meta.id\n    // serverId doesn't exist for external modules\n    if (!id) {\n      return super.directRequest(url, mod, callstack)\n    }\n\n    const viteMod = this.environment.moduleGraph.getModuleById(id)\n\n    if (!viteMod) {\n      return super.directRequest(id, mod, callstack)\n    }\n\n    try {\n      const exports = await super.directRequest(id, mod, callstack)\n      viteMod.ssrModule = exports\n      return exports\n    } catch (err) {\n      viteMod.ssrError = err\n      throw err\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/ssrStacktrace.ts",
    "content": "import path from 'node:path'\nimport { TraceMap, originalPositionFor } from '@jridgewell/trace-mapping'\nimport type { EnvironmentModuleGraph } from '..'\n\nlet offset: number\n\nfunction calculateOffsetOnce() {\n  if (offset !== undefined) {\n    return\n  }\n\n  try {\n    new Function('throw new Error(1)')()\n  } catch (e) {\n    // in Node 12, stack traces account for the function wrapper.\n    // in Node 13 and later, the function wrapper adds two lines,\n    // which must be subtracted to generate a valid mapping\n    const match = /:(\\d+):\\d+\\)$/.exec(e.stack.split('\\n')[1])\n    offset = match ? +match[1] - 1 : 0\n  }\n}\n\nexport function ssrRewriteStacktrace(\n  stack: string,\n  moduleGraph: EnvironmentModuleGraph,\n): { result: string; alreadyRewritten: boolean } {\n  calculateOffsetOnce()\n\n  let alreadyRewritten = false\n  const rewritten = stack\n    .split('\\n')\n    .map((line) => {\n      return line.replace(\n        /^ {4}at (?:(\\S.*?)\\s\\()?(.+?):(\\d+)(?::(\\d+))?\\)?/,\n        (input, varName, id, originalLine, originalColumn) => {\n          if (!id) return input\n\n          const mod = moduleGraph.getModuleById(id)\n          const rawSourceMap = mod?.transformResult?.map\n\n          if (!rawSourceMap) {\n            return input\n          }\n\n          const traced = new TraceMap(rawSourceMap as any)\n          const line = Number(originalLine) - offset\n          // stacktrace's column is 1-indexed, but sourcemap's one is 0-indexed\n          const column = Number(originalColumn) - 1\n          if (line <= 0 || column < 0) {\n            alreadyRewritten = true\n            return input\n          }\n\n          const pos = originalPositionFor(traced, { line, column })\n          if (!pos.source) {\n            return input\n          }\n\n          const trimmedVarName = varName?.trim()\n          const sourceFile = path.resolve(path.dirname(id), pos.source)\n          // stacktrace's column is 1-indexed, but sourcemap's one is 0-indexed\n          const source = `${sourceFile}:${pos.line}:${pos.column + 1}`\n          if (!trimmedVarName || trimmedVarName === 'eval') {\n            return `    at ${source}`\n          } else {\n            return `    at ${trimmedVarName} (${source})`\n          }\n        },\n      )\n    })\n    .join('\\n')\n  return { result: rewritten, alreadyRewritten }\n}\n\nexport function rebindErrorStacktrace(e: Error, stacktrace: string): void {\n  const { configurable, writable } = Object.getOwnPropertyDescriptor(\n    e,\n    'stack',\n  )!\n  if (configurable) {\n    Object.defineProperty(e, 'stack', {\n      value: stacktrace,\n      enumerable: true,\n      configurable: true,\n      writable: true,\n    })\n  } else if (writable) {\n    e.stack = stacktrace\n  }\n}\n\nconst rewroteStacktraces = new WeakSet()\n\nexport function ssrFixStacktrace(\n  e: Error,\n  moduleGraph: EnvironmentModuleGraph,\n): void {\n  if (!e.stack) return\n  // stacktrace shouldn't be rewritten more than once\n  if (rewroteStacktraces.has(e)) return\n\n  const { result: stacktrace, alreadyRewritten } = ssrRewriteStacktrace(\n    e.stack,\n    moduleGraph,\n  )\n  rebindErrorStacktrace(e, stacktrace)\n  if (alreadyRewritten) {\n    e.message +=\n      ' (The stacktrace appears to be already rewritten by something else, but was passed to vite.ssrFixStacktrace. This may cause incorrect stacktraces.)'\n  }\n\n  rewroteStacktraces.add(e)\n}\n"
  },
  {
    "path": "packages/vite/src/node/ssr/ssrTransform.ts",
    "content": "import path from 'node:path'\nimport MagicString from 'magic-string'\nimport type { SourceMap } from 'rolldown'\nimport type { ESTree } from 'rolldown/utils'\nimport { extract_names as extractNames } from 'periscopic'\nimport { walk as eswalk } from 'estree-walker'\nimport type { RawSourceMap } from '@jridgewell/remapping'\nimport { parseAstAsync as rolldownParseAstAsync } from 'rolldown/parseAst'\nimport type { TransformResult } from '../server/transformRequest'\nimport {\n  combineSourcemaps,\n  generateCodeFrame,\n  isDefined,\n  numberToPos,\n} from '../utils'\nimport { isJSONRequest } from '../plugins/json'\nimport type { DefineImportMetadata } from '../../shared/ssrTransform'\n\nexport interface ModuleRunnerTransformOptions {\n  json?: {\n    stringify?: boolean\n  }\n}\n\nexport const ssrModuleExportsKey = `__vite_ssr_exports__`\nexport const ssrImportKey = `__vite_ssr_import__`\nexport const ssrDynamicImportKey = `__vite_ssr_dynamic_import__`\nexport const ssrExportAllKey = `__vite_ssr_exportAll__`\nexport const ssrExportNameKey = `__vite_ssr_exportName__`\nexport const ssrImportMetaKey = `__vite_ssr_import_meta__`\n\nconst hashbangRE = /^#!.*\\n/\n\nexport async function ssrTransform(\n  code: string,\n  inMap: SourceMap | { mappings: '' } | null,\n  url: string,\n  originalCode: string,\n  options?: ModuleRunnerTransformOptions,\n): Promise<TransformResult | null> {\n  if (options?.json?.stringify && isJSONRequest(url)) {\n    return ssrTransformJSON(code, inMap)\n  }\n  return ssrTransformScript(code, inMap, url, originalCode)\n}\n\nasync function ssrTransformJSON(\n  code: string,\n  inMap: SourceMap | { mappings: '' } | null,\n): Promise<TransformResult> {\n  return {\n    code: code.replace('export default', `${ssrModuleExportsKey}.default =`),\n    map: inMap,\n    deps: [],\n    dynamicDeps: [],\n    ssr: true,\n  }\n}\n\nasync function ssrTransformScript(\n  code: string,\n  inMap: SourceMap | { mappings: '' } | null,\n  url: string,\n  originalCode: string,\n): Promise<TransformResult | null> {\n  const s = new MagicString(code)\n\n  let ast: ESTree.Program\n  try {\n    ast = await rolldownParseAstAsync(code)\n  } catch (err) {\n    // enhance known rollup errors\n    // https://github.com/rollup/rollup/blob/42e587e0e37bc0661aa39fe7ad6f1d7fd33f825c/src/utils/bufferToAst.ts#L17-L22\n    if (err.code === 'PARSE_ERROR') {\n      err.message = `Parse failure: ${err.message}\\n`\n      err.id = url\n      if (typeof err.pos === 'number') {\n        err.loc = numberToPos(code, err.pos)\n        err.loc.file = url\n        err.frame = generateCodeFrame(code, err.pos)\n        err.message += `At file: ${url}:${err.loc.line}:${err.loc.column}`\n      } else {\n        err.message += `At file: ${url}`\n      }\n    }\n    throw err\n  }\n\n  let uid = 0\n  const deps = new Set<string>()\n  const dynamicDeps = new Set<string>()\n  const idToImportMap = new Map<string, string>()\n  const declaredConst = new Set<string>()\n\n  // hoist at the start of the file, after the hashbang\n  const fileStartIndex = hashbangRE.exec(code)?.[0].length ?? 0\n  let hoistIndex = fileStartIndex\n\n  function defineImport(\n    index: number,\n    importNode: (\n      | ESTree.ImportDeclaration\n      | (ESTree.ExportNamedDeclaration & { source: ESTree.StringLiteral })\n      | ESTree.ExportAllDeclaration\n    ) & {\n      start: number\n      end: number\n    },\n    metadata?: DefineImportMetadata,\n  ) {\n    const source = importNode.source.value\n    deps.add(source)\n\n    // Reduce metadata to undefined if it's all default values\n    const metadataArg =\n      (metadata?.importedNames?.length ?? 0) > 0\n        ? `, ${JSON.stringify(metadata)}`\n        : ''\n\n    const importId = `__vite_ssr_import_${uid++}__`\n    const transformedImport = `const ${importId} = await ${ssrImportKey}(${JSON.stringify(\n      source,\n    )}${metadataArg});\\n`\n\n    s.update(importNode.start, importNode.end, transformedImport)\n\n    if (importNode.start === index) {\n      // no need to hoist, but update hoistIndex to keep the order\n      hoistIndex = importNode.end\n    } else {\n      // There will be an error if the module is called before it is imported,\n      // so the module import statement is hoisted to the top\n      s.move(importNode.start, importNode.end, index)\n    }\n\n    return importId\n  }\n\n  function defineExport(name: string, local = name) {\n    // wrap with try/catch to fallback to `undefined` for backward compat.\n    s.appendLeft(\n      fileStartIndex,\n      `${ssrExportNameKey}(${JSON.stringify(name)}, () => { try { return ${local} } catch {} });\\n`,\n    )\n  }\n\n  const imports: (\n    | ESTree.ImportDeclaration\n    | ESTree.ExportNamedDeclaration\n    | ESTree.ExportAllDeclaration\n  )[] = []\n  const exports: (\n    | ESTree.ExportNamedDeclaration\n    | ESTree.ExportDefaultDeclaration\n    | ESTree.ExportAllDeclaration\n  )[] = []\n  const reExportImportIdMap = new Map<\n    ESTree.ExportNamedDeclaration | ESTree.ExportAllDeclaration,\n    string\n  >()\n\n  for (const node of ast.body) {\n    if (node.type === 'ImportDeclaration') {\n      imports.push(node)\n    } else if (node.type === 'ExportDefaultDeclaration') {\n      exports.push(node)\n    } else if (\n      node.type === 'ExportNamedDeclaration' ||\n      node.type === 'ExportAllDeclaration'\n    ) {\n      imports.push(node)\n      exports.push(node)\n    }\n  }\n\n  // 1. check all import statements, hoist imports, and record id -> importName map\n  for (const node of imports) {\n    // hoist re-export's import at the same time as normal imports to preserve execution order\n    if (node.type === 'ExportNamedDeclaration') {\n      if (node.source) {\n        // export { foo, bar } from './foo'\n        const importId = defineImport(\n          hoistIndex,\n          node as ESTree.ExportNamedDeclaration & {\n            source: ESTree.StringLiteral\n          },\n          {\n            importedNames: node.specifiers.map((s) =>\n              getIdentifierNameOrLiteralValue(s.local),\n            ),\n          },\n        )\n        reExportImportIdMap.set(node, importId)\n      }\n      continue\n    }\n    if (node.type === 'ExportAllDeclaration') {\n      if (node.source) {\n        // export * from './foo'\n        const importId = defineImport(hoistIndex, node)\n        reExportImportIdMap.set(node, importId)\n      }\n      continue\n    }\n\n    // import foo from 'foo' --> foo -> __import_foo__.default\n    // import { baz } from 'foo' --> baz -> __import_foo__.baz\n    // import * as ok from 'foo' --> ok -> __import_foo__\n    const importId = defineImport(hoistIndex, node, {\n      importedNames: node.specifiers\n        .map((s) => {\n          if (s.type === 'ImportSpecifier')\n            return getIdentifierNameOrLiteralValue(s.imported)\n          else if (s.type === 'ImportDefaultSpecifier') return 'default'\n        })\n        .filter(isDefined),\n    })\n    for (const spec of node.specifiers) {\n      if (spec.type === 'ImportSpecifier') {\n        if (spec.imported.type === 'Identifier') {\n          idToImportMap.set(\n            spec.local.name,\n            `${importId}.${spec.imported.name}`,\n          )\n        } else {\n          idToImportMap.set(\n            spec.local.name,\n            `${importId}[${JSON.stringify(spec.imported.value)}]`,\n          )\n        }\n      } else if (spec.type === 'ImportDefaultSpecifier') {\n        idToImportMap.set(spec.local.name, `${importId}.default`)\n      } else {\n        // namespace specifier\n        idToImportMap.set(spec.local.name, importId)\n      }\n    }\n  }\n\n  // 2. check all export statements and define exports\n  for (const node of exports) {\n    // named exports\n    if (node.type === 'ExportNamedDeclaration') {\n      if (node.declaration) {\n        if (\n          node.declaration.type === 'FunctionDeclaration' ||\n          node.declaration.type === 'ClassDeclaration'\n        ) {\n          // export function foo() {}\n          defineExport(node.declaration.id!.name)\n        } else {\n          const declaration = node.declaration as ESTree.VariableDeclaration\n          // export const foo = 1, bar = 2\n          for (const decl of declaration.declarations) {\n            const names = extractNames(decl.id as any)\n            for (const name of names) {\n              defineExport(name)\n            }\n          }\n        }\n        s.remove(node.start, node.declaration.start)\n      } else {\n        if (node.source) {\n          // export { foo, bar } from './foo'\n          const importId = reExportImportIdMap.get(node)!\n          for (const spec of node.specifiers) {\n            const exportedAs = getIdentifierNameOrLiteralValue(spec.exported)\n\n            if (spec.local.type === 'Identifier') {\n              defineExport(exportedAs, `${importId}.${spec.local.name}`)\n            } else {\n              defineExport(\n                exportedAs,\n                `${importId}[${JSON.stringify(spec.local.value)}]`,\n              )\n            }\n          }\n        } else {\n          s.remove(node.start, node.end)\n          // export { foo, bar }\n          for (const spec of node.specifiers) {\n            // spec.local can be Literal only when it has \"from 'something'\"\n            const local = (spec.local as ESTree.IdentifierReference).name\n            const binding = idToImportMap.get(local)\n            const exportedAs = getIdentifierNameOrLiteralValue(spec.exported)\n\n            defineExport(exportedAs, binding || local)\n          }\n        }\n      }\n    }\n\n    // default export\n    if (node.type === 'ExportDefaultDeclaration') {\n      const expressionTypes = ['FunctionExpression', 'ClassExpression']\n      if (\n        'id' in node.declaration &&\n        node.declaration.id &&\n        !expressionTypes.includes(node.declaration.type)\n      ) {\n        // named hoistable/class exports\n        // export default function foo() {}\n        // export default class A {}\n        const { name } = node.declaration.id\n        s.remove(node.start, node.start + 15 /* 'export default '.length */)\n        defineExport('default', name)\n      } else {\n        // anonymous default exports\n        const name = `__vite_ssr_export_default__`\n        s.update(\n          node.start,\n          node.start + 14 /* 'export default'.length */,\n          `const ${name} =`,\n        )\n        defineExport('default', name)\n      }\n    }\n\n    // export * from './foo'\n    if (node.type === 'ExportAllDeclaration') {\n      const importId = reExportImportIdMap.get(node)!\n      if (node.exported) {\n        const exportedAs = getIdentifierNameOrLiteralValue(node.exported)\n        defineExport(exportedAs, `${importId}`)\n      } else {\n        s.appendLeft(node.end, `${ssrExportAllKey}(${importId});\\n`)\n      }\n    }\n  }\n\n  // 3. convert references to import bindings & import.meta references\n  walk(ast, {\n    onStatements(statements) {\n      // ensure \";\" between statements\n      for (let i = 0; i < statements.length - 1; i++) {\n        const stmt = statements[i]\n        if (\n          code[stmt.end - 1] !== ';' &&\n          stmt.type !== 'FunctionDeclaration' &&\n          stmt.type !== 'ClassDeclaration' &&\n          stmt.type !== 'BlockStatement' &&\n          stmt.type !== 'ImportDeclaration'\n        ) {\n          s.appendLeft(stmt.end, ';')\n        }\n      }\n    },\n    onIdentifier(id, parent, parentStack) {\n      const grandparent = parentStack[1]\n      const binding = idToImportMap.get(id.name)\n      if (!binding) {\n        return\n      }\n      if (isStaticProperty(parent) && parent.shorthand) {\n        // let binding used in a property shorthand\n        // { foo } -> { foo: __import_x__.foo }\n        // skip for destructuring patterns\n        if (\n          !isNodeInPattern(parent) ||\n          isInDestructuringAssignment(parent, parentStack)\n        ) {\n          s.appendLeft(id.end, `: ${binding}`)\n        }\n      } else if (\n        (parent.type === 'PropertyDefinition' &&\n          grandparent?.type === 'ClassBody') ||\n        (parent.type === 'ClassDeclaration' && id === parent.superClass)\n      ) {\n        if (!declaredConst.has(id.name)) {\n          declaredConst.add(id.name)\n          // locate the top-most node containing the class declaration\n          const topNode = parentStack[parentStack.length - 2]\n          s.prependRight(topNode.start, `const ${id.name} = ${binding};\\n`)\n        }\n      } else if (parent.type === 'CallExpression') {\n        s.update(id.start, id.end, binding)\n        // wrap with (0, ...) to avoid method binding `this`\n        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#method_binding\n        s.prependRight(id.start, `(0,`)\n        s.appendLeft(id.end, `)`)\n      } else if (\n        // don't transform class name identifier\n        !(parent.type === 'ClassExpression' && id === parent.id)\n      ) {\n        s.update(id.start, id.end, binding)\n      }\n    },\n    onImportMeta(node) {\n      s.update(node.start, node.end, ssrImportMetaKey)\n    },\n    onDynamicImport(node) {\n      s.update(node.start, node.start + 6, ssrDynamicImportKey)\n      if (node.type === 'ImportExpression' && node.source.type === 'Literal') {\n        dynamicDeps.add(node.source.value as string)\n      }\n    },\n  })\n\n  let map: TransformResult['map']\n  if (inMap?.mappings === '') {\n    map = inMap\n  } else {\n    map = s.generateMap({ hires: 'boundary' }) as SourceMap\n    map.sources = [path.basename(url)]\n    // needs to use originalCode instead of code\n    // because code might be already transformed even if map is null\n    map.sourcesContent = [originalCode]\n    if (\n      inMap &&\n      inMap.mappings &&\n      'sources' in inMap &&\n      inMap.sources.length > 0\n    ) {\n      map = combineSourcemaps(url, [\n        map as RawSourceMap,\n        inMap as RawSourceMap,\n      ]) as SourceMap\n    }\n  }\n\n  return {\n    code: s.toString(),\n    map,\n    ssr: true,\n    deps: [...deps],\n    dynamicDeps: [...dynamicDeps],\n  }\n}\n\nfunction getIdentifierNameOrLiteralValue(node: ESTree.ModuleExportName) {\n  return node.type === 'Identifier' ? node.name : node.value\n}\n\ninterface Visitors {\n  onIdentifier: (\n    node: ESTree.IdentifierReference,\n    parent: ESTree.Node,\n    parentStack: ESTree.Node[],\n  ) => void\n  onImportMeta: (node: ESTree.Node) => void\n  onDynamicImport: (node: ESTree.Node) => void\n  onStatements: (statements: ESTree.Node[]) => void\n}\n\ntype ESTreeProperty = ESTree.Node & { type: 'Property' }\nconst isNodeInPatternWeakSet = new WeakSet<ESTree.Node>()\nconst setIsNodeInPattern = (node: ESTreeProperty) =>\n  isNodeInPatternWeakSet.add(node)\nconst isNodeInPattern = (node: ESTree.Node): node is ESTreeProperty =>\n  isNodeInPatternWeakSet.has(node)\n\n/**\n * Same logic from \\@vue/compiler-core & \\@vue/compiler-sfc\n * Except this is using acorn AST\n */\nfunction walk(\n  root: ESTree.Node,\n  { onIdentifier, onImportMeta, onDynamicImport, onStatements }: Visitors,\n) {\n  const parentStack: ESTree.Node[] = []\n  const varKindStack: ESTree.VariableDeclaration['kind'][] = []\n  const scopeMap = new WeakMap<ESTree.Node, Set<string>>()\n  const identifiers: [id: any, stack: ESTree.Node[]][] = []\n\n  const setScope = (node: ESTree.Node, name: string) => {\n    let scopeIds = scopeMap.get(node)\n    if (scopeIds && scopeIds.has(name)) {\n      return\n    }\n    if (!scopeIds) {\n      scopeIds = new Set()\n      scopeMap.set(node, scopeIds)\n    }\n    scopeIds.add(name)\n  }\n\n  function isInScope(name: string, parents: ESTree.Node[]) {\n    return parents.some((node) => scopeMap.get(node)?.has(name))\n  }\n  function handlePattern(p: ESTree.ParamPattern, parentScope: ESTree.Node) {\n    if (p.type === 'Identifier') {\n      setScope(parentScope, p.name)\n    } else if (p.type === 'RestElement') {\n      handlePattern(p.argument, parentScope)\n    } else if (p.type === 'ObjectPattern') {\n      p.properties.forEach((property) => {\n        if (property.type === 'RestElement') {\n          setScope(\n            parentScope,\n            (property.argument as ESTree.IdentifierName).name,\n          )\n        } else {\n          handlePattern(property.value, parentScope)\n        }\n      })\n    } else if (p.type === 'ArrayPattern') {\n      p.elements.forEach((element) => {\n        if (element) {\n          handlePattern(element, parentScope)\n        }\n      })\n    } else if (p.type === 'AssignmentPattern') {\n      handlePattern(p.left, parentScope)\n    } else {\n      setScope(parentScope, (p as any).name)\n    }\n  }\n\n  ;(eswalk as any)(root, {\n    enter(node: ESTree.Node, parent: ESTree.Node | null) {\n      if (node.type === 'ImportDeclaration') {\n        return this.skip()\n      }\n\n      // for nodes that can contain multiple statements\n      if (\n        node.type === 'Program' ||\n        node.type === 'BlockStatement' ||\n        node.type === 'StaticBlock'\n      ) {\n        onStatements(node.body)\n      } else if (node.type === 'SwitchCase') {\n        onStatements(node.consequent)\n      }\n\n      // track parent stack, skip for \"else-if\"/\"else\" branches as acorn nests\n      // the ast within \"if\" nodes instead of flattening them\n      if (\n        parent &&\n        !(parent.type === 'IfStatement' && node === parent.alternate)\n      ) {\n        parentStack.unshift(parent)\n      }\n\n      // track variable declaration kind stack used by VariableDeclarator\n      if (node.type === 'VariableDeclaration') {\n        varKindStack.unshift(node.kind)\n      }\n\n      if (node.type === 'MetaProperty' && node.meta.name === 'import') {\n        onImportMeta(node)\n      } else if (node.type === 'ImportExpression') {\n        onDynamicImport(node)\n      }\n\n      if (node.type === 'Identifier') {\n        if (\n          !isInScope(node.name, parentStack) &&\n          isRefIdentifier(node, parent!, parentStack)\n        ) {\n          // record the identifier, for DFS -> BFS\n          identifiers.push([node, parentStack.slice(0)])\n        }\n      } else if (isFunction(node)) {\n        // If it is a function declaration, it could be shadowing an import\n        // Add its name to the scope so it won't get replaced\n        if (node.type === 'FunctionDeclaration') {\n          const parentScope = findParentScope(parentStack)\n          if (parentScope) {\n            setScope(parentScope, node.id!.name)\n          }\n        }\n        // If it is a function expression, its name (if exist) could also be\n        // shadowing an import. So add its own name to the scope\n        if (node.type === 'FunctionExpression' && node.id) {\n          setScope(node, node.id.name)\n        }\n        // walk function expressions and add its arguments to known identifiers\n        // so that we don't prefix them\n        node.params.forEach((p) => {\n          if (p.type === 'ObjectPattern' || p.type === 'ArrayPattern') {\n            handlePattern(p, node)\n            return\n          }\n          ;(eswalk as any)(p.type === 'AssignmentPattern' ? p.left : p, {\n            enter(child: ESTree.Node, parent: ESTree.Node | undefined) {\n              // skip params default value of destructure\n              if (\n                parent?.type === 'AssignmentPattern' &&\n                parent.right === child\n              ) {\n                return this.skip()\n              }\n              if (child.type !== 'Identifier') return\n              // do not record as scope variable if is a destructuring keyword\n              if (isStaticPropertyKey(child, parent)) return\n              // do not record if this is a default value\n              // assignment of a destructuring variable\n              if (\n                (parent?.type === 'TemplateLiteral' &&\n                  parent.expressions.includes(child as ESTree.Expression)) ||\n                (parent?.type === 'CallExpression' && parent.callee === child)\n              ) {\n                return\n              }\n              setScope(node, child.name)\n            },\n          })\n        })\n      } else if (node.type === 'ClassDeclaration') {\n        // A class declaration name could shadow an import, so add its name to the parent scope\n        const parentScope = findParentScope(parentStack)\n        if (parentScope) {\n          setScope(parentScope, node.id!.name)\n        }\n      } else if (node.type === 'ClassExpression' && node.id) {\n        // A class expression name could shadow an import, so add its name to the scope\n        setScope(node, node.id.name)\n      } else if (node.type === 'Property' && parent!.type === 'ObjectPattern') {\n        // mark property in destructuring pattern\n        setIsNodeInPattern(node)\n      } else if (node.type === 'VariableDeclarator') {\n        const parentFunction = findParentScope(\n          parentStack,\n          varKindStack[0] === 'var',\n        )\n        if (parentFunction) {\n          handlePattern(node.id, parentFunction)\n        }\n      } else if (node.type === 'CatchClause' && node.param) {\n        handlePattern(node.param, node)\n      }\n    },\n\n    leave(node: ESTree.Node, parent: ESTree.Node | null) {\n      // untrack parent stack from above\n      if (\n        parent &&\n        !(parent.type === 'IfStatement' && node === parent.alternate)\n      ) {\n        parentStack.shift()\n      }\n\n      if (node.type === 'VariableDeclaration') {\n        varKindStack.shift()\n      }\n    },\n  })\n\n  // emit the identifier events in BFS so the hoisted declarations\n  // can be captured correctly\n  identifiers.forEach(([node, stack]) => {\n    if (!isInScope(node.name, stack)) onIdentifier(node, stack[0], stack)\n  })\n}\n\nfunction isRefIdentifier(\n  id: ESTree.Node & { type: 'Identifier' },\n  parent: ESTree.Node,\n  parentStack: ESTree.Node[],\n) {\n  // declaration id\n  if (\n    parent.type === 'CatchClause' ||\n    ((parent.type === 'VariableDeclarator' ||\n      parent.type === 'ClassDeclaration') &&\n      parent.id === id)\n  ) {\n    return false\n  }\n\n  if (isFunction(parent)) {\n    // function declaration/expression id\n    if (parent.id === id) {\n      return false\n    }\n    // params list\n    if (\n      parent.params.includes(\n        id as Exclude<\n          typeof id,\n          ESTree.TSThisParameter | ESTree.TSIndexSignatureName\n        >,\n      )\n    ) {\n      return false\n    }\n  }\n\n  // class method name\n  if (parent.type === 'MethodDefinition' && !parent.computed) {\n    return false\n  }\n\n  // property key\n  if (isStaticPropertyKey(id, parent)) {\n    return false\n  }\n\n  // object destructuring pattern\n  if (isNodeInPattern(parent) && parent.value === id) {\n    return false\n  }\n\n  // non-assignment array destructuring pattern\n  if (\n    parent.type === 'ArrayPattern' &&\n    !isInDestructuringAssignment(parent, parentStack)\n  ) {\n    return false\n  }\n\n  // member expression property\n  if (\n    parent.type === 'MemberExpression' &&\n    parent.property === id &&\n    !parent.computed\n  ) {\n    return false\n  }\n\n  // export { id } from \"lib\"\n  // export * as id from \"lib\"\n  if (\n    parent.type === 'ExportSpecifier' ||\n    parent.type === 'ExportAllDeclaration'\n  ) {\n    return false\n  }\n\n  // is a special keyword but parsed as identifier\n  if (id.name === 'arguments') {\n    return false\n  }\n\n  return true\n}\n\nconst isStaticProperty = (\n  node: ESTree.Node,\n): node is ESTree.Node & { type: 'Property' } =>\n  node.type === 'Property' && !node.computed\n\nconst isStaticPropertyKey = (\n  node: ESTree.Node,\n  parent: ESTree.Node | undefined,\n) => parent && isStaticProperty(parent) && parent.key === node\n\nconst functionNodeTypeRE = /Function(?:Expression|Declaration)$|Method$/\ntype FunctionNodes = ESTree.Node & {\n  type:\n    | `Function${'Expression' | 'Declaration'}`\n    | `${string}Function${'Expression' | 'Declaration'}`\n    | `${string}Method`\n}\nfunction isFunction(node: ESTree.Node): node is FunctionNodes {\n  return functionNodeTypeRE.test(node.type)\n}\n\nconst blockNodeTypeRE = /^BlockStatement$|^For(?:In|Of)?Statement$/\nfunction isBlock(node: ESTree.Node) {\n  return blockNodeTypeRE.test(node.type)\n}\n\nfunction findParentScope(\n  parentStack: ESTree.Node[],\n  isVar = false,\n): ESTree.Node | undefined {\n  return parentStack.find(isVar ? isFunction : isBlock)\n}\n\nfunction isInDestructuringAssignment(\n  parent: ESTree.Node,\n  parentStack: ESTree.Node[],\n): boolean {\n  if (parent.type === 'Property' || parent.type === 'ArrayPattern') {\n    return parentStack.some((i) => i.type === 'AssignmentExpression')\n  }\n  return false\n}\n"
  },
  {
    "path": "packages/vite/src/node/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"include\": [\"./\", \"../module-runner\", \"../types\"],\n  \"exclude\": [\"**/fixtures\", \"**/__tests__\", \"**/__tests_dts__\"],\n  \"compilerOptions\": {\n    // https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping#node-20\n    \"lib\": [\"ES2023\", \"DOM\"], // DOM because we have client code that gets inlined via function.toString()\n    \"target\": \"ES2023\",\n    \"skipLibCheck\": true, // lib check is done on final types\n    \"stripInternal\": true,\n    \"paths\": {\n      \"vite/module-runner\": [\"../module-runner\"]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/node/typeUtils.ts",
    "content": "import type {\n  ObjectHook,\n  MinimalPluginContext as RolldownMinimalPluginContext,\n  Plugin as RolldownPlugin,\n} from 'rolldown'\n\nexport type NonNeverKeys<T> = {\n  [K in keyof T]: T[K] extends never ? never : K\n}[keyof T]\n\nexport type GetHookContextMap<Plugin> = {\n  [K in keyof Plugin]-?: Plugin[K] extends ObjectHook<infer T, unknown>\n    ? T extends (this: infer This, ...args: any[]) => any\n      ? This extends RolldownMinimalPluginContext\n        ? This\n        : never\n      : never\n    : never\n}\n\ntype RollupPluginHooksContext = GetHookContextMap<RolldownPlugin>\nexport type RollupPluginHooks = NonNeverKeys<RollupPluginHooksContext>\n\nexport type RequiredExceptFor<T, K extends keyof T> = Pick<T, K> &\n  Required<Omit<T, K>>\n"
  },
  {
    "path": "packages/vite/src/node/utils.ts",
    "content": "import fs from 'node:fs'\nimport os from 'node:os'\nimport net from 'node:net'\nimport path from 'node:path'\nimport { exec } from 'node:child_process'\nimport crypto from 'node:crypto'\nimport { fileURLToPath } from 'node:url'\nimport type { ServerOptions as HttpsServerOptions } from 'node:https'\nimport { builtinModules } from 'node:module'\nimport { promises as dns } from 'node:dns'\nimport { performance } from 'node:perf_hooks'\nimport type { AddressInfo, Server } from 'node:net'\nimport fsp from 'node:fs/promises'\nimport remapping from '@jridgewell/remapping'\nimport type { DecodedSourceMap, RawSourceMap } from '@jridgewell/remapping'\nimport colors from 'picocolors'\nimport type { Debugger } from 'obug'\nimport debug from 'obug'\nimport type MagicString from 'magic-string'\nimport type { Equal } from '@type-challenges/utils'\n\nimport type { TransformResult } from 'rolldown'\nimport { createFilter as _createFilter } from '@rollup/pluginutils'\nimport type { Alias, AliasOptions } from '#dep-types/alias'\nimport type { FSWatcher } from '#dep-types/chokidar'\nimport {\n  cleanUrl,\n  isWindows,\n  slash,\n  splitFileAndPostfix,\n  withTrailingSlash,\n} from '../shared/utils'\nimport { VALID_ID_PREFIX } from '../shared/constants'\nimport { createIsBuiltin } from '../shared/builtin'\nimport {\n  CLIENT_ENTRY,\n  CLIENT_PUBLIC_PATH,\n  CSS_LANGS_RE,\n  ENV_PUBLIC_PATH,\n  FS_PREFIX,\n  OPTIMIZABLE_ENTRY_RE,\n  loopbackHosts,\n  wildcardHosts,\n} from './constants'\nimport type { DepOptimizationOptions } from './optimizer'\nimport type { ResolvedConfig } from './config'\nimport type { ResolvedServerUrls, ViteDevServer } from './server'\nimport type { PreviewServer } from './preview'\nimport { type PackageCache, findNearestPackageData } from './packages'\nimport type { BuildEnvironmentOptions } from './build'\nimport type { CommonServerOptions } from '.'\n\n/**\n * Inlined to keep `@rollup/pluginutils` in devDependencies\n */\nexport type FilterPattern =\n  | ReadonlyArray<string | RegExp>\n  | string\n  | RegExp\n  | null\nexport const createFilter = _createFilter as (\n  include?: FilterPattern,\n  exclude?: FilterPattern,\n  options?: { resolve?: string | false | null },\n) => (id: string | unknown) => boolean\n\nexport { withFilter } from 'rolldown/filter'\n\nconst replaceSlashOrColonRE = /[/:]/g\nconst replaceDotRE = /\\./g\nconst replaceNestedIdRE = /\\s*>\\s*/g\nconst replaceHashRE = /#/g\nconst replacePlusRE = /\\+/g\nexport const flattenId = (id: string): string => {\n  const flatId = limitFlattenIdLength(\n    id\n      .replace(replaceSlashOrColonRE, '_')\n      .replace(replaceDotRE, '__')\n      .replace(replaceNestedIdRE, '___')\n      .replace(replaceHashRE, '____')\n      .replace(replacePlusRE, '_____'),\n  )\n  return flatId\n}\n\nconst FLATTEN_ID_HASH_LENGTH = 8\nconst FLATTEN_ID_MAX_FILE_LENGTH = 170\n\nconst limitFlattenIdLength = (\n  id: string,\n  limit: number = FLATTEN_ID_MAX_FILE_LENGTH,\n): string => {\n  if (id.length <= limit) {\n    return id\n  }\n  return id.slice(0, limit - (FLATTEN_ID_HASH_LENGTH + 1)) + '_' + getHash(id)\n}\n\nexport const normalizeId = (id: string): string =>\n  id.replace(replaceNestedIdRE, ' > ')\n\n// Supported by Node, Deno, Bun\nconst NODE_BUILTIN_NAMESPACE = 'node:'\n// Supported by Bun\nconst BUN_BUILTIN_NAMESPACE = 'bun:'\n// Some runtimes like Bun injects namespaced modules here, which is not a node builtin\nconst nodeBuiltins = builtinModules.filter((id) => !id.includes(':'))\n\nconst isBuiltinCache = new WeakMap<\n  (string | RegExp)[],\n  (id: string, importer?: string) => boolean\n>()\n\nexport function isBuiltin(builtins: (string | RegExp)[], id: string): boolean {\n  let isBuiltin = isBuiltinCache.get(builtins)\n  if (!isBuiltin) {\n    isBuiltin = createIsBuiltin(builtins)\n    isBuiltinCache.set(builtins, isBuiltin)\n  }\n  return isBuiltin(id)\n}\n\nexport const nodeLikeBuiltins: (string | RegExp)[] = [\n  ...nodeBuiltins,\n  new RegExp(`^${NODE_BUILTIN_NAMESPACE}`),\n  new RegExp(`^${BUN_BUILTIN_NAMESPACE}`),\n]\n\nexport function isNodeLikeBuiltin(id: string): boolean {\n  return isBuiltin(nodeLikeBuiltins, id)\n}\n\nexport function isNodeBuiltin(id: string): boolean {\n  if (id.startsWith(NODE_BUILTIN_NAMESPACE)) return true\n  return nodeBuiltins.includes(id)\n}\n\nexport function isInNodeModules(id: string): boolean {\n  return id.includes('node_modules')\n}\n\nexport function moduleListContains(\n  moduleList: string[] | undefined,\n  id: string,\n): boolean | undefined {\n  return moduleList?.some(\n    (m) => m === id || id.startsWith(withTrailingSlash(m)),\n  )\n}\n\nexport function isOptimizable(\n  id: string,\n  optimizeDeps: DepOptimizationOptions,\n): boolean {\n  const { extensions } = optimizeDeps\n  return (\n    OPTIMIZABLE_ENTRY_RE.test(id) ||\n    (extensions?.some((ext) => id.endsWith(ext)) ?? false)\n  )\n}\n\nexport const bareImportRE: RegExp = /^(?![a-zA-Z]:)[\\w@](?!.*:\\/\\/)/\nexport const deepImportRE: RegExp = /^([^@][^/]*)\\/|^(@[^/]+\\/[^/]+)\\//\n\nexport const _dirname: string = path.dirname(\n  fileURLToPath(/** #__KEEP__ */ import.meta.url),\n)\n\n// https://github.com/rolldown/rolldown/blob/62fba31428af244f871f0e119ed43936ee5d01fd/packages/rolldown/src/log/logger.ts#L64\nexport const rollupVersion = '4.23.0'\nexport { VERSION as rolldownVersion } from 'rolldown'\n\n// set in bin/vite.js\nconst filter = process.env.VITE_DEBUG_FILTER\n\nconst DEBUG = process.env.DEBUG\n\ninterface DebuggerOptions {\n  onlyWhenFocused?: boolean | string\n  depth?: number\n}\n\nexport type ViteDebugScope = `vite:${string}`\n\nexport function createDebugger(\n  namespace: ViteDebugScope,\n  options: DebuggerOptions = {},\n): Debugger['log'] | undefined {\n  const log = debug(namespace)\n  const { onlyWhenFocused, depth } = options\n\n  if (depth && log.inspectOpts && log.inspectOpts.depth == null) {\n    log.inspectOpts.depth = options.depth\n  }\n\n  let enabled = log.enabled\n  if (enabled && onlyWhenFocused) {\n    const ns = typeof onlyWhenFocused === 'string' ? onlyWhenFocused : namespace\n    enabled = !!DEBUG?.includes(ns)\n  }\n\n  if (enabled) {\n    return (...args: [string, ...any[]]) => {\n      if (!filter || args.some((a) => a?.includes?.(filter))) {\n        log(...args)\n      }\n    }\n  }\n}\n\nfunction testCaseInsensitiveFS() {\n  if (!CLIENT_ENTRY.endsWith('client.mjs')) {\n    throw new Error(\n      `cannot test case insensitive FS, CLIENT_ENTRY const doesn't contain client.mjs`,\n    )\n  }\n  if (!fs.existsSync(CLIENT_ENTRY)) {\n    throw new Error(\n      'cannot test case insensitive FS, CLIENT_ENTRY does not point to an existing file: ' +\n        CLIENT_ENTRY,\n    )\n  }\n  return fs.existsSync(CLIENT_ENTRY.replace('client.mjs', 'cLiEnT.mjs'))\n}\n\nexport const isCaseInsensitiveFS: boolean = testCaseInsensitiveFS()\n\nconst VOLUME_RE = /^[A-Z]:/i\n\nexport function normalizePath(id: string): string {\n  return path.posix.normalize(isWindows ? slash(id) : id)\n}\n\nexport function fsPathFromId(id: string): string {\n  const fsPath = normalizePath(\n    id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id,\n  )\n  return fsPath[0] === '/' || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`\n}\n\nexport function fsPathFromUrl(url: string): string {\n  return fsPathFromId(cleanUrl(url))\n}\n\n/**\n * Check if dir is a parent of file\n *\n * Warning: parameters are not validated, only works with normalized absolute paths\n *\n * @param dir - normalized absolute path\n * @param file - normalized absolute path\n * @returns true if dir is a parent of file\n */\nexport function isParentDirectory(dir: string, file: string): boolean {\n  dir = withTrailingSlash(dir)\n  return (\n    file.startsWith(dir) ||\n    (isCaseInsensitiveFS && file.toLowerCase().startsWith(dir.toLowerCase()))\n  )\n}\n\n/**\n * Check if 2 file name are identical\n *\n * Warning: parameters are not validated, only works with normalized absolute paths\n *\n * @param file1 - normalized absolute path\n * @param file2 - normalized absolute path\n * @returns true if both files url are identical\n */\nexport function isSameFilePath(file1: string, file2: string): boolean {\n  return (\n    file1 === file2 ||\n    (isCaseInsensitiveFS && file1.toLowerCase() === file2.toLowerCase())\n  )\n}\n\nexport const externalRE: RegExp = /^([a-z]+:)?\\/\\//\nexport const isExternalUrl = (url: string): boolean => externalRE.test(url)\n\nexport const dataUrlRE: RegExp = /^\\s*data:/i\nexport const isDataUrl = (url: string): boolean => dataUrlRE.test(url)\n\nexport const virtualModuleRE: RegExp = /^virtual-module:.*/\nexport const virtualModulePrefix = 'virtual-module:'\n\n// NOTE: We should start relying on the \"Sec-Fetch-Dest\" header instead of this\n// hardcoded list. We can eventually remove this function when the minimum version\n// of browsers we support in dev all support this header.\nconst knownJsSrcRE =\n  /\\.(?:[jt]sx?|m[jt]s|vue|marko|svelte|astro|imba|mdx)(?:$|\\?)/\nexport const isJSRequest = (url: string): boolean => {\n  url = cleanUrl(url)\n  if (knownJsSrcRE.test(url)) {\n    return true\n  }\n  if (!path.extname(url) && url[url.length - 1] !== '/') {\n    return true\n  }\n  return false\n}\n\nexport const isCSSRequest = (request: string): boolean =>\n  CSS_LANGS_RE.test(request)\n\nconst importQueryRE = /(\\?|&)import=?(?:&|$)/\nconst directRequestRE = /(\\?|&)direct=?(?:&|$)/\nconst internalPrefixes = [\n  FS_PREFIX,\n  VALID_ID_PREFIX,\n  CLIENT_PUBLIC_PATH,\n  ENV_PUBLIC_PATH,\n]\nconst InternalPrefixRE = new RegExp(`^(?:${internalPrefixes.join('|')})`)\nconst trailingSeparatorRE = /[?&]$/\nexport const isImportRequest = (url: string): boolean => importQueryRE.test(url)\nexport const isInternalRequest = (url: string): boolean =>\n  InternalPrefixRE.test(url)\n\nexport function removeImportQuery(url: string): string {\n  return url.replace(importQueryRE, '$1').replace(trailingSeparatorRE, '')\n}\nexport function removeDirectQuery(url: string): string {\n  return url.replace(directRequestRE, '$1').replace(trailingSeparatorRE, '')\n}\n\nexport const urlRE: RegExp = /(\\?|&)url(?:&|$)/\nexport const rawRE: RegExp = /(\\?|&)raw(?:&|$)/\nexport function removeUrlQuery(url: string): string {\n  return url.replace(urlRE, '$1').replace(trailingSeparatorRE, '')\n}\nexport function removeRawQuery(url: string): string {\n  return url.replace(rawRE, '$1').replace(trailingSeparatorRE, '')\n}\n\nexport function injectQuery(url: string, queryToInject: string): string {\n  const { file, postfix } = splitFileAndPostfix(url)\n  const normalizedFile = isWindows ? slash(file) : file\n  return `${normalizedFile}?${queryToInject}${postfix[0] === '?' ? `&${postfix.slice(1)}` : /* hash only */ postfix}`\n}\n\nconst timestampRE = /\\bt=\\d{13}&?\\b/\nexport function removeTimestampQuery(url: string): string {\n  return url.replace(timestampRE, '').replace(trailingSeparatorRE, '')\n}\n\nexport async function asyncReplace(\n  input: string,\n  re: RegExp,\n  replacer: (match: RegExpExecArray) => string | Promise<string>,\n): Promise<string> {\n  let match: RegExpExecArray | null\n  let remaining = input\n  let rewritten = ''\n  while ((match = re.exec(remaining))) {\n    rewritten += remaining.slice(0, match.index)\n    rewritten += await replacer(match)\n    remaining = remaining.slice(match.index + match[0].length)\n  }\n  rewritten += remaining\n  return rewritten\n}\n\nexport function timeFrom(start: number, subtract = 0): string {\n  const time: number | string = performance.now() - start - subtract\n  const timeString = (time.toFixed(2) + `ms`).padEnd(5, ' ')\n  if (time < 10) {\n    return colors.green(timeString)\n  } else if (time < 50) {\n    return colors.yellow(timeString)\n  } else {\n    return colors.red(timeString)\n  }\n}\n\n/**\n * pretty url for logging.\n */\nexport function prettifyUrl(url: string, root: string): string {\n  url = removeTimestampQuery(url)\n  const isAbsoluteFile = url.startsWith(root)\n  if (isAbsoluteFile || url.startsWith(FS_PREFIX)) {\n    const file = path.posix.relative(\n      root,\n      isAbsoluteFile ? url : fsPathFromId(url),\n    )\n    return colors.dim(file)\n  } else {\n    return colors.dim(url)\n  }\n}\n\nexport function isObject(value: unknown): value is Record<string, any> {\n  return Object.prototype.toString.call(value) === '[object Object]'\n}\n\nexport function isDefined<T>(value: T | undefined | null): value is T {\n  return value != null\n}\n\nexport function tryStatSync(file: string): fs.Stats | undefined {\n  try {\n    // The \"throwIfNoEntry\" is a performance optimization for cases where the file does not exist\n    return fs.statSync(file, { throwIfNoEntry: false })\n  } catch {\n    // Ignore errors\n  }\n}\n\nexport function lookupFile(\n  dir: string,\n  fileNames: string[],\n): string | undefined {\n  while (dir) {\n    for (const fileName of fileNames) {\n      const fullPath = path.join(dir, fileName)\n      if (tryStatSync(fullPath)?.isFile()) return fullPath\n    }\n    const parentDir = path.dirname(dir)\n    if (parentDir === dir) return\n\n    dir = parentDir\n  }\n}\n\nexport function isFilePathESM(\n  filePath: string,\n  packageCache?: PackageCache,\n): boolean {\n  if (/\\.m[jt]s$/.test(filePath)) {\n    return true\n  } else if (/\\.c[jt]s$/.test(filePath)) {\n    return false\n  } else {\n    // check package.json for type: \"module\"\n    try {\n      const pkg = findNearestPackageData(path.dirname(filePath), packageCache)\n      return pkg?.data.type === 'module'\n    } catch {\n      return false\n    }\n  }\n}\n\nexport const splitRE: RegExp = /\\r?\\n/g\n\nconst range: number = 2\n\nexport function pad(source: string, n = 2): string {\n  const lines = source.split(splitRE)\n  return lines.map((l) => ` `.repeat(n) + l).join(`\\n`)\n}\n\ntype Pos = {\n  /** 1-based */\n  line: number\n  /** 0-based */\n  column: number\n}\n\nexport function posToNumber(source: string, pos: number | Pos): number {\n  if (typeof pos === 'number') return pos\n  const lines = source.split(splitRE)\n  const { line, column } = pos\n  let start = 0\n  for (let i = 0; i < line - 1 && i < lines.length; i++) {\n    start += lines[i].length + 1\n  }\n  return start + column\n}\n\nexport function numberToPos(source: string, offset: number | Pos): Pos {\n  if (typeof offset !== 'number') return offset\n  if (offset > source.length) {\n    throw new Error(\n      `offset is longer than source length! offset ${offset} > length ${source.length}`,\n    )\n  }\n\n  const lines = source.slice(0, offset).split(splitRE)\n  return {\n    line: lines.length,\n    column: lines[lines.length - 1].length,\n  }\n}\n\nconst MAX_DISPLAY_LEN = 120\nconst ELLIPSIS = '...'\n\nexport function generateCodeFrame(\n  source: string,\n  start: number | Pos = 0,\n  end?: number | Pos,\n): string {\n  start = Math.max(posToNumber(source, start), 0)\n  end = Math.min(\n    end !== undefined ? posToNumber(source, end) : start,\n    source.length,\n  )\n  const lastPosLine =\n    end !== undefined\n      ? numberToPos(source, end).line\n      : numberToPos(source, start).line + range\n  const lineNumberWidth = Math.max(3, String(lastPosLine).length + 1)\n  const lines = source.split(splitRE)\n  let count = 0\n  const res: string[] = []\n  for (let i = 0; i < lines.length; i++) {\n    count += lines[i].length\n    if (count >= start) {\n      for (let j = i - range; j <= i + range || end > count; j++) {\n        if (j < 0 || j >= lines.length) continue\n        const line = j + 1\n        const lineLength = lines[j].length\n        const pad = Math.max(start - (count - lineLength), 0)\n        const underlineLength = Math.max(\n          1,\n          end > count ? lineLength - pad : end - start,\n        )\n\n        let displayLine = lines[j]\n        let underlinePad = pad\n        if (lineLength > MAX_DISPLAY_LEN) {\n          let startIdx = 0\n          if (j === i) {\n            if (underlineLength > MAX_DISPLAY_LEN) {\n              startIdx = pad\n            } else {\n              const center = pad + Math.floor(underlineLength / 2)\n              startIdx = Math.max(0, center - Math.floor(MAX_DISPLAY_LEN / 2))\n            }\n            underlinePad =\n              Math.max(0, pad - startIdx) + (startIdx > 0 ? ELLIPSIS.length : 0)\n          }\n          const prefix = startIdx > 0 ? ELLIPSIS : ''\n          const suffix = lineLength - startIdx > MAX_DISPLAY_LEN ? ELLIPSIS : ''\n          const sliceLen = MAX_DISPLAY_LEN - prefix.length - suffix.length\n          displayLine =\n            prefix + displayLine.slice(startIdx, startIdx + sliceLen) + suffix\n        }\n        res.push(\n          `${line}${' '.repeat(lineNumberWidth - String(line).length)}|  ${displayLine}`,\n        )\n        if (j === i) {\n          // push underline\n          const underline = '^'.repeat(\n            Math.min(underlineLength, MAX_DISPLAY_LEN),\n          )\n          res.push(\n            `${' '.repeat(lineNumberWidth)}|  ` +\n              ' '.repeat(underlinePad) +\n              underline,\n          )\n        } else if (j > i) {\n          if (end > count) {\n            const length = Math.max(Math.min(end - count, lineLength), 1)\n            const underline = '^'.repeat(Math.min(length, MAX_DISPLAY_LEN))\n            res.push(`${' '.repeat(lineNumberWidth)}|  ` + underline)\n          }\n          count += lineLength + 1\n        }\n      }\n      break\n    }\n    count++\n  }\n  return res.join('\\n')\n}\n\nexport function isFileReadable(filename: string): boolean {\n  if (!tryStatSync(filename)) {\n    return false\n  }\n\n  try {\n    // Check if current process has read permission to the file\n    fs.accessSync(filename, fs.constants.R_OK)\n\n    return true\n  } catch {\n    return false\n  }\n}\n\nconst splitFirstDirRE = /(.+?)[\\\\/](.+)/\n\n/**\n * Delete every file and subdirectory. **The given directory must exist.**\n * Pass an optional `skip` array to preserve files under the root directory.\n */\nexport function emptyDir(dir: string, skip?: string[]): void {\n  const skipInDir: string[] = []\n  let nested: Map<string, string[]> | null = null\n  if (skip?.length) {\n    for (const file of skip) {\n      if (path.dirname(file) !== '.') {\n        const matched = splitFirstDirRE.exec(file)\n        if (matched) {\n          nested ??= new Map()\n          const [, nestedDir, skipPath] = matched\n          let nestedSkip = nested.get(nestedDir)\n          if (!nestedSkip) {\n            nestedSkip = []\n            nested.set(nestedDir, nestedSkip)\n          }\n          if (!nestedSkip.includes(skipPath)) {\n            nestedSkip.push(skipPath)\n          }\n        }\n      } else {\n        skipInDir.push(file)\n      }\n    }\n  }\n  for (const file of fs.readdirSync(dir)) {\n    if (skipInDir.includes(file)) {\n      continue\n    }\n    if (nested?.has(file)) {\n      emptyDir(path.resolve(dir, file), nested.get(file))\n    } else {\n      fs.rmSync(path.resolve(dir, file), { recursive: true, force: true })\n    }\n  }\n}\n\n// NOTE: we cannot use `fs.cpSync` because of a bug in Node.js (https://github.com/nodejs/node/issues/58768, https://github.com/nodejs/node/issues/59168)\n//       also note that we should set `dereference: true` when we use `fs.cpSync`\nexport function copyDir(srcDir: string, destDir: string): void {\n  fs.mkdirSync(destDir, { recursive: true })\n  for (const file of fs.readdirSync(srcDir)) {\n    const srcFile = path.resolve(srcDir, file)\n    if (srcFile === destDir) {\n      continue\n    }\n    const destFile = path.resolve(destDir, file)\n    const stat = fs.statSync(srcFile)\n    if (stat.isDirectory()) {\n      copyDir(srcFile, destFile)\n    } else {\n      fs.copyFileSync(srcFile, destFile)\n    }\n  }\n}\n\nexport const ERR_SYMLINK_IN_RECURSIVE_READDIR =\n  'ERR_SYMLINK_IN_RECURSIVE_READDIR'\nexport async function recursiveReaddir(dir: string): Promise<string[]> {\n  if (!fs.existsSync(dir)) {\n    return []\n  }\n  let dirents: fs.Dirent[]\n  try {\n    dirents = await fsp.readdir(dir, { withFileTypes: true })\n  } catch (e) {\n    if (e.code === 'EACCES') {\n      // Ignore permission errors\n      return []\n    }\n    throw e\n  }\n  if (dirents.some((dirent) => dirent.isSymbolicLink())) {\n    const err: any = new Error(\n      'Symbolic links are not supported in recursiveReaddir',\n    )\n    err.code = ERR_SYMLINK_IN_RECURSIVE_READDIR\n    throw err\n  }\n  const files = await Promise.all(\n    dirents.map((dirent) => {\n      const res = path.resolve(dir, dirent.name)\n      return dirent.isDirectory() ? recursiveReaddir(res) : normalizePath(res)\n    }),\n  )\n  return files.flat(1)\n}\n\n// `fs.realpathSync.native` resolves differently in Windows network drive,\n// causing file read errors. skip for now.\n// https://github.com/nodejs/node/issues/37737\nexport let safeRealpathSync:\n  | typeof windowsSafeRealPathSync\n  | typeof fs.realpathSync.native = isWindows\n  ? windowsSafeRealPathSync\n  : fs.realpathSync.native\n\n// Based on https://github.com/larrybahr/windows-network-drive\n// MIT License, Copyright (c) 2017 Larry Bahr\nconst windowsNetworkMap = new Map()\nfunction windowsMappedRealpathSync(path: string) {\n  const realPath = fs.realpathSync.native(path)\n  if (realPath.startsWith('\\\\\\\\')) {\n    for (const [network, volume] of windowsNetworkMap) {\n      if (realPath.startsWith(network)) return realPath.replace(network, volume)\n    }\n  }\n  return realPath\n}\nconst parseNetUseRE = /^\\w* +(\\w:) +([^ ]+)\\s/\nlet firstSafeRealPathSyncRun = false\n\nfunction windowsSafeRealPathSync(path: string): string {\n  if (!firstSafeRealPathSyncRun) {\n    optimizeSafeRealPathSync()\n    firstSafeRealPathSyncRun = true\n  }\n  return fs.realpathSync(path)\n}\n\nfunction optimizeSafeRealPathSync() {\n  // Check the availability `fs.realpathSync.native`\n  // in Windows virtual and RAM disks that bypass the Volume Mount Manager, in programs such as imDisk\n  // get the error EISDIR: illegal operation on a directory\n  try {\n    fs.realpathSync.native(path.resolve('./'))\n  } catch (error) {\n    if (error.message.includes('EISDIR: illegal operation on a directory')) {\n      safeRealpathSync = fs.realpathSync\n      return\n    }\n  }\n  exec('net use', (error, stdout) => {\n    if (error) return\n    const lines = stdout.split('\\n')\n    // OK           Y:        \\\\NETWORKA\\Foo         Microsoft Windows Network\n    // OK           Z:        \\\\NETWORKA\\Bar         Microsoft Windows Network\n    for (const line of lines) {\n      const m = parseNetUseRE.exec(line)\n      if (m) windowsNetworkMap.set(m[2], m[1])\n    }\n    if (windowsNetworkMap.size === 0) {\n      safeRealpathSync = fs.realpathSync.native\n    } else {\n      safeRealpathSync = windowsMappedRealpathSync\n    }\n  })\n}\n\nexport function ensureWatchedFile(\n  watcher: FSWatcher,\n  file: string | null,\n  root: string,\n): void {\n  if (\n    file &&\n    // only need to watch if out of root\n    !file.startsWith(withTrailingSlash(root)) &&\n    // some rollup plugins use null bytes for private resolved Ids\n    !file.includes('\\0') &&\n    fs.existsSync(file)\n  ) {\n    // resolve file to normalized system path\n    watcher.add(path.resolve(file))\n  }\n}\n\ninterface ImageCandidate {\n  url: string\n  descriptor: string\n}\n\nfunction joinSrcset(ret: ImageCandidate[]) {\n  return ret\n    .map(({ url, descriptor }) => url + (descriptor ? ` ${descriptor}` : ''))\n    .join(', ')\n}\n\n/**\n This regex represents a loose rule of an “image candidate string” and \"image set options\".\n\n @see https://html.spec.whatwg.org/multipage/images.html#srcset-attribute\n @see https://drafts.csswg.org/css-images-4/#image-set-notation\n\n  The Regex has named capturing groups `url` and `descriptor`.\n  The `url` group can be:\n  * any CSS function\n  * CSS string (single or double-quoted)\n  * URL string (unquoted)\n  The `descriptor` is anything after the space and before the comma.\n */\nconst imageCandidateRegex =\n  /(?:^|\\s|(?<=,))(?<url>[\\w-]+\\([^)]*\\)|\"[^\"]*\"|'[^']*'|[^,]\\S*[^,])\\s*(?:\\s(?<descriptor>\\w[^,]+))?(?:,|$)/g\nconst escapedSpaceCharacters = /(?: |\\\\t|\\\\n|\\\\f|\\\\r)+/g\n\nexport function parseSrcset(string: string): ImageCandidate[] {\n  const matches = string\n    .trim()\n    .replace(escapedSpaceCharacters, ' ')\n    .replace(/\\r?\\n/, '')\n    .replace(/,\\s+/, ', ')\n    .replaceAll(/\\s+/g, ' ')\n    .matchAll(imageCandidateRegex)\n  return Array.from(matches, ({ groups }) => ({\n    url: groups?.url?.trim() ?? '',\n    descriptor: groups?.descriptor?.trim() ?? '',\n  })).filter(({ url }) => !!url)\n}\n\nexport function processSrcSet(\n  srcs: string,\n  replacer: (arg: ImageCandidate) => Promise<string>,\n): Promise<string> {\n  return Promise.all(\n    parseSrcset(srcs).map(async ({ url, descriptor }) => ({\n      url: await replacer({ url, descriptor }),\n      descriptor,\n    })),\n  ).then(joinSrcset)\n}\n\nexport function processSrcSetSync(\n  srcs: string,\n  replacer: (arg: ImageCandidate) => string,\n): string {\n  return joinSrcset(\n    parseSrcset(srcs).map(({ url, descriptor }) => ({\n      url: replacer({ url, descriptor }),\n      descriptor,\n    })),\n  )\n}\n\nconst windowsDriveRE = /^[A-Z]:/\nconst replaceWindowsDriveRE = /^([A-Z]):\\//\nconst linuxAbsolutePathRE = /^\\/[^/]/\nfunction escapeToLinuxLikePath(path: string) {\n  if (windowsDriveRE.test(path)) {\n    return path.replace(replaceWindowsDriveRE, '/windows/$1/')\n  }\n  if (linuxAbsolutePathRE.test(path)) {\n    return `/linux${path}`\n  }\n  return path\n}\n\nconst revertWindowsDriveRE = /^\\/windows\\/([A-Z])\\//\nfunction unescapeToLinuxLikePath(path: string) {\n  if (path.startsWith('/linux/')) {\n    return path.slice('/linux'.length)\n  }\n  if (path.startsWith('/windows/')) {\n    return path.replace(revertWindowsDriveRE, '$1:/')\n  }\n  return path\n}\n\n// based on https://github.com/sveltejs/svelte/blob/abf11bb02b2afbd3e4cac509a0f70e318c306364/src/compiler/utils/mapped_code.ts#L221\nconst nullSourceMap: RawSourceMap = {\n  names: [],\n  sources: [],\n  mappings: '',\n  version: 3,\n}\n/**\n * Combines multiple sourcemaps into a single sourcemap.\n * Note that the length of sourcemapList must be 2.\n */\nexport function combineSourcemaps(\n  filename: string,\n  sourcemapList: Array<DecodedSourceMap | RawSourceMap>,\n): RawSourceMap {\n  if (\n    sourcemapList.length === 0 ||\n    sourcemapList.every((m) => m.sources.length === 0)\n  ) {\n    return { ...nullSourceMap }\n  }\n\n  // hack for parse broken with normalized absolute paths on windows (C:/path/to/something).\n  // escape them to linux like paths\n  // also avoid mutation here to prevent breaking plugin's using cache to generate sourcemaps like vue (see #7442)\n  sourcemapList = sourcemapList.map((sourcemap) => {\n    const newSourcemaps = { ...sourcemap }\n    newSourcemaps.sources = sourcemap.sources.map((source) =>\n      source ? escapeToLinuxLikePath(source) : null,\n    )\n    if (sourcemap.sourceRoot) {\n      newSourcemaps.sourceRoot = escapeToLinuxLikePath(sourcemap.sourceRoot)\n    }\n    return newSourcemaps\n  })\n  const escapedFilename = escapeToLinuxLikePath(filename)\n\n  // We don't declare type here so we can convert/fake/map as RawSourceMap\n  let map //: SourceMap\n  let mapIndex = 1\n  const useArrayInterface =\n    sourcemapList.slice(0, -1).find((m) => m.sources.length !== 1) === undefined\n  if (useArrayInterface) {\n    map = remapping(sourcemapList, () => null)\n  } else {\n    map = remapping(sourcemapList[0], function loader(sourcefile) {\n      // this line assumes that the length of the sourcemapList is 2\n      if (sourcefile === escapedFilename && sourcemapList[mapIndex]) {\n        return sourcemapList[mapIndex++]\n      } else {\n        return null\n      }\n    })\n  }\n  if (!map.file) {\n    delete map.file\n  }\n\n  // unescape the previous hack\n  map.sources = map.sources.map((source) =>\n    source ? unescapeToLinuxLikePath(source) : source,\n  )\n  map.file = filename\n\n  return map as RawSourceMap\n}\n\nexport function unique<T>(arr: T[]): T[] {\n  return Array.from(new Set(arr))\n}\n\n/**\n * Returns resolved localhost address when `dns.lookup` result differs from DNS\n *\n * `dns.lookup` result is same when defaultResultOrder is `verbatim`.\n * Even if defaultResultOrder is `ipv4first`, `dns.lookup` result maybe same.\n * For example, when IPv6 is not supported on that machine/network.\n */\nexport async function getLocalhostAddressIfDiffersFromDNS(): Promise<\n  string | undefined\n> {\n  const [nodeResult, dnsResult] = await Promise.all([\n    dns.lookup('localhost'),\n    dns.lookup('localhost', { verbatim: true }),\n  ])\n  const isSame =\n    nodeResult.family === dnsResult.family &&\n    nodeResult.address === dnsResult.address\n  return isSame ? undefined : nodeResult.address\n}\n\nexport function diffDnsOrderChange(\n  oldUrls: ViteDevServer['resolvedUrls'],\n  newUrls: ViteDevServer['resolvedUrls'],\n): boolean {\n  return !(\n    oldUrls === newUrls ||\n    (oldUrls &&\n      newUrls &&\n      arrayEqual(oldUrls.local, newUrls.local) &&\n      arrayEqual(oldUrls.network, newUrls.network))\n  )\n}\n\nexport interface Hostname {\n  /** undefined sets the default behaviour of server.listen */\n  host: string | undefined\n  /** resolve to localhost when possible */\n  name: string\n}\n\nexport async function resolveHostname(\n  optionsHost: string | boolean | undefined,\n): Promise<Hostname> {\n  let host: string | undefined\n  if (optionsHost === undefined || optionsHost === false) {\n    // Use a secure default\n    host = 'localhost'\n  } else if (optionsHost === true) {\n    // If passed --host in the CLI without arguments\n    host = undefined // undefined typically means 0.0.0.0 or :: (listen on all IPs)\n  } else {\n    host = optionsHost\n  }\n\n  // Set host name to localhost when possible\n  let name = host === undefined || wildcardHosts.has(host) ? 'localhost' : host\n\n  if (host === 'localhost') {\n    // See #8647 for more details.\n    const localhostAddr = await getLocalhostAddressIfDiffersFromDNS()\n    if (localhostAddr) {\n      name = localhostAddr\n    }\n  }\n\n  return { host, name }\n}\n\nexport function extractHostnamesFromCerts(\n  certs: HttpsServerOptions['cert'] | undefined,\n): string[] {\n  const certList = certs ? arraify(certs) : []\n  if (certList.length === 0) return []\n\n  const hostnames = certList\n    .map((cert) => {\n      try {\n        return new crypto.X509Certificate(cert)\n      } catch {\n        return null\n      }\n    })\n    .flatMap((cert) =>\n      cert?.subjectAltName\n        ? extractHostnamesFromSubjectAltName(cert.subjectAltName)\n        : [],\n    )\n\n  return unique(hostnames)\n}\n\nexport function resolveServerUrls(\n  server: Server,\n  options: CommonServerOptions,\n  hostname: Hostname,\n  httpsOptions: HttpsServerOptions | undefined,\n  config: ResolvedConfig,\n): ResolvedServerUrls {\n  const address = server.address()\n\n  const isAddressInfo = (x: any): x is AddressInfo => x?.address\n  if (!isAddressInfo(address)) {\n    return { local: [], network: [] }\n  }\n\n  const local: string[] = []\n  const network: string[] = []\n  const protocol = options.https ? 'https' : 'http'\n  const port = address.port\n  const base =\n    config.rawBase === './' || config.rawBase === '' ? '/' : config.rawBase\n\n  if (hostname.host !== undefined && !wildcardHosts.has(hostname.host)) {\n    let hostnameName = hostname.name\n    // ipv6 host\n    if (hostnameName.includes(':')) {\n      hostnameName = `[${hostnameName}]`\n    }\n    const address = `${protocol}://${hostnameName}:${port}${base}`\n    if (loopbackHosts.has(hostname.host)) {\n      local.push(address)\n    } else {\n      network.push(address)\n    }\n  } else {\n    Object.values(os.networkInterfaces())\n      .flatMap((nInterface) => nInterface ?? [])\n      .filter((detail) => detail.address && detail.family === 'IPv4')\n      .forEach((detail) => {\n        let host = detail.address.replace('127.0.0.1', hostname.name)\n        // ipv6 host\n        if (host.includes(':')) {\n          host = `[${host}]`\n        }\n        const url = `${protocol}://${host}:${port}${base}`\n        if (detail.address.includes('127.0.0.1')) {\n          local.push(url)\n        } else {\n          network.push(url)\n        }\n      })\n  }\n\n  const hostnamesFromCert = extractHostnamesFromCerts(httpsOptions?.cert)\n  if (hostnamesFromCert.length > 0) {\n    const existings = new Set([...local, ...network])\n    local.push(\n      ...hostnamesFromCert\n        .map((hostname) => `${protocol}://${hostname}:${port}${base}`)\n        .filter((url) => !existings.has(url)),\n    )\n  }\n\n  return { local, network }\n}\n\nexport function extractHostnamesFromSubjectAltName(\n  subjectAltName: string,\n): string[] {\n  const hostnames: string[] = []\n  let remaining = subjectAltName\n  while (remaining) {\n    const nameEndIndex = remaining.indexOf(':')\n    const name = remaining.slice(0, nameEndIndex)\n    remaining = remaining.slice(nameEndIndex + 1)\n    if (!remaining) break\n\n    const isQuoted = remaining[0] === '\"'\n    let value: string\n    if (isQuoted) {\n      const endQuoteIndex = remaining.indexOf('\"', 1)\n      value = JSON.parse(remaining.slice(0, endQuoteIndex + 1))\n      remaining = remaining.slice(endQuoteIndex + 1)\n    } else {\n      const maybeEndIndex = remaining.indexOf(',')\n      const endIndex = maybeEndIndex === -1 ? remaining.length : maybeEndIndex\n      value = remaining.slice(0, endIndex)\n      remaining = remaining.slice(endIndex)\n    }\n    remaining = remaining.slice(/* for , */ 1).trimStart()\n\n    if (\n      name === 'DNS' &&\n      // [::1] might be included but skip it as it's already included as a local address\n      value !== '[::1]' &&\n      // skip *.IPv4 addresses, which is invalid\n      !(value.startsWith('*.') && net.isIPv4(value.slice(2)))\n    ) {\n      hostnames.push(value.replace('*', 'vite'))\n    }\n  }\n  return hostnames\n}\n\nexport function arraify<T>(target: T | T[]): T[] {\n  return Array.isArray(target) ? target : [target]\n}\n\n// Taken from https://stackoverflow.com/a/36328890\nexport const multilineCommentsRE: RegExp = /\\/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*\\//g\nexport const singlelineCommentsRE: RegExp = /\\/\\/.*/g\nexport const requestQuerySplitRE: RegExp = /\\?(?!.*[/|}])/\nexport const requestQueryMaybeEscapedSplitRE: RegExp = /\\\\?\\?(?!.*[/|}])/\n\nexport const blankReplacer = (match: string): string => ' '.repeat(match.length)\n\nexport function getHash(text: Buffer | string, length = 8): string {\n  const h = crypto.hash('sha256', text, 'hex').substring(0, length)\n  if (length <= 64) return h\n  return h.padEnd(length, '_')\n}\n\nexport function emptyCssComments(raw: string): string {\n  return raw.replace(multilineCommentsRE, blankReplacer)\n}\n\nfunction backwardCompatibleWorkerPlugins(plugins: any) {\n  if (Array.isArray(plugins)) {\n    return plugins\n  }\n  if (typeof plugins === 'function') {\n    return plugins()\n  }\n  return []\n}\n\ntype DeepWritable<T> =\n  T extends ReadonlyArray<unknown>\n    ? { -readonly [P in keyof T]: DeepWritable<T[P]> }\n    : T extends RegExp\n      ? RegExp\n      : T[keyof T] extends Function\n        ? T\n        : { -readonly [P in keyof T]: DeepWritable<T[P]> }\n\nexport function deepClone<T>(value: T): DeepWritable<T> {\n  if (Array.isArray(value)) {\n    return value.map((v) => deepClone(v)) as DeepWritable<T>\n  }\n  if (isObject(value)) {\n    const cloned: Record<string, any> = {}\n    for (const key in value) {\n      cloned[key] = deepClone(value[key])\n    }\n    return cloned as DeepWritable<T>\n  }\n  if (typeof value === 'function') {\n    return value as DeepWritable<T>\n  }\n  if (value instanceof RegExp) {\n    return new RegExp(value) as DeepWritable<T>\n  }\n  if (typeof value === 'object' && value != null) {\n    throw new Error('Cannot deep clone non-plain object')\n  }\n  return value as DeepWritable<T>\n}\n\ntype MaybeFallback<D, V> = undefined extends V ? Exclude<V, undefined> | D : V\n\ntype MergeWithDefaultsResult<D, V> =\n  Equal<D, undefined> extends true\n    ? V\n    : D extends Function | Array<any>\n      ? MaybeFallback<D, V>\n      : V extends Function | Array<any>\n        ? MaybeFallback<D, V>\n        : D extends Record<string, any>\n          ? V extends Record<string, any>\n            ? {\n                [K in keyof D | keyof V]: K extends keyof D\n                  ? K extends keyof V\n                    ? MergeWithDefaultsResult<D[K], V[K]>\n                    : D[K]\n                  : K extends keyof V\n                    ? V[K]\n                    : never\n              }\n            : MaybeFallback<D, V>\n          : MaybeFallback<D, V>\n\nfunction mergeWithDefaultsRecursively<\n  D extends Record<string, any>,\n  V extends Record<string, any>,\n>(defaults: D, values: V): MergeWithDefaultsResult<D, V> {\n  const merged: Record<string, any> = defaults\n  for (const key in values) {\n    const value = values[key]\n    // let null to set the value (e.g. `server.watch: null`)\n    if (value === undefined) continue\n\n    const existing = merged[key]\n    if (existing === undefined) {\n      merged[key] = value\n      continue\n    }\n\n    if (isObject(existing) && isObject(value)) {\n      merged[key] = mergeWithDefaultsRecursively(existing, value)\n      continue\n    }\n\n    // use replace even for arrays\n    merged[key] = value\n  }\n  return merged as MergeWithDefaultsResult<D, V>\n}\n\nconst environmentPathRE = /^environments\\.[^.]+$/\n\nexport function mergeWithDefaults<\n  D extends Record<string, any>,\n  V extends Record<string, any>,\n>(defaults: D, values: V): MergeWithDefaultsResult<DeepWritable<D>, V> {\n  // NOTE: we need to clone the value here to avoid mutating the defaults\n  const clonedDefaults = deepClone(defaults)\n  return mergeWithDefaultsRecursively(clonedDefaults, values)\n}\n\nconst runtimeDeprecatedPath = new Set(['optimizeDeps', 'ssr.optimizeDeps'])\nconst rollupOptionsDeprecationCall = (() => {\n  return () => {\n    const method = process.env.VITE_DEPRECATION_TRACE ? 'trace' : 'warn'\n    // eslint-disable-next-line no-console\n    console[method](\n      '`optimizeDeps.rollupOptions` / `ssr.optimizeDeps.rollupOptions` is deprecated. ' +\n        'Use `optimizeDeps.rolldownOptions` instead. Note that this option may be set by a plugin. ' +\n        (method === 'trace'\n          ? 'Showing trace because VITE_DEPRECATION_TRACE is set.'\n          : 'Set VITE_DEPRECATION_TRACE=1 to see where it is called.'),\n    )\n  }\n})()\n\nexport function setupRollupOptionCompat<\n  T extends Pick<BuildEnvironmentOptions, 'rollupOptions' | 'rolldownOptions'>,\n>(\n  buildConfig: T,\n  path: string,\n): asserts buildConfig is T & {\n  rolldownOptions: Exclude<T['rolldownOptions'], undefined>\n} {\n  // if both rollupOptions and rolldownOptions are present,\n  // ignore rollupOptions and use rolldownOptions\n  buildConfig.rolldownOptions ??= buildConfig.rollupOptions\n  if (\n    runtimeDeprecatedPath.has(path) &&\n    buildConfig.rollupOptions &&\n    buildConfig.rolldownOptions !== buildConfig.rollupOptions\n  ) {\n    rollupOptionsDeprecationCall()\n  }\n\n  // proxy rolldownOptions to rollupOptions\n  Object.defineProperty(buildConfig, 'rollupOptions', {\n    get() {\n      return buildConfig.rolldownOptions\n    },\n    set(newValue) {\n      if (runtimeDeprecatedPath.has(path)) {\n        rollupOptionsDeprecationCall()\n      }\n      buildConfig.rolldownOptions = newValue\n    },\n    configurable: true,\n    enumerable: true,\n  })\n}\n\nconst rollupOptionsRootPaths = new Set([\n  'build',\n  'worker',\n  'optimizeDeps',\n  'ssr.optimizeDeps',\n])\n\n/**\n * Sets up `rollupOptions` compat proxies for an environment.\n */\nfunction setupRollupOptionCompatForEnvironment(environment: any): any {\n  if (!isObject(environment)) {\n    return environment\n  }\n  const merged: Record<string, any> = { ...environment }\n  if (isObject(merged.build)) {\n    setupRollupOptionCompat(merged.build, 'build')\n  }\n  return merged\n}\n\nexport function hasBothRollupOptionsAndRolldownOptions(\n  options: Record<string, any>,\n): boolean {\n  for (const opt of [\n    options.build,\n    options.worker,\n    options.optimizeDeps,\n    options.ssr?.optimizeDeps,\n  ]) {\n    if (\n      opt != null &&\n      opt.rollupOptions != null &&\n      opt.rolldownOptions != null\n    ) {\n      return true\n    }\n  }\n  return false\n}\n\nfunction mergeConfigRecursively(\n  defaults: Record<string, any>,\n  overrides: Record<string, any>,\n  rootPath: string,\n) {\n  const merged: Record<string, any> = { ...defaults }\n  if (rollupOptionsRootPaths.has(rootPath)) {\n    setupRollupOptionCompat(merged, rootPath)\n  }\n\n  for (const key in overrides) {\n    const value = overrides[key]\n    if (value == null) {\n      continue\n    }\n\n    let existing = merged[key]\n    if (key === 'rollupOptions' && rollupOptionsRootPaths.has(rootPath)) {\n      // if both rollupOptions and rolldownOptions are present,\n      // ignore rollupOptions and use rolldownOptions\n      if (overrides.rolldownOptions) continue\n      existing = merged.rolldownOptions\n    }\n\n    if (existing == null) {\n      if (rootPath === '' && key === 'environments' && isObject(value)) {\n        // Clone to avoid mutating the original override object\n        const environments = { ...value }\n        for (const envName in environments) {\n          environments[envName] = setupRollupOptionCompatForEnvironment(\n            environments[envName],\n          )\n        }\n        merged[key] = environments\n      } else if (rootPath === 'environments') {\n        // `environments` exists, but a new environment is added\n        merged[key] = setupRollupOptionCompatForEnvironment(value)\n      } else {\n        merged[key] = value\n      }\n      continue\n    }\n\n    // fields that require special handling\n    if (key === 'alias' && (rootPath === 'resolve' || rootPath === '')) {\n      merged[key] = mergeAlias(existing, value)\n      continue\n    } else if (key === 'assetsInclude' && rootPath === '') {\n      merged[key] = [].concat(existing, value)\n      continue\n    } else if (\n      (((key === 'noExternal' || key === 'external') &&\n        (rootPath === 'ssr' || rootPath === 'resolve')) ||\n        (key === 'allowedHosts' && rootPath === 'server')) &&\n      (existing === true || value === true)\n    ) {\n      merged[key] = true\n      continue\n    } else if (key === 'plugins' && rootPath === 'worker') {\n      merged[key] = () => [\n        ...backwardCompatibleWorkerPlugins(existing),\n        ...backwardCompatibleWorkerPlugins(value),\n      ]\n      continue\n    } else if (key === 'server' && rootPath === 'server.hmr') {\n      merged[key] = value\n      continue\n    }\n\n    if (Array.isArray(existing) || Array.isArray(value)) {\n      merged[key] = [...arraify(existing), ...arraify(value)]\n      continue\n    }\n    if (isObject(existing) && isObject(value)) {\n      merged[key] = mergeConfigRecursively(\n        existing,\n        value,\n        // treat environment.* as root\n        rootPath && !environmentPathRE.test(rootPath)\n          ? `${rootPath}.${key}`\n          : key,\n      )\n      continue\n    }\n\n    merged[key] = value\n  }\n  return merged\n}\n\nexport function mergeConfig<\n  D extends Record<string, any>,\n  O extends Record<string, any>,\n>(\n  defaults: D extends Function ? never : D,\n  overrides: O extends Function ? never : O,\n  isRoot = true,\n): Record<string, any> {\n  if (typeof defaults === 'function' || typeof overrides === 'function') {\n    throw new Error(`Cannot merge config in form of callback`)\n  }\n\n  return mergeConfigRecursively(defaults, overrides, isRoot ? '' : '.')\n}\n\nexport function mergeAlias(\n  a?: AliasOptions,\n  b?: AliasOptions,\n): AliasOptions | undefined {\n  if (!a) return b\n  if (!b) return a\n  if (isObject(a) && isObject(b)) {\n    return { ...a, ...b }\n  }\n  // the order is flipped because the alias is resolved from top-down,\n  // where the later should have higher priority\n  return [...normalizeAlias(b), ...normalizeAlias(a)]\n}\n\nexport function normalizeAlias(o: AliasOptions = []): Alias[] {\n  return Array.isArray(o)\n    ? o.map(normalizeSingleAlias)\n    : Object.keys(o).map((find) =>\n        normalizeSingleAlias({\n          find,\n          replacement: (o as any)[find],\n        }),\n      )\n}\n\n// https://github.com/vitejs/vite/issues/1363\n// work around https://github.com/rollup/plugins/issues/759\nfunction normalizeSingleAlias({\n  find,\n  replacement,\n  customResolver,\n}: Alias): Alias {\n  if (\n    typeof find === 'string' &&\n    find.endsWith('/') &&\n    replacement.endsWith('/')\n  ) {\n    find = find.slice(0, find.length - 1)\n    replacement = replacement.slice(0, replacement.length - 1)\n  }\n\n  const alias: Alias = {\n    find,\n    replacement,\n  }\n  if (customResolver) {\n    alias.customResolver = customResolver\n  }\n  return alias\n}\n\n/**\n * Transforms transpiled code result where line numbers aren't altered,\n * so we can skip sourcemap generation during dev\n */\nexport function transformStableResult(\n  s: MagicString,\n  id: string,\n  config: ResolvedConfig,\n): TransformResult {\n  return {\n    code: s.toString(),\n    map:\n      config.command === 'build' && config.build.sourcemap\n        ? s.generateMap({ hires: 'boundary', source: id })\n        : null,\n  }\n}\n\ntype AsyncFlatten<T extends unknown[]> = T extends (infer U)[]\n  ? Exclude<Awaited<U>, U[]>[]\n  : never\n\nexport async function asyncFlatten<T extends unknown[]>(\n  arr: T,\n): Promise<AsyncFlatten<T>> {\n  do {\n    arr = (await Promise.all(arr)).flat(Infinity) as any\n  } while (arr.some((v: any) => v?.then))\n  return arr as unknown[] as AsyncFlatten<T>\n}\n\n// strip UTF-8 BOM\nexport function stripBomTag(content: string): string {\n  if (content.charCodeAt(0) === 0xfeff) {\n    return content.slice(1)\n  }\n\n  return content\n}\n\n/**\n * Determine if a file is being requested with the correct case, to ensure\n * consistent behavior between dev and prod and across operating systems.\n */\nexport function shouldServeFile(filePath: string, root: string): boolean {\n  // can skip case check on Linux\n  if (!isCaseInsensitiveFS) return true\n\n  return hasCorrectCase(filePath, root)\n}\n\n/**\n * Note that we can't use realpath here, because we don't want to follow\n * symlinks.\n */\nfunction hasCorrectCase(file: string, assets: string): boolean {\n  if (file === assets) return true\n\n  const parent = path.dirname(file)\n\n  if (fs.readdirSync(parent).includes(path.basename(file))) {\n    return hasCorrectCase(parent, assets)\n  }\n\n  return false\n}\n\nexport function joinUrlSegments(a: string, b: string): string {\n  if (!a || !b) {\n    return a || b || ''\n  }\n  if (a.endsWith('/')) {\n    a = a.substring(0, a.length - 1)\n  }\n  if (b[0] !== '/') {\n    b = '/' + b\n  }\n  return a + b\n}\n\nexport function removeLeadingSlash(str: string): string {\n  return str[0] === '/' ? str.slice(1) : str\n}\n\nexport function stripBase(path: string, base: string): string {\n  if (path === base) {\n    return '/'\n  }\n  const devBase = withTrailingSlash(base)\n  return path.startsWith(devBase) ? path.slice(devBase.length - 1) : path\n}\n\nexport function arrayEqual(a: any[], b: any[]): boolean {\n  if (a === b) return true\n  if (a.length !== b.length) return false\n  for (let i = 0; i < a.length; i++) {\n    if (a[i] !== b[i]) return false\n  }\n  return true\n}\n\nexport function evalValue<T = any>(rawValue: string): T {\n  const fn = new Function(`\n    var console, exports, global, module, process, require\n    return (\\n${rawValue}\\n)\n  `)\n  return fn()\n}\n\nexport function getNpmPackageName(importPath: string): string | null {\n  const parts = importPath.split('/')\n  if (parts[0][0] === '@') {\n    if (!parts[1]) return null\n    return `${parts[0]}/${parts[1]}`\n  } else {\n    return parts[0]\n  }\n}\n\nexport function getPkgName(name: string): string | undefined {\n  return name[0] === '@' ? name.split('/')[1] : name\n}\n\nconst escapeRegexRE = /[-/\\\\^$*+?.()|[\\]{}]/g\nexport function escapeRegex(str: string): string {\n  return str.replace(escapeRegexRE, '\\\\$&')\n}\n\ntype CommandType = 'install' | 'uninstall' | 'update'\nexport function getPackageManagerCommand(\n  type: CommandType = 'install',\n): string {\n  const packageManager =\n    process.env.npm_config_user_agent?.split(' ')[0].split('/')[0] || 'npm'\n  switch (type) {\n    case 'install':\n      return packageManager === 'npm' ? 'npm install' : `${packageManager} add`\n    case 'uninstall':\n      return packageManager === 'npm'\n        ? 'npm uninstall'\n        : `${packageManager} remove`\n    case 'update':\n      return packageManager === 'yarn'\n        ? 'yarn upgrade'\n        : `${packageManager} update`\n    default:\n      throw new TypeError(`Unknown command type: ${type}`)\n  }\n}\n\nexport function isDevServer(\n  server: ViteDevServer | PreviewServer,\n): server is ViteDevServer {\n  return 'pluginContainer' in server\n}\n\nexport function createSerialPromiseQueue<T>(): {\n  run(f: () => Promise<T>): Promise<T>\n} {\n  let previousTask: Promise<[unknown, Awaited<T>]> | undefined\n\n  return {\n    async run(f) {\n      const thisTask = f()\n      // wait for both the previous task and this task\n      // so that this function resolves in the order this function is called\n      const depTasks = Promise.all([previousTask, thisTask])\n      previousTask = depTasks\n\n      const [, result] = await depTasks\n\n      // this task was the last one, clear `previousTask` to free up memory\n      if (previousTask === depTasks) {\n        previousTask = undefined\n      }\n\n      return result\n    },\n  }\n}\n\nexport function sortObjectKeys<T extends Record<string, any>>(obj: T): T {\n  const sorted: Record<string, any> = {}\n  for (const key of Object.keys(obj).sort()) {\n    sorted[key] = obj[key]\n  }\n  return sorted as T\n}\n\nexport function displayTime(time: number): string {\n  // display: {X}ms\n  if (time < 1000) {\n    return `${time}ms`\n  }\n\n  time = time / 1000\n\n  // display: {X}s\n  if (time < 60) {\n    return `${time.toFixed(2)}s`\n  }\n\n  // Calculate total minutes and remaining seconds\n  const mins = Math.floor(time / 60)\n  const seconds = Math.round(time % 60)\n\n  // Handle case where seconds rounds to 60\n  if (seconds === 60) {\n    return `${mins + 1}m`\n  }\n\n  // display: {X}m {Y}s\n  return `${mins}m${seconds < 1 ? '' : ` ${seconds}s`}`\n}\n\n/**\n * Encodes the URI path portion (ignores part after ? or #)\n */\nexport function encodeURIPath(uri: string): string {\n  if (uri.startsWith('data:')) return uri\n  const filePath = cleanUrl(uri)\n  const postfix = filePath !== uri ? uri.slice(filePath.length) : ''\n  return encodeURI(filePath) + postfix\n}\n\n/**\n * Like `encodeURIPath`, but only replacing `%` as `%25`. This is useful for environments\n * that can handle un-encoded URIs, where `%` is the only ambiguous character.\n */\nexport function partialEncodeURIPath(uri: string): string {\n  if (uri.startsWith('data:')) return uri\n  const filePath = cleanUrl(uri)\n  const postfix = filePath !== uri ? uri.slice(filePath.length) : ''\n  return filePath.replaceAll('%', '%25') + postfix\n}\n\nexport function decodeURIIfPossible(input: string): string | undefined {\n  try {\n    return decodeURI(input)\n  } catch {\n    // url is malformed, probably a interpolate syntax of template engines\n    return\n  }\n}\n\ntype SigtermCallback = (signal?: 'SIGTERM', exitCode?: number) => Promise<void>\n\n// Use a shared callback when attaching sigterm listeners to avoid `MaxListenersExceededWarning`\nconst sigtermCallbacks = new Set<SigtermCallback>()\nconst parentSigtermCallback: SigtermCallback = async (signal, exitCode) => {\n  await Promise.all([...sigtermCallbacks].map((cb) => cb(signal, exitCode)))\n}\n\nexport const setupSIGTERMListener = (\n  callback: (signal?: 'SIGTERM', exitCode?: number) => Promise<void>,\n): void => {\n  if (sigtermCallbacks.size === 0) {\n    process.once('SIGTERM', parentSigtermCallback)\n    if (process.env.CI !== 'true') {\n      process.stdin.on('end', parentSigtermCallback)\n    }\n  }\n  sigtermCallbacks.add(callback)\n}\n\nexport const teardownSIGTERMListener = (\n  callback: Parameters<typeof setupSIGTERMListener>[0],\n): void => {\n  sigtermCallbacks.delete(callback)\n  if (sigtermCallbacks.size === 0) {\n    process.off('SIGTERM', parentSigtermCallback)\n    if (process.env.CI !== 'true') {\n      process.stdin.off('end', parentSigtermCallback)\n    }\n  }\n}\n\nexport function getServerUrlByHost(\n  resolvedUrls: ResolvedServerUrls | null,\n  host: CommonServerOptions['host'],\n): string | undefined {\n  if (typeof host === 'string') {\n    const matchedUrl = [\n      ...(resolvedUrls?.local ?? []),\n      ...(resolvedUrls?.network ?? []),\n    ].find((url) => url.includes(host))\n    if (matchedUrl) {\n      return matchedUrl\n    }\n  }\n  return resolvedUrls?.local[0] ?? resolvedUrls?.network[0]\n}\n\nlet lastDateNow = 0\n/**\n * Similar to `Date.now()`, but strictly monotonically increasing.\n *\n * This function will never return the same value.\n * Thus, the value may differ from the actual time.\n *\n * related: https://github.com/vitejs/vite/issues/19804\n */\nexport function monotonicDateNow(): number {\n  const now = Date.now()\n  if (now > lastDateNow) {\n    lastDateNow = now\n    return lastDateNow\n  }\n\n  lastDateNow++\n  return lastDateNow\n}\n"
  },
  {
    "path": "packages/vite/src/node/watch.ts",
    "content": "import { EventEmitter } from 'node:events'\nimport path from 'node:path'\nimport type { OutputOptions, WatcherOptions } from 'rolldown'\nimport colors from 'picocolors'\nimport { escapePath } from 'tinyglobby'\nimport type { FSWatcher, WatchOptions } from '#dep-types/chokidar'\nimport { withTrailingSlash } from '../shared/utils'\nimport { arraify, normalizePath } from './utils'\nimport type { Logger } from './logger'\n\nexport function getResolvedOutDirs(\n  root: string,\n  outDir: string,\n  outputOptions: OutputOptions[] | OutputOptions | undefined,\n): Set<string> {\n  const resolvedOutDir = path.resolve(root, outDir)\n  if (!outputOptions) return new Set([resolvedOutDir])\n\n  return new Set(\n    arraify(outputOptions).map(({ dir }) =>\n      dir ? path.resolve(root, dir) : resolvedOutDir,\n    ),\n  )\n}\n\nexport function resolveEmptyOutDir(\n  emptyOutDir: boolean | null,\n  root: string,\n  outDirs: Set<string>,\n  logger?: Logger,\n): boolean {\n  if (emptyOutDir != null) return emptyOutDir\n\n  for (const outDir of outDirs) {\n    if (!normalizePath(outDir).startsWith(withTrailingSlash(root))) {\n      // warn if outDir is outside of root\n      logger?.warn(\n        colors.yellow(\n          `\\n${colors.bold(`(!)`)} outDir ${colors.white(\n            colors.dim(outDir),\n          )} is not inside project root and will not be emptied.\\n` +\n            `Use --emptyOutDir to override.\\n`,\n        ),\n      )\n      return false\n    }\n  }\n  return true\n}\n\nexport function resolveChokidarOptions(\n  options: WatchOptions | undefined,\n  resolvedOutDirs: Set<string>,\n  emptyOutDir: boolean,\n  cacheDir: string,\n): WatchOptions {\n  const { ignored: ignoredList, ...otherOptions } = options ?? {}\n  const ignored: WatchOptions['ignored'] = [\n    '**/.git/**',\n    '**/node_modules/**',\n    '**/test-results/**', // Playwright\n    escapePath(cacheDir) + '/**',\n    ...arraify(ignoredList || []),\n  ]\n  if (emptyOutDir) {\n    ignored.push(\n      ...[...resolvedOutDirs].map((outDir) => escapePath(outDir) + '/**'),\n    )\n  }\n\n  const resolvedWatchOptions: WatchOptions = {\n    ignored,\n    ignoreInitial: true,\n    ignorePermissionErrors: true,\n    ...otherOptions,\n  }\n\n  return resolvedWatchOptions\n}\n\nexport function convertToWatcherOptions(\n  options: WatchOptions | undefined,\n): WatcherOptions['watcher'] {\n  if (!options) return\n\n  return {\n    usePolling: options.usePolling,\n    pollInterval: options.interval,\n  }\n}\n\nclass NoopWatcher extends EventEmitter implements FSWatcher {\n  constructor(public options: WatchOptions) {\n    super()\n  }\n\n  add() {\n    return this\n  }\n\n  unwatch() {\n    return this\n  }\n\n  getWatched() {\n    return {}\n  }\n\n  ref() {\n    return this\n  }\n\n  unref() {\n    return this\n  }\n\n  async close() {\n    // noop\n  }\n}\n\nexport function createNoopWatcher(options: WatchOptions): FSWatcher {\n  return new NoopWatcher(options)\n}\n"
  },
  {
    "path": "packages/vite/src/shared/__tests__/forwardConsole.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { formatConsoleArgs } from '../forwardConsole'\n\ndescribe('formatConsoleArgs', () => {\n  test('formats placeholders', () => {\n    expect(\n      formatConsoleArgs([\n        'format: string=%s number=%d int=%i float=%f json=%j object=%o object2=%O sym=%d style=%c literal=%% trailing',\n        'hello',\n        12.9,\n        '42px',\n        '3.5',\n        { id: 1 },\n        { enabled: true },\n        { nested: { deep: 1 } },\n        Symbol.for('x'),\n        'color:red',\n        'done',\n      ]),\n    ).toMatchInlineSnapshot(\n      `\"format: string=hello number=12.9 int=42 float=3.5 json={\"id\":1} object={\"enabled\":true} object2={\"nested\":{\"deep\":1}} sym=NaN style= literal=% trailing done\"`,\n    )\n\n    expect(\n      formatConsoleArgs(['num=%d int=%i pct=%% miss=%s sym=%d', 3.14, '42px']),\n    ).toMatchInlineSnapshot(`\"num=3.14 int=42 pct=% miss=%s sym=%d\"`)\n  })\n\n  test('stringifies diverse non-template arguments', () => {\n    const topError = new Error('boom')\n    topError.stack = undefined\n\n    const nestedError = new Error('nested')\n    nestedError.stack = undefined\n\n    const circular: any = {\n      ok: true,\n      big: 2n,\n      err: nestedError,\n    }\n    circular.self = circular\n\n    function sampleFn() {\n      return undefined\n    }\n\n    expect(\n      formatConsoleArgs([\n        1n,\n        undefined,\n        true,\n        Symbol.for('s'),\n        sampleFn,\n        topError,\n        circular,\n      ]),\n    ).toMatchInlineSnapshot(\n      `\"1n undefined true Symbol(s) [Function: sampleFn] Error: boom {\"ok\":true,\"big\":\"2n\",\"err\":{\"name\":\"Error\",\"message\":\"nested\"},\"self\":\"[Circular]\"}\"`,\n    )\n  })\n})\n"
  },
  {
    "path": "packages/vite/src/shared/builtin.ts",
    "content": "export function createIsBuiltin(\n  builtins: (string | RegExp)[],\n): (id: string) => boolean {\n  const plainBuiltinsSet = new Set(\n    builtins.filter((builtin) => typeof builtin === 'string'),\n  )\n  const regexBuiltins = builtins.filter(\n    (builtin) => typeof builtin !== 'string',\n  )\n\n  return (id: string) =>\n    plainBuiltinsSet.has(id) || regexBuiltins.some((regexp) => regexp.test(id))\n}\n"
  },
  {
    "path": "packages/vite/src/shared/constants.ts",
    "content": "/**\n * Prefix for resolved Ids that are not valid browser import specifiers\n */\nexport const VALID_ID_PREFIX = `/@id/`\n\n/**\n * Plugins that use 'virtual modules' (e.g. for helper functions), prefix the\n * module ID with `\\0`, a convention from the rollup ecosystem.\n * This prevents other plugins from trying to process the id (like node resolution),\n * and core features like sourcemaps can use this info to differentiate between\n * virtual modules and regular files.\n * `\\0` is not a permitted char in import URLs so we have to replace them during\n * import analysis. The id will be decoded back before entering the plugins pipeline.\n * These encoded virtual ids are also prefixed by the VALID_ID_PREFIX, so virtual\n * modules in the browser end up encoded as `/@id/__x00__{id}`\n */\nexport const NULL_BYTE_PLACEHOLDER = `__x00__`\n\nexport let SOURCEMAPPING_URL = 'sourceMa'\nSOURCEMAPPING_URL += 'ppingURL'\n\nexport const MODULE_RUNNER_SOURCEMAPPING_SOURCE =\n  '//# sourceMappingSource=vite-generated'\n\nexport const ERR_OUTDATED_OPTIMIZED_DEP = 'ERR_OUTDATED_OPTIMIZED_DEP'\n"
  },
  {
    "path": "packages/vite/src/shared/forwardConsole.ts",
    "content": "import type { ForwardConsolePayload } from '#types/customEvent'\nimport type { NormalizedModuleRunnerTransport } from './moduleRunnerTransport'\n\nexport type ForwardConsoleLogLevel =\n  | 'error'\n  | 'warn'\n  | 'info'\n  | 'log'\n  | 'debug'\n  | (string & {})\n\nexport interface ForwardConsoleOptions {\n  unhandledErrors?: boolean\n  logLevels?: ForwardConsoleLogLevel[]\n}\n\nexport interface ResolvedForwardConsoleOptions {\n  enabled: boolean\n  unhandledErrors: boolean\n  logLevels: ForwardConsoleLogLevel[]\n}\n\nexport function setupForwardConsoleHandler(\n  transport: NormalizedModuleRunnerTransport,\n  options: ResolvedForwardConsoleOptions,\n): void {\n  if (!options.enabled) {\n    return\n  }\n\n  function sendError(type: 'error' | 'unhandled-rejection', error: any) {\n    transport.send({\n      type: 'custom',\n      event: 'vite:forward-console',\n      data: {\n        type,\n        data: {\n          name: error?.name || 'Unknown Error',\n          message: error?.message || String(error),\n          stack: error?.stack,\n        },\n      } satisfies ForwardConsolePayload,\n    })\n  }\n\n  function sendLog(level: ForwardConsoleLogLevel, args: unknown[]) {\n    transport.send({\n      type: 'custom',\n      event: 'vite:forward-console',\n      data: {\n        type: 'log',\n        data: {\n          level,\n          message: formatConsoleArgs(args),\n        },\n      } satisfies ForwardConsolePayload,\n    })\n  }\n\n  for (const level of options.logLevels) {\n    const original = (console as any)[level]\n    if (typeof original !== 'function') {\n      continue\n    }\n    ;(console as any)[level] = (...args: unknown[]) => {\n      original(...args)\n      sendLog(level, args)\n    }\n  }\n\n  if (options.unhandledErrors && typeof window !== 'undefined') {\n    window.addEventListener('error', (event) => {\n      // `ErrorEvent` doesn't necessarily have `ErrorEvent.error`.\n      // Use `ErrorEvent.message` as fallback e.g. for ResizeObserver error.\n      // https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent/error\n      // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors\n      const error =\n        event.error ?? (event.message ? new Error(event.message) : event)\n      sendError('error', error)\n    })\n\n    window.addEventListener('unhandledrejection', (event) => {\n      sendError('unhandled-rejection', event.reason)\n    })\n  }\n}\n\n// Zero dep version of Vitest's console formatter\n// https://github.com/vitest-dev/vitest/blob/a2d650e00dbd8220397c5c25aef05c850100e446/packages/utils/src/display.ts#L129\nexport function formatConsoleArgs(args: unknown[]): string {\n  if (args.length === 0) {\n    return ''\n  }\n\n  if (typeof args[0] !== 'string') {\n    return args.map((arg) => stringifyConsoleArg(arg)).join(' ')\n  }\n\n  const len = args.length\n  let i = 1\n  let message = args[0].replace(/%[sdjifoOc%]/g, (specifier) => {\n    if (specifier === '%%') {\n      return '%'\n    }\n    if (i >= len) {\n      return specifier\n    }\n\n    const arg = args[i++]\n    switch (specifier) {\n      case '%s':\n        if (typeof arg === 'bigint') {\n          return `${arg.toString()}n`\n        }\n        return typeof arg === 'object' && arg != null\n          ? stringifyConsoleArg(arg)\n          : String(arg)\n      case '%d':\n        if (typeof arg === 'bigint') {\n          return `${arg.toString()}n`\n        }\n        if (typeof arg === 'symbol') {\n          return 'NaN'\n        }\n        return Number(arg).toString()\n      case '%i':\n        if (typeof arg === 'bigint') {\n          return `${arg.toString()}n`\n        }\n        return Number.parseInt(String(arg), 10).toString()\n      case '%f':\n        return Number.parseFloat(String(arg)).toString()\n      case '%o':\n      case '%O':\n        return stringifyConsoleArg(arg)\n      case '%j':\n        try {\n          const serialized = JSON.stringify(arg)\n          return serialized ?? 'undefined'\n        } catch {\n          return '[Circular]'\n        }\n      case '%c':\n        return ''\n      default:\n        return specifier\n    }\n  })\n\n  for (let arg = args[i]; i < len; arg = args[++i]) {\n    if (arg == null || typeof arg !== 'object') {\n      message += ` ${typeof arg === 'symbol' ? arg.toString() : String(arg)}`\n    } else {\n      message += ` ${stringifyConsoleArg(arg)}`\n    }\n  }\n\n  return message\n}\n\nfunction stringifyConsoleArg(value: unknown): string {\n  if (typeof value === 'string') {\n    return value\n  }\n  if (\n    typeof value === 'number' ||\n    typeof value === 'boolean' ||\n    typeof value === 'undefined'\n  ) {\n    return String(value)\n  }\n  if (typeof value === 'symbol') {\n    return value.toString()\n  }\n  if (typeof value === 'function') {\n    return value.name ? `[Function: ${value.name}]` : '[Function]'\n  }\n  if (value instanceof Error) {\n    return value.stack || `${value.name}: ${value.message}`\n  }\n  if (typeof value === 'bigint') {\n    return `${value}n`\n  }\n\n  const seen = new WeakSet<object>()\n  try {\n    const serialized = JSON.stringify(value, (_, nested) => {\n      if (typeof nested === 'bigint') {\n        return `${nested}n`\n      }\n      if (nested instanceof Error) {\n        return {\n          name: nested.name,\n          message: nested.message,\n          stack: nested.stack,\n        }\n      }\n      if (nested && typeof nested === 'object') {\n        if (seen.has(nested)) {\n          return '[Circular]'\n        }\n        seen.add(nested)\n      }\n      return nested\n    })\n    return serialized ?? String(value)\n  } catch {\n    return String(value)\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/shared/hmr.ts",
    "content": "import type { HotPayload, Update } from '#types/hmrPayload'\nimport type { ModuleNamespace, ViteHotContext } from '#types/hot'\nimport type { InferCustomEventPayload } from '#types/customEvent'\nimport type { NormalizedModuleRunnerTransport } from './moduleRunnerTransport'\n\ntype CustomListenersMap = Map<string, ((data: any) => void)[]>\n\ninterface HotModule {\n  id: string\n  callbacks: HotCallback[]\n}\n\ninterface HotCallback {\n  // the dependencies must be fetchable paths\n  deps: string[]\n  fn: (modules: Array<ModuleNamespace | undefined>) => void\n}\n\nexport interface HMRLogger {\n  error(msg: string | Error): void\n  debug(...msg: unknown[]): void\n}\n\nexport class HMRContext implements ViteHotContext {\n  private newListeners: CustomListenersMap\n\n  constructor(\n    private hmrClient: HMRClient,\n    private ownerPath: string,\n  ) {\n    if (!hmrClient.dataMap.has(ownerPath)) {\n      hmrClient.dataMap.set(ownerPath, {})\n    }\n\n    // when a file is hot updated, a new context is created\n    // clear its stale callbacks\n    const mod = hmrClient.hotModulesMap.get(ownerPath)\n    if (mod) {\n      mod.callbacks = []\n    }\n\n    // clear stale custom event listeners\n    const staleListeners = hmrClient.ctxToListenersMap.get(ownerPath)\n    if (staleListeners) {\n      for (const [event, staleFns] of staleListeners) {\n        const listeners = hmrClient.customListenersMap.get(event)\n        if (listeners) {\n          hmrClient.customListenersMap.set(\n            event,\n            listeners.filter((l) => !staleFns.includes(l)),\n          )\n        }\n      }\n    }\n\n    this.newListeners = new Map()\n    hmrClient.ctxToListenersMap.set(ownerPath, this.newListeners)\n  }\n\n  get data(): any {\n    return this.hmrClient.dataMap.get(this.ownerPath)\n  }\n\n  accept(deps?: any, callback?: any): void {\n    if (typeof deps === 'function' || !deps) {\n      // self-accept: hot.accept(() => {})\n      this.acceptDeps([this.ownerPath], ([mod]) => deps?.(mod))\n    } else if (typeof deps === 'string') {\n      // explicit deps\n      this.acceptDeps([deps], ([mod]) => callback?.(mod))\n    } else if (Array.isArray(deps)) {\n      this.acceptDeps(deps, callback)\n    } else {\n      throw new Error(`invalid hot.accept() usage.`)\n    }\n  }\n\n  // export names (first arg) are irrelevant on the client side, they're\n  // extracted in the server for propagation\n  acceptExports(\n    _: string | readonly string[],\n    callback?: (data: any) => void,\n  ): void {\n    this.acceptDeps([this.ownerPath], ([mod]) => callback?.(mod))\n  }\n\n  dispose(cb: (data: any) => void): void {\n    this.hmrClient.disposeMap.set(this.ownerPath, cb)\n  }\n\n  prune(cb: (data: any) => void): void {\n    this.hmrClient.pruneMap.set(this.ownerPath, cb)\n  }\n\n  // Kept for backward compatibility (#11036)\n  // eslint-disable-next-line @typescript-eslint/no-empty-function\n  decline(): void {}\n\n  invalidate(message: string): void {\n    const firstInvalidatedBy =\n      this.hmrClient.currentFirstInvalidatedBy ?? this.ownerPath\n    this.hmrClient.notifyListeners('vite:invalidate', {\n      path: this.ownerPath,\n      message,\n      firstInvalidatedBy,\n    })\n    this.send('vite:invalidate', {\n      path: this.ownerPath,\n      message,\n      firstInvalidatedBy,\n    })\n    this.hmrClient.logger.debug(\n      `invalidate ${this.ownerPath}${message ? `: ${message}` : ''}`,\n    )\n  }\n\n  on<T extends string>(\n    event: T,\n    cb: (payload: InferCustomEventPayload<T>) => void,\n  ): void {\n    const addToMap = (map: Map<string, any[]>) => {\n      const existing = map.get(event) || []\n      existing.push(cb)\n      map.set(event, existing)\n    }\n    addToMap(this.hmrClient.customListenersMap)\n    addToMap(this.newListeners)\n  }\n\n  off<T extends string>(\n    event: T,\n    cb: (payload: InferCustomEventPayload<T>) => void,\n  ): void {\n    const removeFromMap = (map: Map<string, any[]>) => {\n      const existing = map.get(event)\n      if (existing === undefined) {\n        return\n      }\n      const pruned = existing.filter((l) => l !== cb)\n      if (pruned.length === 0) {\n        map.delete(event)\n        return\n      }\n      map.set(event, pruned)\n    }\n    removeFromMap(this.hmrClient.customListenersMap)\n    removeFromMap(this.newListeners)\n  }\n\n  send<T extends string>(event: T, data?: InferCustomEventPayload<T>): void {\n    this.hmrClient.send({ type: 'custom', event, data })\n  }\n\n  private acceptDeps(\n    deps: string[],\n    callback: HotCallback['fn'] = () => {},\n  ): void {\n    const mod: HotModule = this.hmrClient.hotModulesMap.get(this.ownerPath) || {\n      id: this.ownerPath,\n      callbacks: [],\n    }\n    mod.callbacks.push({\n      deps,\n      fn: callback,\n    })\n    this.hmrClient.hotModulesMap.set(this.ownerPath, mod)\n  }\n}\n\nexport class HMRClient {\n  public hotModulesMap: Map<string, HotModule> = new Map()\n  public disposeMap: Map<string, (data: any) => void | Promise<void>> =\n    new Map()\n  public pruneMap: Map<string, (data: any) => void | Promise<void>> = new Map()\n  public dataMap: Map<string, any> = new Map()\n  public customListenersMap: CustomListenersMap = new Map()\n  public ctxToListenersMap: Map<string, CustomListenersMap> = new Map()\n  public currentFirstInvalidatedBy: string | undefined\n\n  constructor(\n    public logger: HMRLogger,\n    private transport: NormalizedModuleRunnerTransport,\n    // This allows implementing reloading via different methods depending on the environment\n    private importUpdatedModule: (update: Update) => Promise<ModuleNamespace>,\n  ) {}\n\n  public async notifyListeners<T extends string>(\n    event: T,\n    data: InferCustomEventPayload<T>,\n  ): Promise<void>\n  public async notifyListeners(event: string, data: any): Promise<void> {\n    const cbs = this.customListenersMap.get(event)\n    if (cbs) {\n      await Promise.allSettled(cbs.map((cb) => cb(data)))\n    }\n  }\n\n  public send(payload: HotPayload): void {\n    this.transport.send(payload).catch((err) => {\n      this.logger.error(err)\n    })\n  }\n\n  public clear(): void {\n    this.hotModulesMap.clear()\n    this.disposeMap.clear()\n    this.pruneMap.clear()\n    this.dataMap.clear()\n    this.customListenersMap.clear()\n    this.ctxToListenersMap.clear()\n  }\n\n  // After an HMR update, some modules are no longer imported on the page\n  // but they may have left behind side effects that need to be cleaned up\n  // (e.g. style injections)\n  public async prunePaths(paths: string[]): Promise<void> {\n    await Promise.all(\n      paths.map((path) => {\n        const disposer = this.disposeMap.get(path)\n        if (disposer) return disposer(this.dataMap.get(path))\n      }),\n    )\n    await Promise.all(\n      paths.map((path) => {\n        const fn = this.pruneMap.get(path)\n        if (fn) {\n          return fn(this.dataMap.get(path))\n        }\n      }),\n    )\n  }\n\n  protected warnFailedUpdate(err: Error, path: string | string[]): void {\n    if (!(err instanceof Error) || !err.message.includes('fetch')) {\n      this.logger.error(err)\n    }\n    this.logger.error(\n      `Failed to reload ${path}. ` +\n        `This could be due to syntax errors or importing non-existent ` +\n        `modules. (see errors above)`,\n    )\n  }\n\n  private updateQueue: Promise<(() => void) | undefined>[] = []\n  private pendingUpdateQueue = false\n\n  /**\n   * buffer multiple hot updates triggered by the same src change\n   * so that they are invoked in the same order they were sent.\n   * (otherwise the order may be inconsistent because of the http request round trip)\n   */\n  public async queueUpdate(payload: Update): Promise<void> {\n    this.updateQueue.push(this.fetchUpdate(payload))\n    if (!this.pendingUpdateQueue) {\n      this.pendingUpdateQueue = true\n      await Promise.resolve()\n      this.pendingUpdateQueue = false\n      const loading = [...this.updateQueue]\n      this.updateQueue = []\n      ;(await Promise.all(loading)).forEach((fn) => fn && fn())\n    }\n  }\n\n  private async fetchUpdate(update: Update): Promise<(() => void) | undefined> {\n    const { path, acceptedPath, firstInvalidatedBy } = update\n    const mod = this.hotModulesMap.get(path)\n    if (!mod) {\n      // In a code-splitting project,\n      // it is common that the hot-updating module is not loaded yet.\n      // https://github.com/vitejs/vite/issues/721\n      return\n    }\n\n    let fetchedModule: ModuleNamespace | undefined\n    const isSelfUpdate = path === acceptedPath\n\n    // determine the qualified callbacks before we re-import the modules\n    const qualifiedCallbacks = mod.callbacks.filter(({ deps }) =>\n      deps.includes(acceptedPath),\n    )\n\n    if (isSelfUpdate || qualifiedCallbacks.length > 0) {\n      const disposer = this.disposeMap.get(acceptedPath)\n      if (disposer) await disposer(this.dataMap.get(acceptedPath))\n      try {\n        fetchedModule = await this.importUpdatedModule(update)\n      } catch (e) {\n        this.warnFailedUpdate(e, acceptedPath)\n      }\n    }\n\n    return () => {\n      try {\n        this.currentFirstInvalidatedBy = firstInvalidatedBy\n        for (const { deps, fn } of qualifiedCallbacks) {\n          fn(\n            deps.map((dep) =>\n              dep === acceptedPath ? fetchedModule : undefined,\n            ),\n          )\n        }\n        const loggedPath = isSelfUpdate ? path : `${acceptedPath} via ${path}`\n        this.logger.debug(`hot updated: ${loggedPath}`)\n      } finally {\n        this.currentFirstInvalidatedBy = undefined\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/shared/hmrHandler.ts",
    "content": "import type { HotPayload } from '#types/hmrPayload'\n\n// updates to HMR should go one after another. It is possible to trigger another update during the invalidation for example.\nexport function createHMRHandler(\n  handler: (payload: HotPayload) => Promise<void>,\n): (payload: HotPayload) => Promise<void> {\n  const queue = new Queue()\n  return (payload) => queue.enqueue(() => handler(payload))\n}\n\nclass Queue {\n  private queue: {\n    promise: () => Promise<void>\n    resolve: (value?: unknown) => void\n    reject: (err?: unknown) => void\n  }[] = []\n  private pending = false\n\n  enqueue(promise: () => Promise<void>): Promise<void> {\n    return new Promise<any>((resolve, reject) => {\n      this.queue.push({\n        promise,\n        resolve,\n        reject,\n      })\n      this.dequeue()\n    })\n  }\n\n  dequeue(): boolean {\n    if (this.pending) {\n      return false\n    }\n    const item = this.queue.shift()\n    if (!item) {\n      return false\n    }\n    this.pending = true\n    item\n      .promise()\n      .then(item.resolve)\n      .catch(item.reject)\n      .finally(() => {\n        this.pending = false\n        this.dequeue()\n      })\n    return true\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/shared/invokeMethods.ts",
    "content": "export interface FetchFunctionOptions {\n  cached?: boolean\n  startOffset?: number\n}\n\nexport type FetchResult =\n  | CachedFetchResult\n  | ExternalFetchResult\n  | ViteFetchResult\n\nexport interface CachedFetchResult {\n  /**\n   * If module cached in the runner, we can just confirm\n   * it wasn't invalidated on the server side.\n   */\n  cache: true\n}\n\nexport interface ExternalFetchResult {\n  /**\n   * The path to the externalized module starting with file://,\n   * by default this will be imported via a dynamic \"import\"\n   * instead of being transformed by vite and loaded with vite runner\n   */\n  externalize: string\n  /**\n   * Type of the module. Will be used to determine if import statement is correct.\n   * For example, if Vite needs to throw an error if variable is not actually exported\n   */\n  type: 'module' | 'commonjs' | 'builtin' | 'network'\n}\n\nexport interface ViteFetchResult {\n  /**\n   * Code that will be evaluated by vite runner\n   * by default this will be wrapped in an async function\n   */\n  code: string\n  /**\n   * File path of the module on disk.\n   * This will be resolved as import.meta.url/filename\n   * Will be equal to `null` for virtual modules\n   */\n  file: string | null\n  /**\n   * Module ID in the server module graph.\n   */\n  id: string\n  /**\n   * Module URL used in the import.\n   */\n  url: string\n  /**\n   * Invalidate module on the client side.\n   */\n  invalidate: boolean\n}\n\nexport type InvokeSendData<\n  T extends keyof InvokeMethods = keyof InvokeMethods,\n> = {\n  name: T\n  /** 'send' is for requests without an id */\n  id: 'send' | `send:${string}`\n  data: Parameters<InvokeMethods[T]>\n}\n\nexport type InvokeResponseData<\n  T extends keyof InvokeMethods = keyof InvokeMethods,\n> = {\n  name: T\n  /** 'response' is for responses without an id */\n  id: 'response' | `response:${string}`\n  data:\n    | { result: Awaited<ReturnType<InvokeMethods[T]>>; error?: undefined }\n    | { result?: undefined; error: any }\n}\n\nexport type InvokeMethods = {\n  fetchModule: (\n    id: string,\n    importer?: string,\n    options?: FetchFunctionOptions,\n  ) => Promise<FetchResult>\n\n  getBuiltins: () => Promise<\n    Array<\n      | { type: 'string'; value: string }\n      | { type: 'RegExp'; source: string; flags: string }\n    >\n  >\n}\n"
  },
  {
    "path": "packages/vite/src/shared/moduleRunnerTransport.ts",
    "content": "import { nanoid } from 'nanoid/non-secure'\nimport type { CustomPayload, HotPayload } from '#types/hmrPayload'\nimport { promiseWithResolvers } from './utils'\nimport type {\n  InvokeMethods,\n  InvokeResponseData,\n  InvokeSendData,\n} from './invokeMethods'\n\nexport type ModuleRunnerTransportHandlers = {\n  onMessage: (data: HotPayload) => void\n  onDisconnection: () => void\n}\n\n/**\n * \"send and connect\" or \"invoke\" must be implemented\n */\nexport interface ModuleRunnerTransport {\n  connect?(handlers: ModuleRunnerTransportHandlers): Promise<void> | void\n  disconnect?(): Promise<void> | void\n  send?(data: HotPayload): Promise<void> | void\n  invoke?(data: HotPayload): Promise<{ result: any } | { error: any }>\n  timeout?: number\n}\n\ntype InvokeableModuleRunnerTransport = Omit<ModuleRunnerTransport, 'invoke'> & {\n  invoke<T extends keyof InvokeMethods>(\n    name: T,\n    data: Parameters<InvokeMethods[T]>,\n  ): Promise<ReturnType<Awaited<InvokeMethods[T]>>>\n}\n\nfunction reviveInvokeError(e: any) {\n  const error = new Error(e.message || 'Unknown invoke error')\n  Object.assign(error, e, {\n    // pass the whole error instead of just the stacktrace\n    // so that it gets formatted nicely with console.log\n    runnerError: new Error('RunnerError'),\n  })\n  return error\n}\n\nconst createInvokeableTransport = (\n  transport: ModuleRunnerTransport,\n): InvokeableModuleRunnerTransport => {\n  if (transport.invoke) {\n    return {\n      ...transport,\n      async invoke(name, data) {\n        const result = await transport.invoke!({\n          type: 'custom',\n          event: 'vite:invoke',\n          data: {\n            id: 'send',\n            name,\n            data,\n          } satisfies InvokeSendData,\n        } satisfies CustomPayload)\n        if ('error' in result) {\n          throw reviveInvokeError(result.error)\n        }\n        return result.result\n      },\n    }\n  }\n\n  if (!transport.send || !transport.connect) {\n    throw new Error(\n      'transport must implement send and connect when invoke is not implemented',\n    )\n  }\n\n  const rpcPromises = new Map<\n    string,\n    {\n      resolve: (data: any) => void\n      reject: (data: any) => void\n      name: string\n      timeoutId?: ReturnType<typeof setTimeout>\n    }\n  >()\n\n  return {\n    ...transport,\n    connect({ onMessage, onDisconnection }) {\n      return transport.connect!({\n        onMessage(payload) {\n          if (payload.type === 'custom' && payload.event === 'vite:invoke') {\n            const data = payload.data as InvokeResponseData\n            if (data.id.startsWith('response:')) {\n              const invokeId = data.id.slice('response:'.length)\n              const promise = rpcPromises.get(invokeId)\n              if (!promise) return\n\n              if (promise.timeoutId) clearTimeout(promise.timeoutId)\n\n              rpcPromises.delete(invokeId)\n\n              const { error, result } = data.data\n              if (error) {\n                promise.reject(error)\n              } else {\n                promise.resolve(result)\n              }\n              return\n            }\n          }\n          onMessage(payload)\n        },\n        onDisconnection,\n      })\n    },\n    disconnect() {\n      rpcPromises.forEach((promise) => {\n        promise.reject(\n          new Error(\n            `transport was disconnected, cannot call ${JSON.stringify(promise.name)}`,\n          ),\n        )\n      })\n      rpcPromises.clear()\n      return transport.disconnect?.()\n    },\n    send(data) {\n      return transport.send!(data)\n    },\n    async invoke<T extends keyof InvokeMethods>(\n      name: T,\n      data: Parameters<InvokeMethods[T]>,\n    ) {\n      const promiseId = nanoid()\n      const wrappedData: CustomPayload = {\n        type: 'custom',\n        event: 'vite:invoke',\n        data: {\n          name,\n          id: `send:${promiseId}`,\n          data,\n        } satisfies InvokeSendData,\n      }\n      const sendPromise = transport.send!(wrappedData)\n\n      const { promise, resolve, reject } =\n        promiseWithResolvers<ReturnType<Awaited<InvokeMethods[T]>>>()\n      const timeout = transport.timeout ?? 60000\n      let timeoutId: ReturnType<typeof setTimeout> | undefined\n      if (timeout > 0) {\n        timeoutId = setTimeout(() => {\n          rpcPromises.delete(promiseId)\n          reject(\n            new Error(\n              `transport invoke timed out after ${timeout}ms (data: ${JSON.stringify(wrappedData)})`,\n            ),\n          )\n        }, timeout)\n        timeoutId?.unref?.()\n      }\n      rpcPromises.set(promiseId, { resolve, reject, name, timeoutId })\n\n      if (sendPromise) {\n        sendPromise.catch((err) => {\n          clearTimeout(timeoutId)\n          rpcPromises.delete(promiseId)\n          reject(err)\n        })\n      }\n\n      try {\n        return await promise\n      } catch (err) {\n        throw reviveInvokeError(err)\n      }\n    },\n  }\n}\n\nexport interface NormalizedModuleRunnerTransport {\n  connect?(onMessage?: (data: HotPayload) => void): Promise<void> | void\n  disconnect?(): Promise<void> | void\n  send(data: HotPayload): Promise<void>\n  invoke<T extends keyof InvokeMethods>(\n    name: T,\n    data: Parameters<InvokeMethods[T]>,\n  ): Promise<ReturnType<Awaited<InvokeMethods[T]>>>\n}\n\nexport const normalizeModuleRunnerTransport = (\n  transport: ModuleRunnerTransport,\n): NormalizedModuleRunnerTransport => {\n  const invokeableTransport = createInvokeableTransport(transport)\n\n  let isConnected = !invokeableTransport.connect\n  let connectingPromise: Promise<void> | undefined\n\n  return {\n    ...(transport as Omit<ModuleRunnerTransport, 'connect'>),\n    ...(invokeableTransport.connect\n      ? {\n          async connect(onMessage) {\n            if (isConnected) return\n            if (connectingPromise) {\n              await connectingPromise\n              return\n            }\n\n            const maybePromise = invokeableTransport.connect!({\n              onMessage: onMessage ?? (() => {}),\n              onDisconnection() {\n                isConnected = false\n              },\n            })\n            if (maybePromise) {\n              connectingPromise = maybePromise\n              await connectingPromise\n              connectingPromise = undefined\n            }\n            isConnected = true\n          },\n        }\n      : {}),\n    ...(invokeableTransport.disconnect\n      ? {\n          async disconnect() {\n            if (!isConnected) return\n            if (connectingPromise) {\n              await connectingPromise\n            }\n            isConnected = false\n            await invokeableTransport.disconnect!()\n          },\n        }\n      : {}),\n    async send(data) {\n      if (!invokeableTransport.send) return\n\n      if (!isConnected) {\n        if (connectingPromise) {\n          await connectingPromise\n        } else {\n          throw new Error('send was called before connect')\n        }\n      }\n      await invokeableTransport.send(data)\n    },\n    async invoke(name, data) {\n      if (!isConnected) {\n        if (connectingPromise) {\n          await connectingPromise\n        } else {\n          throw new Error('invoke was called before connect')\n        }\n      }\n      return invokeableTransport.invoke(name, data)\n    },\n  }\n}\n\nexport const createWebSocketModuleRunnerTransport = (options: {\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  createConnection: () => WebSocket\n  pingInterval?: number\n}): Required<\n  Pick<ModuleRunnerTransport, 'connect' | 'disconnect' | 'send'>\n> => {\n  const pingInterval = options.pingInterval ?? 30000\n\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  let ws: WebSocket | undefined\n  let pingIntervalId: ReturnType<typeof setInterval> | undefined\n  return {\n    async connect({ onMessage, onDisconnection }) {\n      const socket = options.createConnection()\n      socket.addEventListener('message', async ({ data }) => {\n        onMessage(JSON.parse(data))\n      })\n\n      let isOpened = socket.readyState === socket.OPEN\n      if (!isOpened) {\n        await new Promise<void>((resolve, reject) => {\n          socket.addEventListener(\n            'open',\n            () => {\n              isOpened = true\n              resolve()\n            },\n            { once: true },\n          )\n          socket.addEventListener('close', async () => {\n            if (!isOpened) {\n              reject(new Error('WebSocket closed without opened.'))\n              return\n            }\n\n            onMessage({\n              type: 'custom',\n              event: 'vite:ws:disconnect',\n              data: { webSocket: socket },\n            })\n            onDisconnection()\n          })\n        })\n      }\n\n      onMessage({\n        type: 'custom',\n        event: 'vite:ws:connect',\n        data: { webSocket: socket },\n      })\n      ws = socket\n\n      // proxy(nginx, docker) hmr ws maybe caused timeout,\n      // so send ping package let ws keep alive.\n      pingIntervalId = setInterval(() => {\n        if (socket.readyState === socket.OPEN) {\n          socket.send(JSON.stringify({ type: 'ping' }))\n        }\n      }, pingInterval)\n    },\n    disconnect() {\n      clearInterval(pingIntervalId)\n      ws?.close()\n    },\n    send(data) {\n      ws!.send(JSON.stringify(data))\n    },\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/shared/ssrTransform.ts",
    "content": "export interface DefineImportMetadata {\n  /**\n   * Imported names before being transformed to `ssrImportKey`\n   *\n   * import foo, { bar as baz, qux } from 'hello'\n   * => ['default', 'bar', 'qux']\n   *\n   * import * as namespace from 'world\n   * => undefined\n   */\n  importedNames?: string[]\n}\n\nexport interface SSRImportMetadata extends DefineImportMetadata {\n  isDynamicImport?: boolean\n}\n\n/**\n * Vite converts `import { } from 'foo'` to `const _ = __vite_ssr_import__('foo')`.\n * Top-level imports and dynamic imports work slightly differently in Node.js.\n * This function normalizes the differences so it matches prod behaviour.\n */\nexport function analyzeImportedModDifference(\n  mod: any,\n  rawId: string,\n  moduleType: string | undefined,\n  metadata?: SSRImportMetadata,\n): void {\n  // No normalization needed if the user already dynamic imports this module\n  if (metadata?.isDynamicImport) return\n\n  // If the user named imports a specifier that can't be analyzed, error.\n  // If the module doesn't import anything explicitly, e.g. `import 'foo'` or\n  // `import * as foo from 'foo'`, we can skip.\n  if (metadata?.importedNames?.length) {\n    const missingBindings = metadata.importedNames.filter((s) => !(s in mod))\n    if (missingBindings.length) {\n      const lastBinding = missingBindings[missingBindings.length - 1]\n\n      // For invalid named exports only, similar to how Node.js errors for top-level imports.\n      // But since we transform as dynamic imports, we need to emulate the error manually.\n      if (moduleType === 'module') {\n        throw new SyntaxError(\n          `[vite] The requested module '${rawId}' does not provide an export named '${lastBinding}'`,\n        )\n      } else {\n        // For non-ESM, named imports is done via static analysis with cjs-module-lexer in Node.js.\n        // Copied from Node.js\n        throw new SyntaxError(`\\\n[vite] Named export '${lastBinding}' not found. The requested module '${rawId}' is a CommonJS module, which may not support all module.exports as named exports.\nCommonJS modules can always be imported via the default export, for example using:\n\nimport pkg from '${rawId}';\nconst {${missingBindings.join(', ')}} = pkg;\n`)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/shared/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.base.json\",\n  \"include\": [\"./\", \"../types\"],\n  \"exclude\": [\"__tests__\"],\n  \"compilerOptions\": {\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"stripInternal\": true\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/shared/utils.ts",
    "content": "import { NULL_BYTE_PLACEHOLDER, VALID_ID_PREFIX } from './constants'\n\nexport const isWindows: boolean =\n  typeof process !== 'undefined' && process.platform === 'win32'\n\n/**\n * Prepend `/@id/` and replace null byte so the id is URL-safe.\n * This is prepended to resolved ids that are not valid browser\n * import specifiers by the importAnalysis plugin.\n */\nexport function wrapId(id: string): string {\n  return id.startsWith(VALID_ID_PREFIX)\n    ? id\n    : VALID_ID_PREFIX + id.replace('\\0', NULL_BYTE_PLACEHOLDER)\n}\n\n/**\n * Undo {@link wrapId}'s `/@id/` and null byte replacements.\n */\nexport function unwrapId(id: string): string {\n  return id.startsWith(VALID_ID_PREFIX)\n    ? id.slice(VALID_ID_PREFIX.length).replace(NULL_BYTE_PLACEHOLDER, '\\0')\n    : id\n}\n\nconst windowsSlashRE = /\\\\/g\nexport function slash(p: string): string {\n  return p.replace(windowsSlashRE, '/')\n}\n\nconst postfixRE = /[?#].*$/\nexport function cleanUrl(url: string): string {\n  return url.replace(postfixRE, '')\n}\n\nexport function splitFileAndPostfix(path: string): {\n  file: string\n  postfix: string\n} {\n  const file = cleanUrl(path)\n  return { file, postfix: path.slice(file.length) }\n}\n\nexport function isPrimitive(value: unknown): boolean {\n  return !value || (typeof value !== 'object' && typeof value !== 'function')\n}\n\nexport function withTrailingSlash(path: string): string {\n  if (path[path.length - 1] !== '/') {\n    return `${path}/`\n  }\n  return path\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nexport const AsyncFunction = async function () {}.constructor as typeof Function\n\n// https://github.com/nodejs/node/issues/43047#issuecomment-1564068099\nlet asyncFunctionDeclarationPaddingLineCount: number | undefined\n\nexport function getAsyncFunctionDeclarationPaddingLineCount(): number {\n  if (typeof asyncFunctionDeclarationPaddingLineCount === 'undefined') {\n    const body = '/*code*/'\n    const source = new AsyncFunction('a', 'b', body).toString()\n    asyncFunctionDeclarationPaddingLineCount =\n      source.slice(0, source.indexOf(body)).split('\\n').length - 1\n  }\n  return asyncFunctionDeclarationPaddingLineCount\n}\n\nexport interface PromiseWithResolvers<T> {\n  promise: Promise<T>\n  resolve: (value: T | PromiseLike<T>) => void\n  reject: (reason?: any) => void\n}\nexport function promiseWithResolvers<T>(): PromiseWithResolvers<T> {\n  let resolve: any\n  let reject: any\n  const promise = new Promise<T>((_resolve, _reject) => {\n    resolve = _resolve\n    reject = _reject\n  })\n  return { promise, resolve, reject }\n}\n"
  },
  {
    "path": "packages/vite/src/types/alias.d.ts",
    "content": "/**\nTypes from https://github.com/rollup/plugins/blob/master/packages/alias/types/index.d.ts\nInlined because the plugin is bundled.\n\nhttps://github.com/rollup/plugins/blob/master/LICENSE\n\nThe MIT License (MIT)\n\nCopyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n\nimport type { FunctionPluginHooks } from 'rolldown'\n\nexport interface Alias {\n  find: string | RegExp\n  replacement: string\n  /**\n   * Instructs the plugin to use an alternative resolving algorithm,\n   * rather than the Rollup's resolver.\n   * @default null\n   * @deprecated Use a custom plugin with resolveId hook and `enforce: 'pre'` instead\n   */\n  customResolver?: ResolverFunction | ResolverObject | null\n}\n\nexport type MapToFunction<T> = T extends Function ? T : never\n\nexport type ResolverFunction = MapToFunction<FunctionPluginHooks['resolveId']>\n\nexport interface ResolverObject {\n  buildStart?: FunctionPluginHooks['buildStart']\n  resolveId: ResolverFunction\n}\n\n/**\n * Specifies an `Object`, or an `Array` of `Object`,\n * which defines aliases used to replace values in `import` or `require` statements.\n * With either format, the order of the entries is important,\n * in that the first defined rules are applied first.\n *\n * This is passed to \\@rollup/plugin-alias as the \"entries\" field\n * https://github.com/rollup/plugins/tree/master/packages/alias#entries\n */\nexport type AliasOptions = readonly Alias[] | { [find: string]: string }\n"
  },
  {
    "path": "packages/vite/src/types/anymatch.d.ts",
    "content": "export type AnymatchFn = (testString: string) => boolean\nexport type AnymatchPattern = string | RegExp | AnymatchFn\ntype AnymatchMatcher = AnymatchPattern | AnymatchPattern[]\n\nexport { AnymatchMatcher as Matcher }\n"
  },
  {
    "path": "packages/vite/src/types/chokidar.d.ts",
    "content": "// Inlined to avoid extra dependency (chokidar is bundled in the published build)\n\n// https://github.com/paulmillr/chokidar/blob/3.6.0/types/index.d.ts\n// MIT Licensed https://github.com/paulmillr/chokidar/blob/3.6.0/LICENSE\n\n/// <reference types=\"node\" />\n\nimport type * as fs from 'node:fs'\nimport { EventEmitter } from 'node:events'\nimport type { Matcher } from './anymatch'\n\nexport class FSWatcher extends EventEmitter implements fs.FSWatcher {\n  options: WatchOptions\n\n  /**\n   * Constructs a new FSWatcher instance with optional WatchOptions parameter.\n   */\n  constructor(options?: WatchOptions)\n\n  /**\n   * When called, requests that the Node.js event loop not exit so long as the fs.FSWatcher is active.\n   * Calling watcher.ref() multiple times will have no effect.\n   */\n  ref(): this\n\n  /**\n   * When called, the active fs.FSWatcher object will not require the Node.js event loop to remain active.\n   * If there is no other activity keeping the event loop running, the process may exit before the fs.FSWatcher object's callback is invoked.\n   * Calling watcher.unref() multiple times will have no effect.\n   */\n  unref(): this\n\n  /**\n   * Add files, directories, or glob patterns for tracking. Takes an array of strings or just one\n   * string.\n   */\n  add(paths: string | ReadonlyArray<string>): this\n\n  /**\n   * Stop watching files, directories, or glob patterns. Takes an array of strings or just one\n   * string.\n   */\n  unwatch(paths: string | ReadonlyArray<string>): this\n\n  /**\n   * Returns an object representing all the paths on the file system being watched by this\n   * `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless\n   * the `cwd` option was used), and the values are arrays of the names of the items contained in\n   * each directory.\n   */\n  getWatched(): {\n    [directory: string]: string[]\n  }\n\n  /**\n   * Removes all listeners from watched files.\n   */\n  close(): Promise<void>\n\n  on(\n    event: 'add' | 'addDir' | 'change',\n    listener: (path: string, stats?: fs.Stats) => void,\n  ): this\n\n  on(\n    event: 'all',\n    listener: (\n      eventName: 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir',\n      path: string,\n      stats?: fs.Stats,\n    ) => void,\n  ): this\n\n  /**\n   * Error occurred\n   */\n  on(event: 'error', listener: (error: Error) => void): this\n\n  /**\n   * Exposes the native Node `fs.FSWatcher events`\n   */\n  on(\n    event: 'raw',\n    listener: (eventName: string, path: string, details: any) => void,\n  ): this\n\n  /**\n   * Fires when the initial scan is complete\n   */\n  on(event: 'ready', listener: () => void): this\n\n  on(event: 'unlink' | 'unlinkDir', listener: (path: string) => void): this\n\n  on(event: string, listener: (...args: any[]) => void): this\n}\n\nexport interface WatchOptions {\n  /**\n   * Indicates whether the process should continue to run as long as files are being watched. If\n   * set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`,\n   * even if the process continues to run.\n   */\n  persistent?: boolean\n\n  /**\n   * ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to\n   * be ignored. The whole relative or absolute path is tested, not just filename. If a function\n   * with two arguments is provided, it gets called twice per path - once with a single argument\n   * (the path), second time with two arguments (the path and the\n   * [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path).\n   */\n  ignored?: Matcher\n\n  /**\n   * If set to `false` then `add`/`addDir` events are also emitted for matching paths while\n   * instantiating the watching as chokidar discovers these file paths (before the `ready` event).\n   */\n  ignoreInitial?: boolean\n\n  /**\n   * When `false`, only the symlinks themselves will be watched for changes instead of following\n   * the link references and bubbling events through the link's path.\n   */\n  followSymlinks?: boolean\n\n  /**\n   * The base directory from which watch `paths` are to be derived. Paths emitted with events will\n   * be relative to this.\n   */\n  cwd?: string\n\n  /**\n   * If set to true then the strings passed to .watch() and .add() are treated as literal path\n   * names, even if they look like globs.\n   *\n   * @default false\n   */\n  disableGlobbing?: boolean\n\n  /**\n   * Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU\n   * utilization, consider setting this to `false`. It is typically necessary to **set this to\n   * `true` to successfully watch files over a network**, and it may be necessary to successfully\n   * watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides\n   * the `useFsEvents` default.\n   */\n  usePolling?: boolean\n\n  /**\n   * Whether to use the `fsevents` watching interface if available. When set to `true` explicitly\n   * and `fsevents` is available this supersedes the `usePolling` setting. When set to `false` on\n   * OS X, `usePolling: true` becomes the default.\n   */\n  useFsEvents?: boolean\n\n  /**\n   * If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that\n   * may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is\n   * provided even in cases where it wasn't already available from the underlying watch events.\n   */\n  alwaysStat?: boolean\n\n  /**\n   * If set, limits how many levels of subdirectories will be traversed.\n   */\n  depth?: number\n\n  /**\n   * Interval of file system polling.\n   */\n  interval?: number\n\n  /**\n   * Interval of file system polling for binary files. ([see list of binary extensions](https://gi\n   * thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))\n   */\n  binaryInterval?: number\n\n  /**\n   *  Indicates whether to watch files that don't have read permissions if possible. If watching\n   *  fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed\n   *  silently.\n   */\n  ignorePermissionErrors?: boolean\n\n  /**\n   * `true` if `useFsEvents` and `usePolling` are `false`. Automatically filters out artifacts\n   * that occur when using editors that use \"atomic writes\" instead of writing directly to the\n   * source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change`\n   * event rather than `unlink` then `add`. If the default of 100 ms does not work well for you,\n   * you can override it by setting `atomic` to a custom value, in milliseconds.\n   */\n  atomic?: boolean | number\n\n  /**\n   * can be set to an object in order to adjust timing params:\n   */\n  awaitWriteFinish?: AwaitWriteFinishOptions | boolean\n}\n\nexport interface AwaitWriteFinishOptions {\n  /**\n   * Amount of time in milliseconds for a file size to remain constant before emitting its event.\n   */\n  stabilityThreshold?: number\n\n  /**\n   * File size polling interval.\n   */\n  pollInterval?: number\n}\n\n/**\n * produces an instance of `FSWatcher`.\n */\nexport function watch(\n  paths: string | ReadonlyArray<string>,\n  options?: WatchOptions,\n): FSWatcher\n"
  },
  {
    "path": "packages/vite/src/types/commonjs.d.ts",
    "content": "/**\n * https://github.com/rollup/plugins/blob/master/packages/commonjs/types/index.d.ts\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file at\n * https://github.com/rollup/plugins/blob/master/LICENSE\n */\nexport interface RollupCommonJSOptions {\n  /**\n   * A minimatch pattern, or array of patterns, which specifies the files in\n   * the build the plugin should operate on. By default, all files with\n   * extension `\".cjs\"` or those in `extensions` are included, but you can\n   * narrow this list by only including specific files. These files will be\n   * analyzed and transpiled if either the analysis does not find ES module\n   * specific statements or `transformMixedEsModules` is `true`.\n   * @default undefined\n   */\n  include?: string | RegExp | readonly (string | RegExp)[]\n  /**\n   * A minimatch pattern, or array of patterns, which specifies the files in\n   * the build the plugin should _ignore_. By default, all files with\n   * extensions other than those in `extensions` or `\".cjs\"` are ignored, but you\n   * can exclude additional files. See also the `include` option.\n   * @default undefined\n   */\n  exclude?: string | RegExp | readonly (string | RegExp)[]\n  /**\n   * For extensionless imports, search for extensions other than .js in the\n   * order specified. Note that you need to make sure that non-JavaScript files\n   * are transpiled by another plugin first.\n   * @default [ '.js' ]\n   */\n  extensions?: ReadonlyArray<string>\n  /**\n   * If true then uses of `global` won't be dealt with by this plugin\n   * @default false\n   */\n  ignoreGlobal?: boolean\n  /**\n   * If false, skips source map generation for CommonJS modules. This will\n   * improve performance.\n   * @default true\n   */\n  sourceMap?: boolean\n  /**\n   * Some `require` calls cannot be resolved statically to be translated to\n   * imports.\n   * When this option is set to `false`, the generated code will either\n   * directly throw an error when such a call is encountered or, when\n   * `dynamicRequireTargets` is used, when such a call cannot be resolved with a\n   * configured dynamic require target.\n   * Setting this option to `true` will instead leave the `require` call in the\n   * code or use it as a fallback for `dynamicRequireTargets`.\n   * @default false\n   */\n  ignoreDynamicRequires?: boolean\n  /**\n   * Instructs the plugin whether to enable mixed module transformations. This\n   * is useful in scenarios with modules that contain a mix of ES `import`\n   * statements and CommonJS `require` expressions. Set to `true` if `require`\n   * calls should be transformed to imports in mixed modules, or `false` if the\n   * `require` expressions should survive the transformation. The latter can be\n   * important if the code contains environment detection, or you are coding\n   * for an environment with special treatment for `require` calls such as\n   * ElectronJS. See also the `ignore` option.\n   * @default false\n   */\n  transformMixedEsModules?: boolean\n  /**\n   * By default, this plugin will try to hoist `require` statements as imports\n   * to the top of each file. While this works well for many code bases and\n   * allows for very efficient ESM output, it does not perfectly capture\n   * CommonJS semantics as the order of side effects like log statements may\n   * change. But it is especially problematic when there are circular `require`\n   * calls between CommonJS modules as those often rely on the lazy execution of\n   * nested `require` calls.\n   *\n   * Setting this option to `true` will wrap all CommonJS files in functions\n   * which are executed when they are required for the first time, preserving\n   * NodeJS semantics. Note that this can have an impact on the size and\n   * performance of the generated code.\n   *\n   * The default value of `\"auto\"` will only wrap CommonJS files when they are\n   * part of a CommonJS dependency cycle, e.g. an index file that is required by\n   * many of its dependencies. All other CommonJS files are hoisted. This is the\n   * recommended setting for most code bases.\n   *\n   * `false` will entirely prevent wrapping and hoist all files. This may still\n   * work depending on the nature of cyclic dependencies but will often cause\n   * problems.\n   *\n   * You can also provide a minimatch pattern, or array of patterns, to only\n   * specify a subset of files which should be wrapped in functions for proper\n   * `require` semantics.\n   *\n   * `\"debug\"` works like `\"auto\"` but after bundling, it will display a warning\n   * containing a list of ids that have been wrapped which can be used as\n   * minimatch pattern for fine-tuning.\n   * @default \"auto\"\n   */\n  strictRequires?: boolean | string | RegExp | readonly (string | RegExp)[]\n  /**\n   * Sometimes you have to leave require statements unconverted. Pass an array\n   * containing the IDs or a `id => boolean` function.\n   * @default []\n   */\n  ignore?: ReadonlyArray<string> | ((id: string) => boolean)\n  /**\n   * In most cases, where `require` calls are inside a `try-catch` clause,\n   * they should be left unconverted as it requires an optional dependency\n   * that may or may not be installed beside the rolled up package.\n   * Due to the conversion of `require` to a static `import` - the call is\n   * hoisted to the top of the file, outside the `try-catch` clause.\n   *\n   * - `true`: Default. All `require` calls inside a `try` will be left unconverted.\n   * - `false`: All `require` calls inside a `try` will be converted as if the\n   *   `try-catch` clause is not there.\n   * - `remove`: Remove all `require` calls from inside any `try` block.\n   * - `string[]`: Pass an array containing the IDs to left unconverted.\n   * - `((id: string) => boolean|'remove')`: Pass a function that controls\n   *   individual IDs.\n   *\n   * @default true\n   */\n  ignoreTryCatch?:\n    | boolean\n    | 'remove'\n    | ReadonlyArray<string>\n    | ((id: string) => boolean | 'remove')\n  /**\n   * Controls how to render imports from external dependencies. By default,\n   * this plugin assumes that all external dependencies are CommonJS. This\n   * means they are rendered as default imports to be compatible with e.g.\n   * NodeJS where ES modules can only import a default export from a CommonJS\n   * dependency.\n   *\n   * If you set `esmExternals` to `true`, this plugin assumes that all\n   * external dependencies are ES modules and respect the\n   * `requireReturnsDefault` option. If that option is not set, they will be\n   * rendered as namespace imports.\n   *\n   * You can also supply an array of ids to be treated as ES modules, or a\n   * function that will be passed each external id to determine whether it is\n   * an ES module.\n   * @default false\n   */\n  esmExternals?: boolean | ReadonlyArray<string> | ((id: string) => boolean)\n  /**\n   * Controls what is returned when requiring an ES module from a CommonJS file.\n   * When using the `esmExternals` option, this will also apply to external\n   * modules. By default, this plugin will render those imports as namespace\n   * imports i.e.\n   *\n   * ```js\n   * // input\n   * const foo = require('foo');\n   *\n   * // output\n   * import * as foo from 'foo';\n   * ```\n   *\n   * However, there are some situations where this may not be desired.\n   * For these situations, you can change Rollup's behaviour either globally or\n   * per module. To change it globally, set the `requireReturnsDefault` option\n   * to one of the following values:\n   *\n   * - `false`: This is the default, requiring an ES module returns its\n   *   namespace. This is the only option that will also add a marker\n   *   `__esModule: true` to the namespace to support interop patterns in\n   *   CommonJS modules that are transpiled ES modules.\n   * - `\"namespace\"`: Like `false`, requiring an ES module returns its\n   *   namespace, but the plugin does not add the `__esModule` marker and thus\n   *   creates more efficient code. For external dependencies when using\n   *   `esmExternals: true`, no additional interop code is generated.\n   * - `\"auto\"`: This is complementary to how `output.exports: \"auto\"` works in\n   *   Rollup: If a module has a default export and no named exports, requiring\n   *   that module returns the default export. In all other cases, the namespace\n   *   is returned. For external dependencies when using `esmExternals: true`, a\n   *   corresponding interop helper is added.\n   * - `\"preferred\"`: If a module has a default export, requiring that module\n   *   always returns the default export, no matter whether additional named\n   *   exports exist. This is similar to how previous versions of this plugin\n   *   worked. Again for external dependencies when using `esmExternals: true`,\n   *   an interop helper is added.\n   * - `true`: This will always try to return the default export on require\n   *   without checking if it actually exists. This can throw at build time if\n   *   there is no default export. This is how external dependencies are handled\n   *   when `esmExternals` is not used. The advantage over the other options is\n   *   that, like `false`, this does not add an interop helper for external\n   *   dependencies, keeping the code lean.\n   *\n   * To change this for individual modules, you can supply a function for\n   * `requireReturnsDefault` instead. This function will then be called once for\n   * each required ES module or external dependency with the corresponding id\n   * and allows you to return different values for different modules.\n   * @default false\n   */\n  requireReturnsDefault?:\n    | boolean\n    | 'auto'\n    | 'preferred'\n    | 'namespace'\n    | ((id: string) => boolean | 'auto' | 'preferred' | 'namespace')\n\n  /**\n   * @default \"auto\"\n   */\n  defaultIsModuleExports?: boolean | 'auto' | ((id: string) => boolean | 'auto')\n  /**\n   * Some modules contain dynamic `require` calls, or require modules that\n   * contain circular dependencies, which are not handled well by static\n   * imports. Including those modules as `dynamicRequireTargets` will simulate a\n   * CommonJS (NodeJS-like) environment for them with support for dynamic\n   * dependencies. It also enables `strictRequires` for those modules.\n   *\n   * Note: In extreme cases, this feature may result in some paths being\n   * rendered as absolute in the final bundle. The plugin tries to avoid\n   * exposing paths from the local machine, but if you are `dynamicRequirePaths`\n   * with paths that are far away from your project's folder, that may require\n   * replacing strings like `\"/Users/John/Desktop/foo-project/\"` -\\> `\"/\"`.\n   */\n  dynamicRequireTargets?: string | ReadonlyArray<string>\n  /**\n   * To avoid long paths when using the `dynamicRequireTargets` option, you can use this option to specify a directory\n   * that is a common parent for all files that use dynamic require statements. Using a directory higher up such as `/`\n   * may lead to unnecessarily long paths in the generated code and may expose directory names on your machine like your\n   * home directory name. By default, it uses the current working directory.\n   */\n  dynamicRequireRoot?: string\n}\n"
  },
  {
    "path": "packages/vite/src/types/connect.d.ts",
    "content": "// Inlined to avoid extra dependency\n// MIT Licensed https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/LICENSE\n\n// Type definitions for connect v3.4.0\n// Project: https://github.com/senchalabs/connect\n// Definitions by: Maxime LUCE <https://github.com/SomaticIT>\n//                 Evan Hahn <https://github.com/EvanHahn>\n// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped\n\n/// <reference types=\"node\" />\nimport * as http from 'node:http'\n\nexport namespace Connect {\n  export type ServerHandle = HandleFunction | http.Server\n\n  export class IncomingMessage extends http.IncomingMessage {\n    originalUrl?: http.IncomingMessage['url'] | undefined\n  }\n\n  export type NextFunction = (err?: any) => void\n\n  export type SimpleHandleFunction = (\n    req: IncomingMessage,\n    res: http.ServerResponse,\n  ) => void\n  export type NextHandleFunction = (\n    req: IncomingMessage,\n    res: http.ServerResponse,\n    next: NextFunction,\n  ) => void\n  export type ErrorHandleFunction = (\n    err: any,\n    req: IncomingMessage,\n    res: http.ServerResponse,\n    next: NextFunction,\n  ) => void\n  export type HandleFunction =\n    | SimpleHandleFunction\n    | NextHandleFunction\n    | ErrorHandleFunction\n\n  export interface ServerStackItem {\n    route: string\n    handle: ServerHandle\n  }\n\n  export interface Server extends NodeJS.EventEmitter {\n    (req: http.IncomingMessage, res: http.ServerResponse, next?: Function): void\n\n    route: string\n    stack: ServerStackItem[]\n\n    /**\n     * Utilize the given middleware `handle` to the given `route`,\n     * defaulting to _/_. This \"route\" is the mount-point for the\n     * middleware, when given a value other than _/_ the middleware\n     * is only effective when that segment is present in the request's\n     * pathname.\n     *\n     * For example if we were to mount a function at _/admin_, it would\n     * be invoked on _/admin_, and _/admin/settings_, however it would\n     * not be invoked for _/_, or _/posts_.\n     */\n    use(fn: NextHandleFunction): Server\n    use(fn: HandleFunction): Server\n    use(route: string, fn: NextHandleFunction): Server\n    use(route: string, fn: HandleFunction): Server\n\n    /**\n     * Handle server requests, punting them down\n     * the middleware stack.\n     */\n    handle(\n      req: http.IncomingMessage,\n      res: http.ServerResponse,\n      next: Function,\n    ): void\n\n    /**\n     * Listen for connections.\n     *\n     * This method takes the same arguments\n     * as node's `http.Server#listen()`.\n     *\n     * HTTP and HTTPS:\n     *\n     * If you run your application both as HTTP\n     * and HTTPS you may wrap them individually,\n     * since your Connect \"server\" is really just\n     * a JavaScript `Function`.\n     *\n     *      var connect = require('connect')\n     *        , http = require('http')\n     *        , https = require('https');\n     *\n     *      var app = connect();\n     *\n     *      http.createServer(app).listen(80);\n     *      https.createServer(options, app).listen(443);\n     */\n    listen(\n      port: number,\n      hostname?: string,\n      backlog?: number,\n      callback?: Function,\n    ): http.Server\n    listen(port: number, hostname?: string, callback?: Function): http.Server\n    listen(path: string, callback?: Function): http.Server\n    listen(handle: any, listeningListener?: Function): http.Server\n  }\n}\n"
  },
  {
    "path": "packages/vite/src/types/dynamicImportVars.d.ts",
    "content": "export interface RollupDynamicImportVarsOptions {\n  /**\n   * Files to include in this plugin (default all).\n   * @default []\n   */\n  include?: string | RegExp | (string | RegExp)[]\n  /**\n   * Files to exclude in this plugin (default none).\n   * @default []\n   */\n  exclude?: string | RegExp | (string | RegExp)[]\n  /**\n   * @deprecated This option is no-op and will be removed in future versions.\n   */\n  warnOnError?: boolean\n}\n"
  },
  {
    "path": "packages/vite/src/types/package.json",
    "content": "{\n  \"//\": \"this file is just here to make pnpm happy with --frozen-lockfile\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "packages/vite/src/types/shims.d.ts",
    "content": "declare module 'connect' {\n  const connect: () => any\n  export = connect\n}\n\ndeclare module 'cors' {\n  function cors(options: any): any\n  export = cors\n}\n\ndeclare module 'launch-editor-middleware' {\n  const plugin: any\n  export = plugin\n}\n\ndeclare module 'postcss-import' {\n  import type { Plugin } from 'postcss'\n  const plugin: (options: {\n    resolve: (\n      id: string,\n      basedir: string,\n      importOptions: any,\n    ) => string | string[] | Promise<string | string[]>\n    load: (id: string) => Promise<string>\n    nameLayer: (index: number, rootFilename: string) => string\n  }) => Plugin\n  export = plugin\n}\n\n// eslint-disable-next-line no-var\ndeclare var __vite_profile_session: import('node:inspector').Session | undefined\n// eslint-disable-next-line no-var\ndeclare var __vite_start_time: number | undefined\n"
  },
  {
    "path": "packages/vite/src/types/ws.d.ts",
    "content": "// Modified and inlined to avoid extra dependency\n// Source: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/ws/index.d.ts\n\n// Type definitions for ws 8.5\n// Project: https://github.com/websockets/ws\n// Definitions by: Paul Loyd <https://github.com/loyd>\n//                 Margus Lamp <https://github.com/mlamp>\n//                 Philippe D'Alva <https://github.com/TitaneBoy>\n//                 reduckted <https://github.com/reduckted>\n//                 teidesu <https://github.com/teidesu>\n//                 Bartosz Wojtkowiak <https://github.com/wojtkowiak>\n//                 Kyle Hensel <https://github.com/k-yle>\n//                 Samuel Skeen <https://github.com/cwadrupldijjit>\n// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped\n\n/// <reference types=\"node\" />\n\nimport { EventEmitter } from 'node:events'\nimport type {\n  Agent,\n  ClientRequest,\n  ClientRequestArgs,\n  Server as HTTPServer,\n  IncomingMessage,\n  OutgoingHttpHeaders,\n} from 'node:http'\nimport type { Server as HTTPSServer } from 'node:https'\nimport type { Duplex, DuplexOptions } from 'node:stream'\nimport type { SecureContextOptions } from 'node:tls'\nimport type { URL } from 'node:url'\nimport type { ZlibOptions } from 'node:zlib'\n\n// WebSocket socket.\ndeclare class WebSocket extends EventEmitter {\n  /** The connection is not yet open. */\n  static readonly CONNECTING: 0\n  /** The connection is open and ready to communicate. */\n  static readonly OPEN: 1\n  /** The connection is in the process of closing. */\n  static readonly CLOSING: 2\n  /** The connection is closed. */\n  static readonly CLOSED: 3\n\n  binaryType: 'nodebuffer' | 'arraybuffer' | 'fragments'\n  readonly bufferedAmount: number\n  readonly extensions: string\n  /** Indicates whether the websocket is paused */\n  readonly isPaused: boolean\n  readonly protocol: string\n  /** The current state of the connection */\n  readonly readyState:\n    | typeof WebSocket.CONNECTING\n    | typeof WebSocket.OPEN\n    | typeof WebSocket.CLOSING\n    | typeof WebSocket.CLOSED\n  readonly url: string\n\n  /** The connection is not yet open. */\n  readonly CONNECTING: 0\n  /** The connection is open and ready to communicate. */\n  readonly OPEN: 1\n  /** The connection is in the process of closing. */\n  readonly CLOSING: 2\n  /** The connection is closed. */\n  readonly CLOSED: 3\n\n  onopen: ((event: WebSocket.Event) => void) | null\n  onerror: ((event: WebSocket.ErrorEvent) => void) | null\n  onclose: ((event: WebSocket.CloseEvent) => void) | null\n  onmessage: ((event: WebSocket.MessageEvent) => void) | null\n\n  constructor(address: null)\n  constructor(\n    address: string | URL,\n    options?: WebSocket.ClientOptions | ClientRequestArgs,\n  )\n  constructor(\n    address: string | URL,\n    protocols?: string | string[],\n    options?: WebSocket.ClientOptions | ClientRequestArgs,\n  )\n\n  close(code?: number, data?: string | Buffer): void\n  ping(data?: any, mask?: boolean, cb?: (err: Error) => void): void\n  pong(data?: any, mask?: boolean, cb?: (err: Error) => void): void\n  send(data: any, cb?: (err?: Error) => void): void\n  send(\n    data: any,\n    options: {\n      mask?: boolean | undefined\n      binary?: boolean | undefined\n      compress?: boolean | undefined\n      fin?: boolean | undefined\n    },\n    cb?: (err?: Error) => void,\n  ): void\n  terminate(): void\n\n  /**\n   * Pause the websocket causing it to stop emitting events. Some events can still be\n   * emitted after this is called, until all buffered data is consumed. This method\n   * is a noop if the ready state is `CONNECTING` or `CLOSED`.\n   */\n  pause(): void\n  /**\n   * Make a paused socket resume emitting events. This method is a noop if the ready\n   * state is `CONNECTING` or `CLOSED`.\n   */\n  resume(): void\n\n  // HTML5 WebSocket events\n  addEventListener(\n    method: 'message',\n    cb: (event: WebSocket.MessageEvent) => void,\n    options?: WebSocket.EventListenerOptions,\n  ): void\n  addEventListener(\n    method: 'close',\n    cb: (event: WebSocket.CloseEvent) => void,\n    options?: WebSocket.EventListenerOptions,\n  ): void\n  addEventListener(\n    method: 'error',\n    cb: (event: WebSocket.ErrorEvent) => void,\n    options?: WebSocket.EventListenerOptions,\n  ): void\n  addEventListener(\n    method: 'open',\n    cb: (event: WebSocket.Event) => void,\n    options?: WebSocket.EventListenerOptions,\n  ): void\n\n  removeEventListener(\n    method: 'message',\n    cb: (event: WebSocket.MessageEvent) => void,\n  ): void\n  removeEventListener(\n    method: 'close',\n    cb: (event: WebSocket.CloseEvent) => void,\n  ): void\n  removeEventListener(\n    method: 'error',\n    cb: (event: WebSocket.ErrorEvent) => void,\n  ): void\n  removeEventListener(\n    method: 'open',\n    cb: (event: WebSocket.Event) => void,\n  ): void\n\n  // Events\n  on(\n    event: 'close',\n    listener: (this: WebSocket, code: number, reason: Buffer) => void,\n  ): this\n  on(event: 'error', listener: (this: WebSocket, err: Error) => void): this\n  on(\n    event: 'upgrade',\n    listener: (this: WebSocket, request: IncomingMessage) => void,\n  ): this\n  on(\n    event: 'message',\n    listener: (\n      this: WebSocket,\n      data: WebSocket.RawData,\n      isBinary: boolean,\n    ) => void,\n  ): this\n  on(event: 'open', listener: (this: WebSocket) => void): this\n  on(\n    event: 'ping' | 'pong',\n    listener: (this: WebSocket, data: Buffer) => void,\n  ): this\n  on(\n    event: 'unexpected-response',\n    listener: (\n      this: WebSocket,\n      request: ClientRequest,\n      response: IncomingMessage,\n    ) => void,\n  ): this\n  on(\n    event: string | symbol,\n    listener: (this: WebSocket, ...args: any[]) => void,\n  ): this\n\n  once(\n    event: 'close',\n    listener: (this: WebSocket, code: number, reason: Buffer) => void,\n  ): this\n  once(event: 'error', listener: (this: WebSocket, err: Error) => void): this\n  once(\n    event: 'upgrade',\n    listener: (this: WebSocket, request: IncomingMessage) => void,\n  ): this\n  once(\n    event: 'message',\n    listener: (\n      this: WebSocket,\n      data: WebSocket.RawData,\n      isBinary: boolean,\n    ) => void,\n  ): this\n  once(event: 'open', listener: (this: WebSocket) => void): this\n  once(\n    event: 'ping' | 'pong',\n    listener: (this: WebSocket, data: Buffer) => void,\n  ): this\n  once(\n    event: 'unexpected-response',\n    listener: (\n      this: WebSocket,\n      request: ClientRequest,\n      response: IncomingMessage,\n    ) => void,\n  ): this\n  once(\n    event: string | symbol,\n    listener: (this: WebSocket, ...args: any[]) => void,\n  ): this\n\n  off(\n    event: 'close',\n    listener: (this: WebSocket, code: number, reason: Buffer) => void,\n  ): this\n  off(event: 'error', listener: (this: WebSocket, err: Error) => void): this\n  off(\n    event: 'upgrade',\n    listener: (this: WebSocket, request: IncomingMessage) => void,\n  ): this\n  off(\n    event: 'message',\n    listener: (\n      this: WebSocket,\n      data: WebSocket.RawData,\n      isBinary: boolean,\n    ) => void,\n  ): this\n  off(event: 'open', listener: (this: WebSocket) => void): this\n  off(\n    event: 'ping' | 'pong',\n    listener: (this: WebSocket, data: Buffer) => void,\n  ): this\n  off(\n    event: 'unexpected-response',\n    listener: (\n      this: WebSocket,\n      request: ClientRequest,\n      response: IncomingMessage,\n    ) => void,\n  ): this\n  off(\n    event: string | symbol,\n    listener: (this: WebSocket, ...args: any[]) => void,\n  ): this\n\n  addListener(\n    event: 'close',\n    listener: (code: number, reason: Buffer) => void,\n  ): this\n  addListener(event: 'error', listener: (err: Error) => void): this\n  addListener(\n    event: 'upgrade',\n    listener: (request: IncomingMessage) => void,\n  ): this\n  addListener(\n    event: 'message',\n    listener: (data: WebSocket.RawData, isBinary: boolean) => void,\n  ): this\n  addListener(event: 'open', listener: () => void): this\n  addListener(event: 'ping' | 'pong', listener: (data: Buffer) => void): this\n  addListener(\n    event: 'unexpected-response',\n    listener: (request: ClientRequest, response: IncomingMessage) => void,\n  ): this\n  addListener(event: string | symbol, listener: (...args: any[]) => void): this\n\n  removeListener(\n    event: 'close',\n    listener: (code: number, reason: Buffer) => void,\n  ): this\n  removeListener(event: 'error', listener: (err: Error) => void): this\n  removeListener(\n    event: 'upgrade',\n    listener: (request: IncomingMessage) => void,\n  ): this\n  removeListener(\n    event: 'message',\n    listener: (data: WebSocket.RawData, isBinary: boolean) => void,\n  ): this\n  removeListener(event: 'open', listener: () => void): this\n  removeListener(event: 'ping' | 'pong', listener: (data: Buffer) => void): this\n  removeListener(\n    event: 'unexpected-response',\n    listener: (request: ClientRequest, response: IncomingMessage) => void,\n  ): this\n  removeListener(\n    event: string | symbol,\n    listener: (...args: any[]) => void,\n  ): this\n}\n\ndeclare const WebSocketAlias: typeof WebSocket\ninterface WebSocketAlias extends WebSocket {}\n\ndeclare namespace WebSocket {\n  /**\n   * Data represents the raw message payload received over the WebSocket.\n   */\n  type RawData = Buffer | ArrayBuffer | Buffer[]\n\n  /**\n   * Data represents the message payload received over the WebSocket.\n   */\n  type Data = string | Buffer | ArrayBuffer | Buffer[]\n\n  /**\n   * CertMeta represents the accepted types for certificate & key data.\n   */\n  type CertMeta = string | string[] | Buffer | Buffer[]\n\n  /**\n   * VerifyClientCallbackSync is a synchronous callback used to inspect the\n   * incoming message. The return value (boolean) of the function determines\n   * whether or not to accept the handshake.\n   */\n  type VerifyClientCallbackSync = (info: {\n    origin: string\n    secure: boolean\n    req: IncomingMessage\n  }) => boolean\n\n  /**\n   * VerifyClientCallbackAsync is an asynchronous callback used to inspect the\n   * incoming message. The return value (boolean) of the function determines\n   * whether or not to accept the handshake.\n   */\n  type VerifyClientCallbackAsync = (\n    info: { origin: string; secure: boolean; req: IncomingMessage },\n    callback: (\n      res: boolean,\n      code?: number,\n      message?: string,\n      headers?: OutgoingHttpHeaders,\n    ) => void,\n  ) => void\n\n  interface ClientOptions extends SecureContextOptions {\n    protocol?: string | undefined\n    followRedirects?: boolean | undefined\n    generateMask?(mask: Buffer): void\n    handshakeTimeout?: number | undefined\n    maxRedirects?: number | undefined\n    perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined\n    localAddress?: string | undefined\n    protocolVersion?: number | undefined\n    headers?: { [key: string]: string } | undefined\n    origin?: string | undefined\n    agent?: Agent | undefined\n    host?: string | undefined\n    family?: number | undefined\n    checkServerIdentity?(servername: string, cert: CertMeta): boolean\n    rejectUnauthorized?: boolean | undefined\n    maxPayload?: number | undefined\n    skipUTF8Validation?: boolean | undefined\n  }\n\n  interface PerMessageDeflateOptions {\n    serverNoContextTakeover?: boolean | undefined\n    clientNoContextTakeover?: boolean | undefined\n    serverMaxWindowBits?: number | undefined\n    clientMaxWindowBits?: number | undefined\n    zlibDeflateOptions?:\n      | {\n          flush?: number | undefined\n          finishFlush?: number | undefined\n          chunkSize?: number | undefined\n          windowBits?: number | undefined\n          level?: number | undefined\n          memLevel?: number | undefined\n          strategy?: number | undefined\n          dictionary?: Buffer | Buffer[] | DataView | undefined\n          info?: boolean | undefined\n        }\n      | undefined\n    zlibInflateOptions?: ZlibOptions | undefined\n    threshold?: number | undefined\n    concurrencyLimit?: number | undefined\n  }\n\n  interface Event {\n    type: string\n    target: WebSocket\n  }\n\n  interface ErrorEvent {\n    error: any\n    message: string\n    type: string\n    target: WebSocket\n  }\n\n  interface CloseEvent {\n    wasClean: boolean\n    code: number\n    reason: string\n    type: string\n    target: WebSocket\n  }\n\n  interface MessageEvent {\n    data: Data\n    type: string\n    target: WebSocket\n  }\n\n  interface EventListenerOptions {\n    once?: boolean | undefined\n  }\n\n  interface ServerOptions {\n    host?: string | undefined\n    port?: number | undefined\n    backlog?: number | undefined\n    server?: HTTPServer | HTTPSServer | undefined\n    verifyClient?:\n      | VerifyClientCallbackAsync\n      | VerifyClientCallbackSync\n      | undefined\n    handleProtocols?: (\n      protocols: Set<string>,\n      request: IncomingMessage,\n    ) => string | false\n    path?: string | undefined\n    noServer?: boolean | undefined\n    clientTracking?: boolean | undefined\n    perMessageDeflate?: boolean | PerMessageDeflateOptions | undefined\n    maxPayload?: number | undefined\n    skipUTF8Validation?: boolean | undefined\n    WebSocket?: typeof WebSocket.WebSocket | undefined\n  }\n\n  interface AddressInfo {\n    address: string\n    family: string\n    port: number\n  }\n\n  // WebSocket Server\n  class Server<T extends WebSocket = WebSocket> extends EventEmitter {\n    options: ServerOptions\n    path: string\n    clients: Set<T>\n\n    constructor(options?: ServerOptions, callback?: () => void)\n\n    address(): AddressInfo | string\n    close(cb?: (err?: Error) => void): void\n    handleUpgrade(\n      request: IncomingMessage,\n      socket: Duplex,\n      upgradeHead: Buffer,\n      callback: (client: T, request: IncomingMessage) => void,\n    ): void\n    shouldHandle(request: IncomingMessage): boolean | Promise<boolean>\n\n    // Events\n    on(\n      event: 'connection',\n      cb: (this: Server<T>, socket: T, request: IncomingMessage) => void,\n    ): this\n    on(event: 'error', cb: (this: Server<T>, error: Error) => void): this\n    on(\n      event: 'headers',\n      cb: (\n        this: Server<T>,\n        headers: string[],\n        request: IncomingMessage,\n      ) => void,\n    ): this\n    on(event: 'close' | 'listening', cb: (this: Server<T>) => void): this\n    on(\n      event: string | symbol,\n      listener: (this: Server<T>, ...args: any[]) => void,\n    ): this\n\n    once(\n      event: 'connection',\n      cb: (this: Server<T>, socket: T, request: IncomingMessage) => void,\n    ): this\n    once(event: 'error', cb: (this: Server<T>, error: Error) => void): this\n    once(\n      event: 'headers',\n      cb: (\n        this: Server<T>,\n        headers: string[],\n        request: IncomingMessage,\n      ) => void,\n    ): this\n    once(event: 'close' | 'listening', cb: (this: Server<T>) => void): this\n    once(\n      event: string | symbol,\n      listener: (this: Server<T>, ...args: any[]) => void,\n    ): this\n\n    off(\n      event: 'connection',\n      cb: (this: Server<T>, socket: T, request: IncomingMessage) => void,\n    ): this\n    off(event: 'error', cb: (this: Server<T>, error: Error) => void): this\n    off(\n      event: 'headers',\n      cb: (\n        this: Server<T>,\n        headers: string[],\n        request: IncomingMessage,\n      ) => void,\n    ): this\n    off(event: 'close' | 'listening', cb: (this: Server<T>) => void): this\n    off(\n      event: string | symbol,\n      listener: (this: Server<T>, ...args: any[]) => void,\n    ): this\n\n    addListener(\n      event: 'connection',\n      cb: (client: T, request: IncomingMessage) => void,\n    ): this\n    addListener(event: 'error', cb: (err: Error) => void): this\n    addListener(\n      event: 'headers',\n      cb: (headers: string[], request: IncomingMessage) => void,\n    ): this\n    addListener(event: 'close' | 'listening', cb: () => void): this\n    addListener(\n      event: string | symbol,\n      listener: (...args: any[]) => void,\n    ): this\n\n    removeListener(event: 'connection', cb: (client: T) => void): this\n    removeListener(event: 'error', cb: (err: Error) => void): this\n    removeListener(\n      event: 'headers',\n      cb: (headers: string[], request: IncomingMessage) => void,\n    ): this\n    removeListener(event: 'close' | 'listening', cb: () => void): this\n    removeListener(\n      event: string | symbol,\n      listener: (...args: any[]) => void,\n    ): this\n  }\n\n  const WebSocketServer: typeof Server\n  interface WebSocketServer extends Server {}\n  const WebSocket: typeof WebSocketAlias\n  interface WebSocket extends WebSocketAlias {}\n\n  // WebSocket stream\n  function createWebSocketStream(\n    websocket: WebSocket,\n    options?: DuplexOptions,\n  ): Duplex\n}\n\n// export = WebSocket\nexport { WebSocket, WebSocketAlias }\n"
  },
  {
    "path": "packages/vite/tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"target\": \"ES2023\",\n    \"module\": \"Preserve\",\n    \"types\": [\"node\"],\n    \"noEmit\": true,\n    \"moduleResolution\": \"bundler\",\n    \"isolatedDeclarations\": true,\n    \"declaration\": true,\n    \"strict\": true,\n    \"noImplicitOverride\": true,\n    \"noUnusedLocals\": true,\n    \"esModuleInterop\": true,\n    \"useUnknownInCatchVariables\": false\n  }\n}\n"
  },
  {
    "path": "packages/vite/tsconfig.check.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"moduleResolution\": \"node16\",\n    \"module\": \"Node16\",\n    \"lib\": [\"ES2020\"], // ES2020 is very conservative check for client types, could be bumped if needed\n    \"types\": [], // Avoid checking unrelated node_modules types\n    \"noEmit\": true,\n    \"strict\": true,\n    \"noUncheckedSideEffectImports\": true,\n    \"exactOptionalPropertyTypes\": true\n  },\n  \"include\": [\n    // dist\n    \"dist/**/*\",\n    \"types/**/*\"\n  ]\n}\n"
  },
  {
    "path": "packages/vite/tsconfig.json",
    "content": "{\n  \"extends\": \"./tsconfig.base.json\",\n  \"include\": [\"rolldown.config.ts\", \"rolldown.dts.config.ts\", \"scripts\"],\n  \"compilerOptions\": {\n    \"esModuleInterop\": true,\n    \"isolatedDeclarations\": false,\n    \"declaration\": false,\n    \"resolveJsonModule\": true\n  }\n}\n"
  },
  {
    "path": "packages/vite/types/customEvent.d.ts",
    "content": "import type {\n  ErrorPayload,\n  FullReloadPayload,\n  PrunePayload,\n  UpdatePayload,\n} from './hmrPayload.js'\n\nexport interface CustomEventMap {\n  // client events\n  'vite:beforeUpdate': UpdatePayload\n  'vite:afterUpdate': UpdatePayload\n  'vite:beforePrune': PrunePayload\n  'vite:beforeFullReload': FullReloadPayload\n  'vite:error': ErrorPayload\n  'vite:invalidate': InvalidatePayload\n  'vite:ws:connect': WebSocketConnectionPayload\n  'vite:ws:disconnect': WebSocketConnectionPayload\n  /** @internal */\n  'vite:forward-console': ForwardConsolePayload\n  /** @internal */\n  'vite:module-loaded': { modules: string[] }\n\n  // server events\n  'vite:client:connect': undefined\n  'vite:client:disconnect': undefined\n}\n\nexport interface WebSocketConnectionPayload {\n  /**\n   * @experimental\n   * We expose this instance experimentally to see potential usage.\n   * This might be removed in the future if we didn't find reasonable use cases.\n   * If you find this useful, please open an issue with details so we can discuss and make it stable API.\n   */\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  webSocket: WebSocket\n}\n\nexport interface InvalidatePayload {\n  path: string\n  message: string | undefined\n  firstInvalidatedBy: string\n}\n\nexport type ForwardConsolePayload =\n  | {\n      type: 'error'\n      data: {\n        name: string\n        message: string\n        stack?: string\n      }\n    }\n  | {\n      type: 'unhandled-rejection'\n      data: {\n        name: string\n        message: string\n        stack?: string\n      }\n    }\n  | {\n      type: 'log'\n      data: {\n        level: string\n        message: string\n      }\n    }\n\n/**\n * provides types for payloads of built-in Vite events\n */\nexport type InferCustomEventPayload<T extends string> =\n  T extends keyof CustomEventMap ? CustomEventMap[T] : any\n\n/**\n * provides types for names of built-in Vite events\n */\nexport type CustomEventName = keyof CustomEventMap | (string & {})\n"
  },
  {
    "path": "packages/vite/types/hmrPayload.d.ts",
    "content": "/** @deprecated use HotPayload */\nexport type HMRPayload = HotPayload\nexport type HotPayload =\n  | ConnectedPayload\n  | PingPayload\n  | UpdatePayload\n  | FullReloadPayload\n  | CustomPayload\n  | ErrorPayload\n  | PrunePayload\n\nexport interface ConnectedPayload {\n  type: 'connected'\n}\n\nexport interface PingPayload {\n  type: 'ping'\n}\n\nexport interface UpdatePayload {\n  type: 'update'\n  updates: Update[]\n}\n\nexport interface Update {\n  type: 'js-update' | 'css-update'\n  /**\n   * URL of HMR patch chunk\n   *\n   * This only exists when full-bundle mode is enabled.\n   */\n  url?: string\n  path: string\n  acceptedPath: string\n  timestamp: number\n  /** @internal */\n  explicitImportRequired?: boolean\n  /** @internal */\n  isWithinCircularImport?: boolean\n  /** @internal */\n  firstInvalidatedBy?: string\n  /** @internal */\n  invalidates?: string[]\n}\n\nexport interface PrunePayload {\n  type: 'prune'\n  paths: string[]\n}\n\nexport interface FullReloadPayload {\n  type: 'full-reload'\n  path?: string\n  /** @internal */\n  triggeredBy?: string\n}\n\nexport interface CustomPayload {\n  type: 'custom'\n  event: string\n  data?: any\n}\n\nexport interface ErrorPayload {\n  type: 'error'\n  err: {\n    [name: string]: any\n    message: string\n    stack: string\n    id?: string\n    frame?: string\n    plugin?: string\n    pluginCode?: string\n    loc?: {\n      file?: string\n      line: number\n      column: number\n    }\n  }\n}\n"
  },
  {
    "path": "packages/vite/types/hot.d.ts",
    "content": "import type { CustomEventName, InferCustomEventPayload } from './customEvent.js'\n\nexport type ModuleNamespace = Record<string, any> & {\n  [Symbol.toStringTag]: 'Module'\n}\n\nexport interface ViteHotContext {\n  readonly data: any\n\n  accept(): void\n  accept(cb: (mod: ModuleNamespace | undefined) => void): void\n  accept(dep: string, cb: (mod: ModuleNamespace | undefined) => void): void\n  accept(\n    deps: readonly string[],\n    cb: (mods: Array<ModuleNamespace | undefined>) => void,\n  ): void\n\n  acceptExports(\n    exportNames: string | readonly string[],\n    cb?: (mod: ModuleNamespace | undefined) => void,\n  ): void\n\n  dispose(cb: (data: any) => void): void\n  prune(cb: (data: any) => void): void\n  invalidate(message?: string): void\n\n  on<T extends CustomEventName>(\n    event: T,\n    cb: (payload: InferCustomEventPayload<T>) => void,\n  ): void\n  off<T extends CustomEventName>(\n    event: T,\n    cb: (payload: InferCustomEventPayload<T>) => void,\n  ): void\n  send<T extends CustomEventName>(\n    event: T,\n    data?: InferCustomEventPayload<T>,\n  ): void\n}\n"
  },
  {
    "path": "packages/vite/types/import-meta.d.ts",
    "content": "/// <reference path=\"./importMeta.d.ts\" />\n\n// https://github.com/microsoft/TypeScript/issues/45096\n// TypeScript has a bug that makes <reference types=\"vite/types/importMeta\" />\n// not possible in userland. This file provides a workaround for now.\n"
  },
  {
    "path": "packages/vite/types/importGlob.d.ts",
    "content": "export interface ImportGlobOptions<\n  Eager extends boolean,\n  AsType extends string,\n> {\n  /**\n   * Import type for the import url.\n   *\n   * @deprecated Use `query` instead, e.g. `as: 'url'` -> `query: '?url', import: 'default'`\n   */\n  as?: AsType\n  /**\n   * Import as static or dynamic\n   *\n   * @default false\n   */\n  eager?: Eager\n  /**\n   * Import only the specific named export. Set to `default` to import the default export.\n   */\n  import?: string\n  /**\n   * Custom queries\n   */\n  query?: string | Record<string, string | number | boolean>\n  /**\n   * Search files also inside `node_modules/` and hidden directories (e.g. `.git/`). This might have impact on performance.\n   *\n   * @default false\n   */\n  exhaustive?: boolean\n  /**\n   * Base path to resolve relative paths.\n   */\n  base?: string\n}\n\nexport type GeneralImportGlobOptions = ImportGlobOptions<boolean, string>\n\n/**\n * Declare Worker in case DOM is not added to the tsconfig lib causing\n * Worker interface is not defined. For developers with DOM lib added,\n * the Worker interface will be merged correctly.\n */\ndeclare global {\n  // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n  interface Worker {}\n}\n\nexport interface KnownAsTypeMap {\n  raw: string\n  url: string\n  worker: Worker\n}\n\nexport interface ImportGlobFunction {\n  /**\n   * Import a list of files with a glob pattern.\n   *\n   * Overload 1: No generic provided, infer the type from `eager` and `as`\n   */\n  <\n    Eager extends boolean,\n    As extends string,\n    T = As extends keyof KnownAsTypeMap ? KnownAsTypeMap[As] : unknown,\n  >(\n    glob: string | string[],\n    options?: ImportGlobOptions<Eager, As>,\n  ): (Eager extends true ? true : false) extends true\n    ? Record<string, T>\n    : Record<string, () => Promise<T>>\n  /**\n   * Import a list of files with a glob pattern.\n   *\n   * Overload 2: Module generic provided, infer the type from `eager: false`\n   */\n  <M>(\n    glob: string | string[],\n    options?: ImportGlobOptions<false, string>,\n  ): Record<string, () => Promise<M>>\n  /**\n   * Import a list of files with a glob pattern.\n   *\n   * Overload 3: Module generic provided, infer the type from `eager: true`\n   */\n  <M>(\n    glob: string | string[],\n    options: ImportGlobOptions<true, string>,\n  ): Record<string, M>\n}\n"
  },
  {
    "path": "packages/vite/types/importMeta.d.ts",
    "content": "// This file is an augmentation to the built-in ImportMeta interface\n// Thus cannot contain any top-level imports\n// <https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation>\n\n// This is tested in `packages/vite/src/node/__tests_dts__/typeOptions.ts`\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- to allow extending by users\ninterface ViteTypeOptions {\n  // strictImportMetaEnv: unknown\n}\n\ntype ImportMetaEnvFallbackKey =\n  'strictImportMetaEnv' extends keyof ViteTypeOptions ? never : string\n\ninterface ImportMetaEnv extends Record<ImportMetaEnvFallbackKey, any> {\n  BASE_URL: string\n  MODE: string\n  DEV: boolean\n  PROD: boolean\n  SSR: boolean\n}\n\ninterface ImportMeta {\n  url: string\n\n  readonly hot?: import('./hot.js').ViteHotContext\n\n  readonly env: ImportMetaEnv\n\n  glob: import('./importGlob.js').ImportGlobFunction\n}\n"
  },
  {
    "path": "packages/vite/types/internal/cssPreprocessorOptions.d.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\n\n// @ts-ignore `sass` may not be installed\nimport type DartSass from 'sass'\n// @ts-ignore `sass-embedded` may not be installed\nimport type SassEmbedded from 'sass-embedded'\n// @ts-ignore `less` may not be installed\nimport type Less from 'less'\n// @ts-ignore `stylus` may not be installed\nimport type Stylus from 'stylus'\n\n/* eslint-enable @typescript-eslint/ban-ts-comment */\n\n// https://github.com/type-challenges/type-challenges/issues/29285\ntype IsAny<T> = boolean extends (T extends never ? true : false) ? true : false\n\ntype DartSassStringOptionsAsync = DartSass.StringOptions<'async'>\ntype SassEmbeddedStringOptionsAsync = SassEmbedded.StringOptions<'async'>\ntype SassStringOptionsAsync =\n  IsAny<SassEmbeddedStringOptionsAsync> extends false\n    ? SassEmbeddedStringOptionsAsync\n    : DartSassStringOptionsAsync\n\nexport type SassModernPreprocessBaseOptions = Omit<\n  SassStringOptionsAsync,\n  'url' | 'sourceMap'\n>\n\nexport type LessPreprocessorBaseOptions = Omit<\n  Less.Options,\n  'sourceMap' | 'filename'\n>\n\nexport type StylusPreprocessorBaseOptions = Omit<\n  Stylus.RenderOptions,\n  'filename'\n> & { define?: Record<string, any> }\n\ndeclare global {\n  // LESS' types somewhat references this which doesn't make sense in Node,\n  // so we have to shim it\n  // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n  interface HTMLLinkElement {}\n}\n"
  },
  {
    "path": "packages/vite/types/internal/esbuildOptions.d.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\n\n// @ts-ignore `esbuild` may not be installed\nimport type esbuild from 'esbuild'\n\n/* eslint-enable @typescript-eslint/ban-ts-comment */\n\nexport type EsbuildTarget = string | string[]\n\nexport type EsbuildLoader = esbuild.Loader\nexport type EsbuildTransformOptions = esbuild.TransformOptions\nexport type EsbuildTransformResult = esbuild.TransformResult\n\nexport type EsbuildMessage = esbuild.Message\n\nexport type DepsOptimizerEsbuildOptions = Omit<\n  esbuild.BuildOptions,\n  | 'bundle'\n  | 'entryPoints'\n  | 'external'\n  | 'write'\n  | 'watch'\n  | 'outdir'\n  | 'outfile'\n  | 'outbase'\n  | 'outExtension'\n  | 'metafile'\n>\n"
  },
  {
    "path": "packages/vite/types/internal/lightningcssOptions.d.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\n\n// @ts-ignore `lightningcss` may not be installed\nimport type Lightningcss from 'lightningcss'\n\n/* eslint-enable @typescript-eslint/ban-ts-comment */\n\nexport type LightningCSSOptions = Omit<\n  Lightningcss.BundleAsyncOptions<Lightningcss.CustomAtRules>,\n  | 'filename'\n  | 'resolver'\n  | 'minify'\n  | 'sourceMap'\n  | 'analyzeDependencies'\n  // properties not overridden by Vite, but does not make sense to set by end users\n  | 'inputSourceMap'\n  | 'projectRoot'\n>\n"
  },
  {
    "path": "packages/vite/types/internal/rollupTypeCompat.d.ts",
    "content": "import type * as Rolldown from 'rolldown'\n\nexport * from 'rolldown'\n\n/** @deprecated use RolldownBuild instead */\nexport type RollupBuild = Rolldown.RolldownBuild\n\n/** @deprecated use RolldownOptions instead */\nexport type RollupOptions = Rolldown.RolldownOptions\n\n/** @deprecated use RolldownOutput instead */\nexport type RollupOutput = Rolldown.RolldownOutput\n\n/** @deprecated use RolldownPlugin instead */\nexport type RollupPlugin = Rolldown.RolldownPlugin\n\n/** @deprecated use RolldownPluginOption instead */\nexport type RollupPluginOption = Rolldown.RolldownPluginOption\n\n/** @deprecated use RolldownWatcher instead */\nexport type RollupWatcher = Rolldown.RolldownWatcher\n\n/** @deprecated use RollupWatcherEvent instead */\nexport type RollupWatcherEvent = Rolldown.RolldownWatcherEvent\n"
  },
  {
    "path": "packages/vite/types/internal/terserOptions.d.ts",
    "content": "/* eslint-disable @typescript-eslint/ban-ts-comment */\n\n// @ts-ignore `terser` may not be installed\nexport type * as Terser from 'terser'\n// @ts-ignore `terser` may not be installed\nimport type * as Terser from 'terser'\n\n/* eslint-enable @typescript-eslint/ban-ts-comment */\n\nexport type TerserMinifyOptions = Terser.MinifyOptions\nexport type TerserMinifyOutput = Terser.MinifyOutput\n"
  },
  {
    "path": "packages/vite/types/metadata.d.ts",
    "content": "export interface AssetMetadata {\n  importedAssets: Set<string>\n  importedCss: Set<string>\n}\n\nexport interface ChunkMetadata {\n  importedAssets: Set<string>\n  importedCss: Set<string>\n  /** @internal */\n  __modules: any\n}\n\nexport interface CustomPluginOptionsVite {\n  /**\n   * If this is a CSS Rollup module, you can scope to its importer's exports\n   * so that if those exports are treeshaken away, the CSS module will also\n   * be treeshaken.\n   *\n   * The \"importerId\" must import the CSS Rollup module statically.\n   *\n   * Example config if the CSS id is `/src/App.vue?vue&type=style&lang.css`:\n   * ```js\n   * cssScopeTo: ['/src/App.vue', 'default']\n   * ```\n   */\n  cssScopeTo?: readonly [importerId: string, exportName: string | undefined]\n\n  /** @deprecated no-op since Vite 6.1 */\n  lang?: string\n}\n\ndeclare module 'rolldown' {\n  export interface OutputAsset {\n    viteMetadata?: AssetMetadata\n  }\n\n  export interface RenderedChunk {\n    viteMetadata?: ChunkMetadata\n  }\n  export interface OutputChunk {\n    viteMetadata?: ChunkMetadata\n  }\n\n  export interface CustomPluginOptions {\n    vite?: CustomPluginOptionsVite\n  }\n}\n"
  },
  {
    "path": "patches/chokidar@3.6.0.patch",
    "content": "diff --git a/lib/fsevents-handler.js b/lib/fsevents-handler.js\nindex fe29393c179d3d6673f996ca6f95bbc83f9a0699..0a341f3d6a2f1497486a23ea99b3c6da003c026f 100644\n--- a/lib/fsevents-handler.js\n+++ b/lib/fsevents-handler.js\n@@ -305,7 +305,8 @@ _watchWithFsEvents(watchPath, realPath, transform, globFilter) {\n   if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return;\n   const opts = this.fsw.options;\n   const watchCallback = async (fullPath, flags, info) => {\n-    if (this.fsw.closed) return;\n+    // PATCH: bypass the callback for better perf when fullPath hit the ignored file list\n+    if (this.fsw.closed || this.fsw._isIgnored(fullPath)) return;\n     if (\n       opts.depth !== undefined &&\n       calcDepth(fullPath, realPath) > opts.depth\n"
  },
  {
    "path": "patches/dotenv-expand@12.0.3.patch",
    "content": "diff --git a/lib/main.js b/lib/main.js\nindex 794f3bf512ee8cd24fe20e83d159bf8682fb901e..5567e6e282d65b87deea02f8cb396d3e7276581e 100644\n--- a/lib/main.js\n+++ b/lib/main.js\n@@ -64,7 +64,7 @@ function expandValue (value, processEnv, runningParsed) {\n \n function expand (options) {\n   // for use with progressive expansion\n-  const runningParsed = {}\n+  // const runningParsed = {}\n \n   let processEnv = process.env\n   if (options && options.processEnv != null) {\n@@ -79,13 +79,15 @@ function expand (options) {\n     if (processEnv[key] && processEnv[key] !== value) {\n       value = processEnv[key]\n     } else {\n-      value = expandValue(value, processEnv, runningParsed)\n+      // PATCH: we pass options.parsed instead of runningParsed\n+      //        to allow variables declared in other files to be used\n+      value = expandValue(value, processEnv, options.parsed)\n     }\n \n     options.parsed[key] = _resolveEscapeSequences(value)\n \n     // for use with progressive expansion\n-    runningParsed[key] = _resolveEscapeSequences(value)\n+    // runningParsed[key] = _resolveEscapeSequences(value)\n   }\n \n   for (const processKey in options.parsed) {\n"
  },
  {
    "path": "patches/sirv@3.0.2.patch",
    "content": "diff --git a/build.js b/build.js\nindex 3734120d67745ff83b2df07fa5d0a40dcb92a69b..bd57f693ac2bd4555a12e7a5436fb9524789ef66 100644\n--- a/build.js\n+++ b/build.js\n@@ -35,7 +35,7 @@ function viaCache(cache, uri, extns) {\n \t}\n }\n \n-function viaLocal(dir, isEtag, uri, extns) {\n+function viaLocal(dir, isEtag, uri, extns, shouldServe) {\n \tlet i=0, arr=toAssume(uri, extns);\n \tlet abs, stats, name, headers;\n \tfor (; i < arr.length; i++) {\n@@ -46,6 +46,7 @@ function viaLocal(dir, isEtag, uri, extns) {\n \t\tif (abs.startsWith(dir) && fs.existsSync(abs)) {\n \t\t\tstats = fs.statSync(abs);\n \t\t\tif (stats.isDirectory()) continue;\n+\t\t\tif (shouldServe && !shouldServe(abs)) continue;\n \t\t\theaders = toHeaders(name, stats, isEtag);\n \t\t\theaders['Cache-Control'] = isEtag ? 'no-cache' : 'no-store';\n \t\t\treturn { abs, stats, headers };\n@@ -164,7 +165,7 @@ module.exports = function (dir, opts={}) {\n \t\t});\n \t}\n \n-\tlet lookup = opts.dev ? viaLocal.bind(0, dir + sep, isEtag) : viaCache.bind(0, FILES);\n+\tlet lookup = opts.dev ? viaLocal.bind(0, dir.endsWith(sep) ? dir : dir + sep, isEtag) : viaCache.bind(0, FILES);\n \n \treturn function (req, res, next) {\n \t\tlet extns = [''];\n@@ -179,7 +180,7 @@ module.exports = function (dir, opts={}) {\n \t\t\tcatch (err) { /* malform uri */ }\n \t\t}\n \n-\t\tlet data = lookup(pathname, extns) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns);\n+\t\tlet data = lookup(pathname, extns, opts.shouldServe) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns, opts.shouldServe);\n \t\tif (!data) return next ? next() : isNotFound(req, res);\n \n \t\tif (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {\ndiff --git a/build.mjs b/build.mjs\nindex 2f866d5216c951ec125f2044af070fa6b530e375..d5335bfbb16e23b57385c1a83226611e29c39093 100644\n--- a/build.mjs\n+++ b/build.mjs\n@@ -35,7 +35,7 @@ function viaCache(cache, uri, extns) {\n \t}\n }\n \n-function viaLocal(dir, isEtag, uri, extns) {\n+function viaLocal(dir, isEtag, uri, extns, shouldServe) {\n \tlet i=0, arr=toAssume(uri, extns);\n \tlet abs, stats, name, headers;\n \tfor (; i < arr.length; i++) {\n@@ -46,6 +46,7 @@ function viaLocal(dir, isEtag, uri, extns) {\n \t\tif (abs.startsWith(dir) && fs.existsSync(abs)) {\n \t\t\tstats = fs.statSync(abs);\n \t\t\tif (stats.isDirectory()) continue;\n+\t\t\tif (shouldServe && !shouldServe(abs)) continue;\n \t\t\theaders = toHeaders(name, stats, isEtag);\n \t\t\theaders['Cache-Control'] = isEtag ? 'no-cache' : 'no-store';\n \t\t\treturn { abs, stats, headers };\n@@ -164,7 +165,7 @@ export default function (dir, opts={}) {\n \t\t});\n \t}\n \n-\tlet lookup = opts.dev ? viaLocal.bind(0, dir + sep, isEtag) : viaCache.bind(0, FILES);\n+\tlet lookup = opts.dev ? viaLocal.bind(0, dir.endsWith(sep) ? dir : dir + sep, isEtag) : viaCache.bind(0, FILES);\n \n \treturn function (req, res, next) {\n \t\tlet extns = [''];\n@@ -179,7 +180,7 @@ export default function (dir, opts={}) {\n \t\t\tcatch (err) { /* malform uri */ }\n \t\t}\n \n-\t\tlet data = lookup(pathname, extns) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns);\n+\t\tlet data = lookup(pathname, extns, opts.shouldServe) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns, opts.shouldServe);\n \t\tif (!data) return next ? next() : isNotFound(req, res);\n \n \t\tif (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {\ndiff --git a/index.d.mts b/index.d.mts\nindex 8bfe364f1db2d1382c56a9b75a014579083cfa70..a8dfa1c473ff15c979bbfbc28c3630a12e222c3a 100644\n--- a/index.d.mts\n+++ b/index.d.mts\n@@ -24,6 +24,8 @@ export interface Options {\n \tgzip?: boolean;\n \tonNoMatch?: (req: IncomingMessage, res: ServerResponse) => void;\n \tsetHeaders?: (res: ServerResponse, pathname: string, stats: Stats) => void;\n+\t/** patched */\n+\tshouldServe?: (absoluteFilePath: string) => void;\n }\n \n export default function (dir?: string, opts?: Options): RequestHandler;\ndiff --git a/index.d.ts b/index.d.ts\nindex 96cc63e7ee1ccdd7266e9193252b799068ef2e3c..9e298d627002cd0b073073aa13528b7492541b5b 100644\n--- a/index.d.ts\n+++ b/index.d.ts\n@@ -25,6 +25,8 @@ declare namespace sirv {\n \t\tgzip?: boolean;\n \t\tonNoMatch?: (req: IncomingMessage, res: ServerResponse) => void;\n \t\tsetHeaders?: (res: ServerResponse, pathname: string, stats: Stats) => void;\n+\t\t/** patched */\n+\t\tshouldServe?: (absoluteFilePath: string) => void;\n \t}\n }\n \n"
  },
  {
    "path": "playground/alias/__tests__/alias.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { editFile, getColor, isBuild, page } from '~utils'\n\ntest('fs', async () => {\n  expect(await page.textContent('.fs')).toMatch('[success] alias to fs path')\n})\n\ntest('fs directory', async () => {\n  expect(await page.textContent('.fs-dir')).toMatch(\n    '[success] alias to directory',\n  )\n})\n\ntest('regex', async () => {\n  expect(await page.textContent('.regex')).toMatch(\n    '[success] alias to directory via regex',\n  )\n})\n\ntest('dependency', async () => {\n  expect(await page.textContent('.dep')).toMatch('[success] out of root')\n})\n\ntest('js via script src', async () => {\n  expect(await page.textContent('.from-script-src')).toMatch(\n    '[success] from script src',\n  )\n})\n\ntest('css via link', async () => {\n  expect(await getColor('body')).toBe('grey')\n  if (isBuild) return\n  editFile('dir/test.css', (code) => code.replace('grey', 'red'))\n  await expect.poll(() => getColor('body')).toBe('red')\n})\n\ntest('optimized dep', async () => {\n  expect(await page.textContent('.optimized')).toMatch(\n    '[success] alias optimized',\n  )\n})\n\ntest('aliased module', async () => {\n  expect(await page.textContent('.aliased-module')).toMatch(\n    '[success] aliased module',\n  )\n})\n\ntest('url conflict alias', async () => {\n  expect(await page.textContent('.url-conflict')).toMatch(\n    '[success] url conflict alias',\n  )\n})\n\ntest('custom resolver', async () => {\n  expect(await page.textContent('.custom-resolver')).toMatch(\n    '[success] alias to custom-resolver path',\n  )\n})\n"
  },
  {
    "path": "playground/alias/customResolver.js",
    "content": "export const msg = `[success] alias to custom-resolver path`\n"
  },
  {
    "path": "playground/alias/dir/from-script-src.js",
    "content": "document.querySelector('.from-script-src').textContent =\n  '[success] from script src'\n"
  },
  {
    "path": "playground/alias/dir/module/index.js",
    "content": "export const msg = `[success] aliased module`\n"
  },
  {
    "path": "playground/alias/dir/module/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-aliased-module\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/alias/dir/test.css",
    "content": "body {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/alias/dir/test.js",
    "content": "export const msg = `[success] alias to directory`\n"
  },
  {
    "path": "playground/alias/dir/url_conflict.js",
    "content": "export const msg = `[success] url conflict alias`\n"
  },
  {
    "path": "playground/alias/index.html",
    "content": "<h1>Alias</h1>\n\n<p class=\"fs\"></p>\n<p class=\"fs-dir\"></p>\n<p class=\"regex\"></p>\n<p class=\"dep\"></p>\n<p class=\"from-script-src\"></p>\n<p class=\"url-conflict\"></p>\n<p class=\"aliased-module\"></p>\n<p class=\"custom-resolver\"></p>\n\n<div class=\"optimized\"></div>\n\n<script type=\"module\">\n  // no node: protocol intentionally\n  import { msg as fsMsg } from 'fs'\n  import { msg as fsDirMsg } from 'fs-dir/test'\n  import { msg as regexMsg } from 'regex/test'\n  import { msg as depMsg } from 'dep'\n  import { msg as moduleMsg } from 'aliased-module/index.js'\n  import { msg as urlConflictMsg } from '//url_conflict.js'\n  import { msg as customResolverMsg } from 'custom-resolver'\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n\n  text('.fs', fsMsg)\n  text('.fs-dir', fsDirMsg)\n  text('.regex', regexMsg + ' via regex')\n  text('.dep', depMsg)\n  text('.aliased-module', moduleMsg)\n  text('.url-conflict', urlConflictMsg)\n  text('.custom-resolver', customResolverMsg)\n\n  import { createApp } from 'vue'\n  import { ref } from 'foo'\n  // vue is aliased to the full browser build AND optimized.\n  // should resolve as expected\n  createApp({\n    template: '[{{ msg }}] alias optimized dep',\n    setup() {\n      return {\n        msg: ref('success'),\n      }\n    },\n  }).mount('.optimized')\n\n  // aliased to an absolute URL in CJS, should be optimized\n  import { isFunction } from '@vue/shared'\n  // also check name clash for aliased deps\n  export { isFunction } from '@vue/shared'\n  console.log(isFunction(() => {}))\n</script>\n\n<script type=\"module\" src=\"/@/from-script-src.js\"></script>\n<link rel=\"stylesheet\" href=\"/@/test.css\" />\n"
  },
  {
    "path": "playground/alias/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-alias\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"aliased-module\": \"file:./dir/module\",\n    \"vue\": \"^3.5.30\",\n    \"@vue/shared\": \"^3.5.30\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/test-resolve-linked\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "playground/alias/test.js",
    "content": "export const msg = `[success] alias to fs path`\n"
  },
  {
    "path": "playground/alias/vite.config.js",
    "content": "import path from 'node:path'\nimport module from 'node:module'\nimport { defineConfig } from 'vite'\n\nconst require = module.createRequire(import.meta.url)\n\nexport default defineConfig({\n  resolve: {\n    alias: [\n      { find: 'fs', replacement: path.resolve(import.meta.dirname, 'test.js') },\n      { find: 'fs-dir', replacement: path.resolve(import.meta.dirname, 'dir') },\n      { find: 'dep', replacement: '@vitejs/test-resolve-linked' },\n      {\n        find: /^regex\\/(.*)/,\n        replacement: `${path.resolve(import.meta.dirname, 'dir')}/$1`,\n      },\n      { find: '/@', replacement: path.resolve(import.meta.dirname, 'dir') },\n      // aliasing a pattern that conflicts with url schemes\n      { find: /^\\/\\//, replacement: path.join(import.meta.dirname, 'dir/') },\n      // aliasing an optimized dep\n      { find: 'vue', replacement: 'vue/dist/vue.esm-bundler.js' },\n      // aliasing an optimized dep to absolute URL\n      {\n        find: '@vue/shared',\n        replacement: require.resolve('@vue/shared/dist/shared.cjs.prod.js'),\n      },\n      // aliasing one unoptimized dep to an optimized dep\n      { find: 'foo', replacement: 'vue' },\n      {\n        find: 'custom-resolver',\n        replacement: path.resolve(import.meta.dirname, 'test.js'),\n        customResolver(id) {\n          return id.replace('test.js', 'customResolver.js')\n        },\n      },\n    ],\n  },\n  build: {\n    minify: false,\n  },\n  define: {\n    __VUE_OPTIONS_API__: true,\n    __VUE_PROD_DEVTOOLS__: true,\n    __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,\n  },\n})\n"
  },
  {
    "path": "playground/assets/__tests__/assets.spec.ts",
    "content": "import path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport {\n  browserLogs,\n  editFile,\n  findAssetFile,\n  getBg,\n  getColor,\n  isBuild,\n  isServe,\n  listAssets,\n  notifyRebuildComplete,\n  page,\n  readFile,\n  readManifest,\n  serverLogs,\n  viteTestUrl,\n  watcher,\n} from '~utils'\n\nconst assetMatch = isBuild\n  ? /\\/foo\\/bar\\/assets\\/asset-[-\\w]{8}\\.png/\n  : '/foo/bar/nested/asset.png'\n\nconst encodedAssetMatch = isBuild\n  ? /\\/foo\\/bar\\/assets\\/asset_small_-[-\\w]{8}\\.png/\n  : '/foo/bar/nested/asset[small].png'\n\nconst iconMatch = `/foo/bar/icon.png`\n\nconst fetchPath = (p: string) => {\n  return fetch(path.posix.join(viteTestUrl, p), {\n    headers: { Accept: 'text/html,*/*' },\n  })\n}\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ntest.runIf(isBuild)(\n  'should not warn about VITE_ASSET tokens in image-set',\n  async () => {\n    expect(serverLogs).toStrictEqual(\n      expect.not.arrayContaining([\n        expect.stringMatching(/VITE_ASSET__.*?didn't resolve at build time/),\n      ]),\n    )\n  },\n)\n\ntest('should get a 404 when using incorrect case', async () => {\n  expect((await fetchPath('icon.png')).headers.get('Content-Type')).toBe(\n    'image/png',\n  )\n  // fallback to index.html\n  const iconPngResult = await fetchPath('ICON.png')\n  expect(iconPngResult.headers.get('Content-Type')).toBe('text/html')\n  expect(iconPngResult.status).toBe(200)\n\n  expect((await fetchPath('bar')).headers.get('Content-Type')).toBe('')\n  // fallback to index.html\n  const barResult = await fetchPath('BAR')\n  expect(barResult.headers.get('Content-Type')).toContain('text/html')\n  expect(barResult.status).toBe(200)\n})\n\ntest('should fallback to index.html when accessing non-existent html file', async () => {\n  expect((await fetchPath('doesnt-exist.html')).status).toBe(200)\n})\n\ndescribe.runIf(isServe)('outside base', () => {\n  test('should get a 404 with html', async () => {\n    const res = await fetch(new URL('/baz', viteTestUrl), {\n      headers: { Accept: 'text/html,*/*' },\n    })\n    expect(res.status).toBe(404)\n    expect(res.headers.get('Content-Type')).toBe('text/html')\n  })\n\n  test('should get a 404 with text', async () => {\n    const res = await fetch(new URL('/baz', viteTestUrl))\n    expect(res.status).toBe(404)\n    expect(res.headers.get('Content-Type')).toBe('text/plain')\n  })\n})\n\ndescribe('injected scripts', () => {\n  test('@vite/client', async () => {\n    const hasClient = await page.$(\n      'script[type=\"module\"][src=\"/foo/bar/@vite/client\"]',\n    )\n    if (isBuild) {\n      expect(hasClient).toBeFalsy()\n    } else {\n      expect(hasClient).toBeTruthy()\n    }\n  })\n\n  test('html-proxy', async () => {\n    const hasHtmlProxy = await page.$(\n      'script[type=\"module\"][src^=\"/foo/bar/index.html?html-proxy\"]',\n    )\n    if (isBuild) {\n      expect(hasHtmlProxy).toBeFalsy()\n    } else {\n      expect(hasHtmlProxy).toBeTruthy()\n    }\n  })\n})\n\ndescribe('raw references from /public', () => {\n  test('load raw js from /public', async () => {\n    expect(await page.textContent('.raw-js')).toMatch('[success]')\n  })\n\n  test('load raw css from /public', async () => {\n    expect(await getColor('.raw-css')).toBe('red')\n  })\n})\n\ntest('import-expression from simple script', async () => {\n  expect(await page.textContent('.import-expression')).toMatch(\n    '[success][success]',\n  )\n})\n\ndescribe('asset imports from js', () => {\n  test('relative', async () => {\n    expect(await page.textContent('.asset-import-relative')).toMatch(assetMatch)\n  })\n\n  test('absolute', async () => {\n    expect(await page.textContent('.asset-import-absolute')).toMatch(assetMatch)\n  })\n\n  test('from /public', async () => {\n    expect(await page.textContent('.public-import')).toMatch(iconMatch)\n  })\n\n  test('from /public (json)', async () => {\n    expect(await page.textContent('.public-json-import')).toMatch(\n      '/foo/bar/foo.json',\n    )\n    expect(await page.textContent('.public-json-import-content'))\n      .toMatchInlineSnapshot(`\n        \"{\n          \"foo\": \"bar\"\n        }\n        \"\n      `)\n  })\n\n  test('from /public (js)', async () => {\n    expect(await page.textContent('.public-js-import')).toMatch(\n      '/foo/bar/raw.js',\n    )\n    expect(await page.textContent('.public-js-import-content'))\n      .toMatchInlineSnapshot(`\n        \"document.querySelector('.raw-js').textContent =\n          '[success] Raw js from /public loaded'\n        \"\n      `)\n    expect(await page.textContent('.public-js-import-content-type')).toMatch(\n      'text/javascript',\n    )\n  })\n\n  test('from /public (ts)', async () => {\n    expect(await page.textContent('.public-ts-import')).toMatch(\n      '/foo/bar/raw.ts',\n    )\n    expect(await page.textContent('.public-ts-import-content'))\n      .toMatchInlineSnapshot(`\n      \"export default function other() {\n        return 1 + 2\n      }\n      \"\n    `)\n    // NOTE: users should configure the mime type for .ts files for preview server\n    if (isServe) {\n      expect(await page.textContent('.public-ts-import-content-type')).toMatch(\n        'text/javascript',\n      )\n    }\n  })\n\n  test('from /public (mts)', async () => {\n    expect(await page.textContent('.public-mts-import')).toMatch(\n      '/foo/bar/raw.mts',\n    )\n    expect(await page.textContent('.public-mts-import-content'))\n      .toMatchInlineSnapshot(`\n      \"export default function foobar() {\n        return 1 + 2\n      }\n      \"\n    `)\n    // NOTE: users should configure the mime type for .ts files for preview server\n    if (isServe) {\n      expect(await page.textContent('.public-mts-import-content-type')).toMatch(\n        'text/javascript',\n      )\n    }\n  })\n})\n\ndescribe('css url() references', () => {\n  test('fonts', async () => {\n    expect(\n      await page.evaluate(() => {\n        return (document as any).fonts.check('700 32px Inter')\n      }),\n    ).toBe(true)\n  })\n\n  test('relative', async () => {\n    expect(await getBg('.css-url-relative')).toMatch(assetMatch)\n  })\n\n  test('encoded', async () => {\n    expect(await getBg('.css-url-encoded')).toMatch(encodedAssetMatch)\n  })\n\n  test('image-set relative', async () => {\n    const imageSet = await getBg('.css-image-set-relative')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(assetMatch)\n    })\n  })\n\n  test('image-set without the url() call', async () => {\n    const imageSet = await getBg('.css-image-set-without-url-call')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(assetMatch)\n    })\n  })\n\n  test('image-set with var', async () => {\n    const imageSet = await getBg('.css-image-set-with-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(assetMatch)\n    })\n  })\n\n  test('image-set with mix', async () => {\n    const imageSet = await getBg('.css-image-set-mix-url-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(assetMatch)\n    })\n  })\n\n  test('image-set with base64', async () => {\n    const imageSet = await getBg('.css-image-set-base64')\n    expect(imageSet).toContain('image-set(url(\"data:image/png;base64,')\n  })\n\n  test('image-set with gradient', async () => {\n    const imageSet = await getBg('.css-image-set-gradient')\n    expect(imageSet).toContain('image-set(url(\"data:image/png;base64,')\n  })\n\n  test('image-set with multiple descriptor', async () => {\n    const imageSet = await getBg('.css-image-set-multiple-descriptor')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(assetMatch)\n    })\n  })\n\n  test('image-set with multiple descriptor as inline style', async () => {\n    const imageSet = await getBg(\n      '.css-image-set-multiple-descriptor-inline-style',\n    )\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(assetMatch)\n    })\n  })\n\n  test('image-set and url exist at the same time.', async () => {\n    const imageSet = await getBg('.image-set-and-url-exsiting-at-same-time')\n    expect(imageSet).toMatch(assetMatch)\n  })\n\n  test('relative in @import', async () => {\n    expect(await getBg('.css-url-relative-at-imported')).toMatch(assetMatch)\n  })\n\n  test('absolute', async () => {\n    expect(await getBg('.css-url-absolute')).toMatch(assetMatch)\n  })\n\n  test('from /public', async () => {\n    expect(await getBg('.css-url-public')).toMatch(iconMatch)\n  })\n\n  test('base64 inline', async () => {\n    const match = isBuild ? `data:image/png;base64` : `/foo/bar/nested/icon.png`\n    expect(await getBg('.css-url-base64-inline')).toMatch(match)\n    expect(await getBg('.css-url-quotes-base64-inline')).toMatch(match)\n  })\n\n  test('no base64 inline for icon and manifest links', async () => {\n    const iconEl = await page.$(`link.ico`)\n    const href = await iconEl.getAttribute('href')\n    expect(href).toMatch(\n      isBuild ? /\\/foo\\/bar\\/assets\\/favicon-[-\\w]{8}\\.ico/ : 'favicon.ico',\n    )\n\n    const manifestEl = await page.$(`link[rel=\"manifest\"]`)\n    const manifestHref = await manifestEl.getAttribute('href')\n    expect(manifestHref).toMatch(\n      isBuild ? /\\/foo\\/bar\\/assets\\/manifest-[-\\w]{8}\\.json/ : 'manifest.json',\n    )\n  })\n\n  test('multiple urls on the same line', async () => {\n    const bg = await getBg('.css-url-same-line')\n    expect(bg).toMatch(assetMatch)\n    expect(bg).toMatch(iconMatch)\n  })\n\n  test('aliased', async () => {\n    const bg = await getBg('.css-url-aliased')\n    expect(bg).toMatch(assetMatch)\n  })\n\n  test('preinlined SVG', async () => {\n    expect(await getBg('.css-url-preinlined-svg')).toMatch(\n      /data:image\\/svg\\+xml,.+/,\n    )\n  })\n\n  test.runIf(isBuild)('generated paths in CSS', () => {\n    const css = findAssetFile(/index-[-\\w]{8}\\.css$/, 'foo')\n\n    // preserve postfix query/hash\n    expect(css).toMatch(`woff2?#iefix`)\n\n    // generate non-relative base for public path in CSS\n    expect(css).not.toMatch(`../icon.png`)\n  })\n\n  test('url() with svg', async () => {\n    const bg = await getBg('.css-url-svg')\n    expect(bg).toMatch(/data:image\\/svg\\+xml,.+/)\n    expect(bg).toContain('blue')\n    expect(bg).not.toContain('red')\n\n    if (isServe) {\n      editFile('nested/fragment-bg-hmr.svg', (code) =>\n        code.replace('fill=\"blue\"', 'fill=\"red\"'),\n      )\n      await expect.poll(() => getBg('.css-url-svg')).toMatch('red')\n    }\n  })\n\n  test('image-set() with svg', async () => {\n    expect(await getBg('.css-image-set-svg')).toMatch(/data:image\\/svg\\+xml,.+/)\n  })\n\n  test('url() with svg in .css?url', async () => {\n    const bg = await getBg('.css-url-svg-in-url')\n    expect(bg).toMatch(/data:image\\/svg\\+xml,.+/)\n    expect(bg).toContain('blue')\n    expect(bg).not.toContain('red')\n\n    if (isServe) {\n      editFile('nested/fragment-bg-hmr2.svg', (code) =>\n        code.replace('fill=\"blue\"', 'fill=\"red\"'),\n      )\n      await expect.poll(() => getBg('.css-url-svg')).toMatch('red')\n    }\n  })\n\n  test.runIf(isServe)('non inlined url() HMR', async () => {\n    const bg = await getBg('.css-url-non-inline-hmr')\n    editFile('nested/donuts-large.svg', (code) =>\n      code.replace('fill=\"blue\"', 'fill=\"red\"'),\n    )\n    await expect.poll(() => getBg('.css-url-non-inline-hmr')).not.toBe(bg)\n  })\n})\n\ndescribe('image', () => {\n  test('src', async () => {\n    const img = await page.$('.img-src')\n    const src = await img.getAttribute('src')\n    expect(src).toMatch(\n      isBuild\n        ? /\\/foo\\/bar\\/assets\\/html-only-asset-[-\\w]{8}\\.jpg/\n        : /\\/foo\\/bar\\/nested\\/html-only-asset.jpg/,\n    )\n  })\n\n  test('src inline', async () => {\n    const img = await page.$('.img-src-inline')\n    const src = await img.getAttribute('src')\n    expect(src).toMatch(\n      isBuild\n        ? /^data:image\\/svg\\+xml,%3csvg/\n        : /\\/foo\\/bar\\/nested\\/inlined.svg/,\n    )\n  })\n\n  test('srcset', async () => {\n    const img = await page.$('.img-src-set')\n    const srcset = await img.getAttribute('srcset')\n    srcset.split(', ').forEach((s) => {\n      expect(s).toMatch(\n        isBuild\n          ? /\\/foo\\/bar\\/assets\\/asset-[-\\w]{8}\\.png \\dx/\n          : /\\/foo\\/bar\\/nested\\/asset.png \\dx/,\n      )\n    })\n  })\n\n  test('srcset (public)', async () => {\n    const img = await page.$('.img-src-set-public')\n    const srcset = await img.getAttribute('srcset')\n    srcset.split(', ').forEach((s) => {\n      expect(s).toMatch(/\\/foo\\/bar\\/icon\\.png \\dx/)\n    })\n  })\n\n  test('srcset (mixed)', async () => {\n    const img = await page.$('.img-src-set-mixed')\n    const srcset = await img.getAttribute('srcset')\n    const srcs = srcset.split(', ')\n    expect(srcs[1]).toMatch(\n      isBuild\n        ? /\\/foo\\/bar\\/assets\\/asset-[-\\w]{8}\\.png \\dx/\n        : /\\/foo\\/bar\\/nested\\/asset.png \\dx/,\n    )\n  })\n})\n\ndescribe('meta', () => {\n  test('og image', async () => {\n    const meta = await page.$('.meta-og-image')\n    const content = await meta.getAttribute('content')\n    expect(content).toMatch(\n      isBuild\n        ? /\\/foo\\/bar\\/assets\\/asset-\\w{8}\\.png/\n        : /\\/foo\\/bar\\/nested\\/asset.png/,\n    )\n  })\n})\n\ndescribe('svg fragments', () => {\n  // 404 is checked already, so here we just ensure the urls end with #fragment\n  test('img url', async () => {\n    const img = await page.$('.svg-frag-img')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-clock-view$/)\n  })\n\n  test('via css url()', async () => {\n    expect(await getBg('.icon')).toMatch(/svg#icon-clock-view\"\\)$/)\n  })\n\n  test('from js import', async () => {\n    const img = await page.$('.svg-frag-import')\n    expect(await img.getAttribute('src')).toMatch(\n      // Assert trimmed (data URI starts with < and ends with >)\n      /^data:image\\/svg\\+xml,%3c.*%3e#icon-heart-view$/,\n    )\n  })\n\n  test('url with an alias', async () => {\n    expect(await getBg('.icon-clock-alias')).toMatch(\n      /\\.svg#icon-clock-view\"\\)$/,\n    )\n  })\n})\n\ntest('Unknown extension assets import', async () => {\n  expect(await page.textContent('.unknown-ext')).toMatch(\n    isBuild ? 'data:application/octet-stream;' : '/nested/foo.unknown',\n  )\n})\n\ntest('?raw import', async () => {\n  expect(await page.textContent('.raw')).toMatch('SVG')\n  expect(await page.textContent('.raw-html')).toBe('<div>partial</div>\\n')\n\n  if (isBuild) return\n  editFile('nested/partial.html', (code) =>\n    code.replace('<div>partial</div>', '<div>partial updated</div>'),\n  )\n  await expect\n    .poll(() => page.textContent('.raw-html'))\n    .toBe('<div>partial updated</div>\\n')\n  expect(browserLogs).toStrictEqual(\n    expect.arrayContaining([\n      expect.stringContaining('hot updated: /nested/partial.html?raw via'),\n    ]),\n  )\n})\n\ntest('?no-inline svg import', async () => {\n  expect(await page.textContent('.no-inline-svg')).toMatch(\n    isBuild\n      ? /\\/foo\\/bar\\/assets\\/fragment-[-\\w]{8}\\.svg/\n      : '/foo/bar/nested/fragment.svg?no-inline',\n  )\n})\n\ntest('?no-inline svg import -- multiple postfix', async () => {\n  expect(await page.textContent('.no-inline-svg-mp')).toMatch(\n    isBuild\n      ? /\\/foo\\/bar\\/assets\\/fragment-[-\\w]{8}\\.svg\\?foo=bar/\n      : '/foo/bar/nested/fragment.svg?no-inline&foo=bar',\n  )\n})\n\ntest('?inline png import', async () => {\n  expect(await page.textContent('.inline-png')).toMatch(\n    /^data:image\\/png;base64,/,\n  )\n})\n\ntest('?inline public png import', async () => {\n  expect(await page.textContent('.inline-public-png')).toMatch(\n    /^data:image\\/png;base64,/,\n  )\n})\n\ntest('?inline public json import', async () => {\n  expect(await page.textContent('.inline-public-json')).toMatch(\n    /^data:application\\/json;base64,/,\n  )\n})\n\ntest('?url import', async () => {\n  const src = readFile('foo.js')\n  expect(await page.textContent('.url')).toMatch(\n    isBuild\n      ? `data:text/javascript;base64,${Buffer.from(src).toString('base64')}`\n      : `/foo/bar/foo.js`,\n  )\n})\n\ntest('?url import on css', async () => {\n  const txt = await page.textContent('.url-css')\n  expect(txt).toMatch(\n    isBuild\n      ? /\\/foo\\/bar\\/assets\\/icons-[-\\w]{8}\\.css/\n      : '/foo/bar/css/icons.css',\n  )\n})\n\ndescribe('unicode url', () => {\n  test('from js import', async () => {\n    const src = readFile('テスト-測試-white space.js')\n    expect(await page.textContent('.unicode-url')).toMatch(\n      isBuild\n        ? `data:text/javascript;base64,${Buffer.from(src).toString('base64')}`\n        : encodeURI(`/foo/bar/テスト-測試-white space.js`),\n    )\n  })\n})\n\ndescribe.runIf(isBuild)('encodeURI', () => {\n  test('img src with encodeURI', async () => {\n    const img = await page.$('.encodeURI')\n    expect(await img.getAttribute('src')).toMatch(/^data:image\\/png;base64,/)\n  })\n})\n\ntest('new URL(..., import.meta.url)', async () => {\n  const imgMatch = isBuild\n    ? /\\/foo\\/bar\\/assets\\/img-[-\\w]{8}\\.png/\n    : '/foo/bar/import-meta-url/img.png'\n\n  expect(await page.textContent('.import-meta-url')).toMatch(imgMatch)\n  if (isServe) {\n    const loadPromise = page.waitForEvent('load')\n    const newContent = readFile('import-meta-url/img-update.png', null)\n    let oldContent: Buffer\n    editFile('import-meta-url/img.png', null, (_oldContent) => {\n      oldContent = _oldContent\n      return newContent\n    })\n    await loadPromise // expect reload\n    await expect\n      .poll(() => page.textContent('.import-meta-url'))\n      .toMatch(imgMatch)\n\n    const loadPromise2 = page.waitForEvent('load')\n    editFile('import-meta-url/img.png', null, (_) => oldContent)\n    await loadPromise2 // expect reload\n    await expect\n      .poll(() => page.textContent('.import-meta-url'))\n      .toMatch(imgMatch)\n  }\n})\n\ntest('new URL(\"@/...\", import.meta.url)', async () => {\n  expect(await page.textContent('.import-meta-url-dep')).toMatch(assetMatch)\n})\n\ntest('new URL(\"/...\", import.meta.url)', async () => {\n  expect(await page.textContent('.import-meta-url-base-path')).toMatch(\n    iconMatch,\n  )\n})\n\ntest('new URL(\"data:...\", import.meta.url)', async () => {\n  const img = await page.$('.import-meta-url-data-uri-img')\n  expect(await img.getAttribute('src')).toMatch(/^data:image\\/png;base64,/)\n  expect(await page.textContent('.import-meta-url-data-uri')).toMatch(\n    /^data:image\\/png;base64,/,\n  )\n})\n\ntest('new URL(..., import.meta.url) without extension', async () => {\n  expect(await page.textContent('.import-meta-url-without-extension')).toMatch(\n    isBuild ? 'data:text/javascript' : 'nested/test.js',\n  )\n  expect(\n    await page.textContent('.import-meta-url-content-without-extension'),\n  ).toContain('export default class')\n})\n\ntest('new URL(`${dynamic}`, import.meta.url)', async () => {\n  expect(await page.textContent('.dynamic-import-meta-url-1')).toMatch(\n    isBuild ? 'data:image/png;base64' : '/foo/bar/nested/icon.png',\n  )\n  expect(await page.textContent('.dynamic-import-meta-url-2')).toMatch(\n    assetMatch,\n  )\n  expect(await page.textContent('.dynamic-import-meta-url-js')).toMatch(\n    isBuild ? 'data:text/javascript;base64' : '/foo/bar/nested/test.js',\n  )\n})\n\ntest('new URL(`./${dynamic}?abc`, import.meta.url)', async () => {\n  expect(await page.textContent('.dynamic-import-meta-url-1-query')).toMatch(\n    isBuild ? 'data:image/png;base64' : '/foo/bar/nested/icon.png?abc',\n  )\n  expect(await page.textContent('.dynamic-import-meta-url-2-query')).toMatch(\n    isBuild\n      ? /\\/foo\\/bar\\/assets\\/asset-[-\\w]{8}\\.png\\?abc/\n      : '/foo/bar/nested/asset.png?abc',\n  )\n})\n\ntest('new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)', async () => {\n  expect(await page.textContent('.dynamic-import-meta-url-1-ternary')).toMatch(\n    isBuild ? 'data:image/png;base64' : '/foo/bar/nested/icon.png?abc',\n  )\n  expect(await page.textContent('.dynamic-import-meta-url-2-ternary')).toMatch(\n    isBuild\n      ? /\\/foo\\/bar\\/assets\\/asset-[-\\w]{8}\\.png\\?abc/\n      : '/foo/bar/nested/asset.png?abc',\n  )\n})\n\ntest(\"new URL(/* @vite-ignore */ 'non-existent', import.meta.url)\", async () => {\n  // the inlined script tag is extracted in a separate file\n  const importMetaUrl = new URL(\n    isBuild ? '/foo/bar/assets/index.js' : '/foo/bar/index.html',\n    page.url(),\n  )\n  expect(await page.textContent('.non-existent-import-meta-url')).toMatch(\n    new URL('non-existent', importMetaUrl).pathname,\n  )\n  expect(serverLogs).not.toContainEqual(\n    expect.stringContaining(\"doesn't exist at build time\"),\n  )\n})\n\ntest('new URL(..., import.meta.url) (multiline)', async () => {\n  const assetMatch = isBuild\n    ? /\\/foo\\/bar\\/assets\\/asset-[-\\w]{8}\\.png/\n    : '/foo/bar/nested/asset.png'\n\n  expect(await page.textContent('.import-meta-url-multiline')).toMatch(\n    assetMatch,\n  )\n})\n\ntest.runIf(isBuild)('manifest', async () => {\n  const manifest = readManifest('foo')\n  const entry = manifest['index.html']\n\n  for (const file of listAssets('foo')) {\n    if (file.endsWith('.css')) {\n      // ignore icons-*.css and css-url-url-*.css as it's imported with ?url\n      if (file.includes('icons-') || file.includes('css-url-url-')) continue\n      expect(entry.css).toContain(`assets/${file}`)\n    } else if (!file.endsWith('.js')) {\n      expect(entry.assets).toContain(`assets/${file}`)\n    }\n  }\n})\n\ndescribe.runIf(isBuild)('css and assets in css in build watch', () => {\n  test('css will not be lost and css does not contain undefined', async () => {\n    editFile('index.html', (code) => code.replace('Assets', 'assets'))\n    await notifyRebuildComplete(watcher)\n    const cssFile = findAssetFile(/index-[-\\w]+\\.css$/, 'foo')\n    expect(cssFile).not.toBe('')\n    expect(cssFile).not.toMatch(/undefined/)\n  })\n\n  test('import module.css', async () => {\n    expect(await getColor('#foo')).toBe('red')\n    editFile('css/foo.module.css', (code) => code.replace('red', 'blue'))\n    await notifyRebuildComplete(watcher)\n    await page.reload()\n    expect(await getColor('#foo')).toBe('blue')\n  })\n\n  test('import with raw query', async () => {\n    expect(await page.textContent('.raw-query')).toBe('foo')\n    editFile('static/foo.txt', (code) => code.replace('foo', 'zoo'))\n    await notifyRebuildComplete(watcher)\n    await page.reload()\n    expect(await page.textContent('.raw-query')).toBe('zoo')\n  })\n})\n\ntest('inline style test', async () => {\n  expect(await getBg('.inline-style')).toMatch(assetMatch)\n  expect(await getBg('.style-url-assets')).toMatch(assetMatch)\n})\n\nif (!isBuild) {\n  test('@import in html style tag hmr', async () => {\n    await expect.poll(() => getColor('.import-css')).toBe('rgb(0, 136, 255)')\n    const loadPromise = page.waitForEvent('load')\n    editFile('./css/import.css', (code) => code.replace('#0088ff', '#00ff88'))\n    await loadPromise\n    await expect.poll(() => getColor('.import-css')).toBe('rgb(0, 255, 136)')\n  })\n}\n\ntest('html import word boundary', async () => {\n  expect(await page.textContent('.obj-import-express')).toMatch(\n    'ignore object import prop',\n  )\n  expect(await page.textContent('.string-import-express')).toMatch('no load')\n})\n\ntest('relative path in html asset', async () => {\n  expect(await page.textContent('.relative-js')).toMatch('hello')\n  expect(await getColor('.relative-css')).toMatch('red')\n})\n\ntest('url() contains file in publicDir, in <style> tag', async () => {\n  expect(await getBg('.style-public-assets')).toContain(iconMatch)\n})\n\ntest('url() contains file in publicDir, as inline style', async () => {\n  expect(await getBg('.inline-style-public')).toContain(iconMatch)\n})\n\ntest('should not rewrite non-relative urls in html', async () => {\n  const link = page.locator('.data-href')\n  expect(await link.getAttribute('href')).toBe('data:,')\n})\n\ntest.runIf(isBuild)('assets inside <noscript> is rewrote', async () => {\n  const indexHtml = readFile('./dist/foo/index.html')\n  expect(indexHtml).toMatch(\n    /<img class=\"noscript\" src=\"\\/foo\\/bar\\/assets\\/asset-[-\\w]+\\.png\" \\/>/,\n  )\n})\n\ntest.runIf(isBuild)('assets inside <template> is rewrote', async () => {\n  const indexHtml = readFile('./dist/foo/index.html')\n  expect(indexHtml).toMatch(\n    /<img class=\"template\" src=\"\\/foo\\/bar\\/assets\\/asset-[-\\w]+\\.png\" \\/>/,\n  )\n})\n"
  },
  {
    "path": "playground/assets/__tests__/encoded-base/assets-encoded-base.spec.ts",
    "content": "import { beforeAll, describe, expect, test } from 'vitest'\nimport {\n  browserLogs,\n  findAssetFile,\n  getBg,\n  getColor,\n  isBuild,\n  page,\n} from '~utils'\n\nconst urlAssetMatch = isBuild\n  ? /\\/foo%20bar\\/other-assets\\/asset-[-\\w]{8}\\.png/\n  : '/nested/asset.png'\n\nconst iconMatch = '/icon.png'\n\nconst absoluteIconMatch = isBuild\n  ? /\\/foo%20bar\\/.*\\/icon-[-\\w]{8}\\.png/\n  : '/nested/icon.png'\n\nconst absolutePublicIconMatch = isBuild ? /\\/foo%20bar\\/icon\\.png/ : '/icon.png'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe('raw references from /public', () => {\n  test('load raw js from /public', async () => {\n    expect(await page.textContent('.raw-js')).toMatch('[success]')\n  })\n\n  test('load raw css from /public', async () => {\n    expect(await getColor('.raw-css')).toBe('red')\n  })\n})\n\ntest('import-expression from simple script', async () => {\n  expect(await page.textContent('.import-expression')).toMatch(\n    '[success][success]',\n  )\n})\n\ndescribe('asset imports from js', () => {\n  test('relative', async () => {\n    expect(await page.textContent('.asset-import-relative')).toMatch(\n      urlAssetMatch,\n    )\n  })\n\n  test('absolute', async () => {\n    expect(await page.textContent('.asset-import-absolute')).toMatch(\n      urlAssetMatch,\n    )\n  })\n\n  test('from /public', async () => {\n    expect(await page.textContent('.public-import')).toMatch(\n      absolutePublicIconMatch,\n    )\n  })\n})\n\ndescribe('css url() references', () => {\n  test('fonts', async () => {\n    expect(\n      await page.evaluate(() => document.fonts.check('700 32px Inter')),\n    ).toBe(true)\n  })\n\n  test('relative', async () => {\n    const bg = await getBg('.css-url-relative')\n    expect(bg).toMatch(urlAssetMatch)\n  })\n\n  test('image-set relative', async () => {\n    const imageSet = await getBg('.css-image-set-relative')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('image-set without the url() call', async () => {\n    const imageSet = await getBg('.css-image-set-without-url-call')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('image-set with var', async () => {\n    const imageSet = await getBg('.css-image-set-with-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('image-set with mix', async () => {\n    const imageSet = await getBg('.css-image-set-mix-url-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('relative in @import', async () => {\n    expect(await getBg('.css-url-relative-at-imported')).toMatch(urlAssetMatch)\n  })\n\n  test('absolute', async () => {\n    expect(await getBg('.css-url-absolute')).toMatch(urlAssetMatch)\n  })\n\n  test('from /public', async () => {\n    expect(await getBg('.css-url-public')).toMatch(iconMatch)\n  })\n\n  test('multiple urls on the same line', async () => {\n    const bg = await getBg('.css-url-same-line')\n    expect(bg).toMatch(urlAssetMatch)\n    expect(bg).toMatch(iconMatch)\n  })\n\n  test('aliased', async () => {\n    const bg = await getBg('.css-url-aliased')\n    expect(bg).toMatch(urlAssetMatch)\n  })\n})\n\ndescribe.runIf(isBuild)('index.css URLs', () => {\n  let css: string\n  beforeAll(() => {\n    css = findAssetFile(/index.*\\.css$/, 'encoded-base', 'other-assets')\n  })\n\n  test('use base URL for asset URL', () => {\n    expect(css).toMatch(urlAssetMatch)\n  })\n\n  test('preserve postfix query/hash', () => {\n    expect(css).toMatch('woff2?#iefix')\n  })\n})\n\ndescribe('image', () => {\n  test('srcset', async () => {\n    const img = await page.$('.img-src-set')\n    const srcset = await img.getAttribute('srcset')\n    srcset.split(', ').forEach((s) => {\n      expect(s).toMatch(\n        isBuild\n          ? /\\/foo%20bar\\/other-assets\\/asset-[-\\w]{8}\\.png \\dx/\n          : /\\/foo%20bar\\/nested\\/asset\\.png \\dx/,\n      )\n    })\n  })\n})\n\ndescribe('svg fragments', () => {\n  // 404 is checked already, so here we just ensure the urls end with #fragment\n  test('img url', async () => {\n    const img = await page.$('.svg-frag-img')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-clock-view$/)\n  })\n\n  test('via css url()', async () => {\n    expect(await getBg('.icon')).toMatch(/svg#icon-clock-view\"\\)$/)\n  })\n\n  test('from js import', async () => {\n    const img = await page.$('.svg-frag-import')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-heart-view$/)\n  })\n})\n\ntest('?raw import', async () => {\n  expect(await page.textContent('.raw')).toMatch('SVG')\n})\n\ntest('?url import', async () => {\n  expect(await page.textContent('.url')).toMatch(\n    isBuild ? /\\/foo%20bar\\/other-assets\\/foo-[-\\w]{8}\\.js/ : '/foo.js',\n  )\n})\n\ntest('?url import on css', async () => {\n  const txt = await page.textContent('.url-css')\n  expect(txt).toMatch(\n    isBuild\n      ? /\\/foo%20bar\\/other-assets\\/icons-[-\\w]{8}\\.css/\n      : '/css/icons.css',\n  )\n})\n\ntest('new URL(..., import.meta.url)', async () => {\n  const urlImgMatch = isBuild\n    ? /\\/foo%20bar\\/other-assets\\/img-[-\\w]{8}\\.png/\n    : '/import-meta-url/img.png'\n  expect(await page.textContent('.import-meta-url')).toMatch(urlImgMatch)\n})\n\ntest('new URL(`${dynamic}`, import.meta.url)', async () => {\n  const dynamic1 = await page.textContent('.dynamic-import-meta-url-1')\n  expect(dynamic1).toMatch(absoluteIconMatch)\n  const dynamic2 = await page.textContent('.dynamic-import-meta-url-2')\n  expect(dynamic2).toMatch(urlAssetMatch)\n})\n\ntest('new URL(`non-existent`, import.meta.url)', async () => {\n  expect(await page.textContent('.non-existent-import-meta-url')).toMatch(\n    '/non-existent',\n  )\n})\n\ntest('inline style test', async () => {\n  expect(await getBg('.inline-style')).toMatch(urlAssetMatch)\n  expect(await getBg('.style-url-assets')).toMatch(urlAssetMatch)\n})\n\ntest('html import word boundary', async () => {\n  expect(await page.textContent('.obj-import-express')).toMatch(\n    'ignore object import prop',\n  )\n  expect(await page.textContent('.string-import-express')).toMatch('no load')\n})\n\ntest('relative path in html asset', async () => {\n  expect(await page.textContent('.relative-js')).toMatch('hello')\n  expect(await getColor('.relative-css')).toMatch('red')\n})\n"
  },
  {
    "path": "playground/assets/__tests__/relative-base/assets-relative-base.spec.ts",
    "content": "import { beforeAll, describe, expect, test } from 'vitest'\nimport {\n  browserLogs,\n  findAssetFile,\n  getBg,\n  getColor,\n  isBuild,\n  page,\n} from '~utils'\n\nconst absoluteAssetMatch = isBuild\n  ? /http.*\\/other-assets\\/asset-[-\\w]{8}\\.png/\n  : '/nested/asset.png'\n\n// Asset URLs in CSS are relative to the same dir, the computed\n// style returns the absolute URL in the test\nconst cssBgAssetMatch = absoluteAssetMatch\n\nconst iconMatch = `/icon.png`\n\nconst absoluteIconMatch = isBuild\n  ? /http.*\\/icon-[-\\w]{8}\\.png/\n  : '/nested/icon.png'\n\nconst absolutePublicIconMatch = isBuild ? /http.*\\/icon\\.png/ : '/icon.png'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe('raw references from /public', () => {\n  test('load raw js from /public', async () => {\n    expect(await page.textContent('.raw-js')).toMatch('[success]')\n  })\n\n  test('load raw css from /public', async () => {\n    expect(await getColor('.raw-css')).toBe('red')\n  })\n})\n\ntest('import-expression from simple script', async () => {\n  expect(await page.textContent('.import-expression')).toMatch(\n    '[success][success]',\n  )\n})\n\ndescribe('asset imports from js', () => {\n  test('relative', async () => {\n    expect(await page.textContent('.asset-import-relative')).toMatch(\n      cssBgAssetMatch,\n    )\n  })\n\n  test('absolute', async () => {\n    expect(await page.textContent('.asset-import-absolute')).toMatch(\n      cssBgAssetMatch,\n    )\n  })\n\n  test('from /public', async () => {\n    expect(await page.textContent('.public-import')).toMatch(\n      absolutePublicIconMatch,\n    )\n  })\n})\n\ndescribe('css url() references', () => {\n  test('fonts', async () => {\n    expect(\n      await page.evaluate(() => {\n        return (document as any).fonts.check('700 32px Inter')\n      }),\n    ).toBe(true)\n  })\n\n  test('relative', async () => {\n    const bg = await getBg('.css-url-relative')\n    expect(bg).toMatch(cssBgAssetMatch)\n  })\n\n  test('image-set relative', async () => {\n    const imageSet = await getBg('.css-image-set-relative')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('image-set without the url() call', async () => {\n    const imageSet = await getBg('.css-image-set-without-url-call')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('image-set with var', async () => {\n    const imageSet = await getBg('.css-image-set-with-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('image-set with mix', async () => {\n    const imageSet = await getBg('.css-image-set-mix-url-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('relative in @import', async () => {\n    expect(await getBg('.css-url-relative-at-imported')).toMatch(\n      cssBgAssetMatch,\n    )\n  })\n\n  test('absolute', async () => {\n    expect(await getBg('.css-url-absolute')).toMatch(cssBgAssetMatch)\n  })\n\n  test('from /public', async () => {\n    expect(await getBg('.css-url-public')).toMatch(iconMatch)\n  })\n\n  test('multiple urls on the same line', async () => {\n    const bg = await getBg('.css-url-same-line')\n    expect(bg).toMatch(cssBgAssetMatch)\n    expect(bg).toMatch(iconMatch)\n  })\n\n  test('aliased', async () => {\n    const bg = await getBg('.css-url-aliased')\n    expect(bg).toMatch(cssBgAssetMatch)\n  })\n\n  test('nested manual chunks', async () => {\n    const bg = await getBg('.css-manual-chunks-relative')\n    expect(bg).toMatch(cssBgAssetMatch)\n  })\n})\n\ndescribe.runIf(isBuild)('index.css URLs', () => {\n  let css: string\n  beforeAll(() => {\n    css = findAssetFile(/index.*\\.css$/, 'relative-base', 'other-assets')\n  })\n\n  test('relative asset URL', () => {\n    expect(css).toMatch(`./asset-`)\n  })\n\n  test('preserve postfix query/hash', () => {\n    expect(css).toMatch(`woff2?#iefix`)\n  })\n})\n\ndescribe('image', () => {\n  test('srcset', async () => {\n    const img = await page.$('.img-src-set')\n    const srcset = await img.getAttribute('srcset')\n    srcset.split(', ').forEach((s) => {\n      expect(s).toMatch(\n        isBuild\n          ? /other-assets\\/asset-[-\\w]{8}\\.png \\dx/\n          : /\\.\\/nested\\/asset\\.png \\dx/,\n      )\n    })\n  })\n})\n\ndescribe('svg fragments', () => {\n  // 404 is checked already, so here we just ensure the urls end with #fragment\n  test('img url', async () => {\n    const img = await page.$('.svg-frag-img')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-clock-view$/)\n  })\n\n  test('via css url()', async () => {\n    expect(await getBg('.icon')).toMatch(/svg#icon-clock-view\"\\)$/)\n  })\n\n  test('from js import', async () => {\n    const img = await page.$('.svg-frag-import')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-heart-view$/)\n  })\n})\n\ntest('?raw import', async () => {\n  expect(await page.textContent('.raw')).toMatch('SVG')\n})\n\ntest('?url import', async () => {\n  expect(await page.textContent('.url')).toMatch(\n    isBuild ? /http.*\\/other-assets\\/foo-[-\\w]{8}\\.js/ : `/foo.js`,\n  )\n})\n\ntest('?url import on css', async () => {\n  const txt = await page.textContent('.url-css')\n  expect(txt).toMatch(\n    isBuild ? /http.*\\/other-assets\\/icons-[-\\w]{8}\\.css/ : '/css/icons.css',\n  )\n  isBuild &&\n    expect(findAssetFile(/index.*\\.js$/, 'relative-base', 'entries')).toMatch(\n      /icons-.+\\.css(?!\\?used)/,\n    )\n})\n\ntest('new URL(..., import.meta.url)', async () => {\n  const absoluteImgMatch = isBuild\n    ? /http.*\\/other-assets\\/img-[-\\w]{8}\\.png/\n    : '/import-meta-url/img.png'\n  expect(await page.textContent('.import-meta-url')).toMatch(absoluteImgMatch)\n})\n\ntest('new URL(`${dynamic}`, import.meta.url)', async () => {\n  const dynamic1 = await page.textContent('.dynamic-import-meta-url-1')\n  expect(dynamic1).toMatch(absoluteIconMatch)\n  const dynamic2 = await page.textContent('.dynamic-import-meta-url-2')\n  expect(dynamic2).toMatch(absoluteAssetMatch)\n})\n\ntest('new URL(`non-existent`, import.meta.url)', async () => {\n  expect(await page.textContent('.non-existent-import-meta-url')).toMatch(\n    '/non-existent',\n  )\n})\n\ntest('inline style test', async () => {\n  expect(await getBg('.inline-style')).toMatch(cssBgAssetMatch)\n  expect(await getBg('.style-url-assets')).toMatch(cssBgAssetMatch)\n})\n\ntest('html import word boundary', async () => {\n  expect(await page.textContent('.obj-import-express')).toMatch(\n    'ignore object import prop',\n  )\n  expect(await page.textContent('.string-import-express')).toMatch('no load')\n})\n\ntest('relative path in html asset', async () => {\n  expect(await page.textContent('.relative-js')).toMatch('hello')\n  expect(await getColor('.relative-css')).toMatch('red')\n})\n"
  },
  {
    "path": "playground/assets/__tests__/runtime-base/assets-runtime-base.spec.ts",
    "content": "import { beforeAll, describe, expect, test } from 'vitest'\nimport {\n  browserLogs,\n  findAssetFile,\n  getBg,\n  getColor,\n  isBuild,\n  page,\n} from '~utils'\n\nconst absoluteAssetMatch = isBuild\n  ? /\\/other-assets\\/asset-[-\\w]{8}\\.png/\n  : '/nested/asset.png'\n\n// Asset URLs in CSS are relative to the same dir, the computed\n// style returns the absolute URL in the test\nconst cssBgAssetMatch = absoluteAssetMatch\n\nconst iconMatch = `/icon.png`\n\nconst absoluteIconMatch = isBuild\n  ? /\\/other-assets\\/icon-[-\\w]{8}\\.png/\n  : '/nested/icon.png'\n\nconst absolutePublicIconMatch = isBuild ? /\\/icon\\.png/ : '/icon.png'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe('raw references from /public', () => {\n  test('load raw js from /public', async () => {\n    expect(await page.textContent('.raw-js')).toMatch('[success]')\n  })\n\n  test('load raw css from /public', async () => {\n    expect(await getColor('.raw-css')).toBe('red')\n  })\n})\n\ntest('import-expression from simple script', async () => {\n  expect(await page.textContent('.import-expression')).toMatch(\n    '[success][success]',\n  )\n})\n\ndescribe('asset imports from js', () => {\n  test('relative', async () => {\n    expect(await page.textContent('.asset-import-relative')).toMatch(\n      cssBgAssetMatch,\n    )\n  })\n\n  test('absolute', async () => {\n    expect(await page.textContent('.asset-import-absolute')).toMatch(\n      cssBgAssetMatch,\n    )\n  })\n\n  test('from /public', async () => {\n    expect(await page.textContent('.public-import')).toMatch(\n      absolutePublicIconMatch,\n    )\n  })\n})\n\ndescribe('css url() references', () => {\n  test('fonts', async () => {\n    expect(\n      await page.evaluate(() => {\n        return (document as any).fonts.check('700 32px Inter')\n      }),\n    ).toBe(true)\n  })\n\n  test('relative', async () => {\n    const bg = await getBg('.css-url-relative')\n    expect(bg).toMatch(cssBgAssetMatch)\n  })\n\n  test('image-set relative', async () => {\n    const imageSet = await getBg('.css-image-set-relative')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('image-set without the url() call', async () => {\n    const imageSet = await getBg('.css-image-set-without-url-call')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('image-set with var', async () => {\n    const imageSet = await getBg('.css-image-set-with-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('image-set with mix', async () => {\n    const imageSet = await getBg('.css-image-set-mix-url-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(cssBgAssetMatch)\n    })\n  })\n\n  test('relative in @import', async () => {\n    expect(await getBg('.css-url-relative-at-imported')).toMatch(\n      cssBgAssetMatch,\n    )\n  })\n\n  test('absolute', async () => {\n    expect(await getBg('.css-url-absolute')).toMatch(cssBgAssetMatch)\n  })\n\n  test('from /public', async () => {\n    expect(await getBg('.css-url-public')).toMatch(iconMatch)\n  })\n\n  test('multiple urls on the same line', async () => {\n    const bg = await getBg('.css-url-same-line')\n    expect(bg).toMatch(cssBgAssetMatch)\n    expect(bg).toMatch(iconMatch)\n  })\n\n  test('aliased', async () => {\n    const bg = await getBg('.css-url-aliased')\n    expect(bg).toMatch(cssBgAssetMatch)\n  })\n})\n\ndescribe.runIf(isBuild)('index.css URLs', () => {\n  let css: string\n  beforeAll(() => {\n    css = findAssetFile(/index-[-\\w]{8}\\.css$/, 'runtime-base', 'other-assets')\n  })\n\n  test('relative asset URL', () => {\n    expect(css).toMatch(`./asset-`)\n  })\n\n  test('preserve postfix query/hash', () => {\n    expect(css).toMatch(`woff2?#iefix`)\n  })\n})\n\ndescribe('image', () => {\n  test('srcset', async () => {\n    const img = await page.$('.img-src-set')\n    const srcset = await img.getAttribute('srcset')\n    srcset.split(', ').forEach((s) => {\n      expect(s).toMatch(\n        isBuild\n          ? /other-assets\\/asset-[-\\w]{8}\\.png \\dx/\n          : /\\.\\/nested\\/asset\\.png \\dx/,\n      )\n    })\n  })\n})\n\ndescribe('svg fragments', () => {\n  // 404 is checked already, so here we just ensure the urls end with #fragment\n  test('img url', async () => {\n    const img = await page.$('.svg-frag-img')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-clock-view$/)\n  })\n\n  test('via css url()', async () => {\n    expect(await getBg('.icon')).toMatch(/svg#icon-clock-view\"\\)$/)\n  })\n\n  test('from js import', async () => {\n    const img = await page.$('.svg-frag-import')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-heart-view$/)\n  })\n})\n\ntest('?raw import', async () => {\n  expect(await page.textContent('.raw')).toMatch('SVG')\n})\n\ntest('?url import', async () => {\n  expect(await page.textContent('.url')).toMatch(\n    isBuild ? /\\/other-assets\\/foo-[-\\w]{8}\\.js/ : `/foo.js`,\n  )\n})\n\ntest('?url import on css', async () => {\n  const txt = await page.textContent('.url-css')\n  expect(txt).toMatch(\n    isBuild ? /\\/other-assets\\/icons-[-\\w]{8}\\.css/ : '/css/icons.css',\n  )\n})\n\ntest('new URL(..., import.meta.url)', async () => {\n  const absoluteImgMatch = isBuild\n    ? /http.*\\/other-assets\\/img-[-\\w]{8}\\.png/\n    : '/import-meta-url/img.png'\n  expect(await page.textContent('.import-meta-url')).toMatch(absoluteImgMatch)\n})\n\ntest('new URL(`${dynamic}`, import.meta.url)', async () => {\n  const dynamic1 = await page.textContent('.dynamic-import-meta-url-1')\n  expect(dynamic1).toMatch(absoluteIconMatch)\n  const dynamic2 = await page.textContent('.dynamic-import-meta-url-2')\n  expect(dynamic2).toMatch(absoluteAssetMatch)\n})\n\ntest('new URL(`non-existent`, import.meta.url)', async () => {\n  expect(await page.textContent('.non-existent-import-meta-url')).toMatch(\n    '/non-existent',\n  )\n})\n\ntest('inline style test', async () => {\n  expect(await getBg('.inline-style')).toMatch(cssBgAssetMatch)\n  expect(await getBg('.style-url-assets')).toMatch(cssBgAssetMatch)\n})\n\ntest('html import word boundary', async () => {\n  expect(await page.textContent('.obj-import-express')).toMatch(\n    'ignore object import prop',\n  )\n  expect(await page.textContent('.string-import-express')).toMatch('no load')\n})\n\ntest('relative path in html asset', async () => {\n  expect(await page.textContent('.relative-js')).toMatch('hello')\n  expect(await getColor('.relative-css')).toMatch('red')\n})\n"
  },
  {
    "path": "playground/assets/__tests__/url-base/assets-url-base.spec.ts",
    "content": "import { beforeAll, describe, expect, test } from 'vitest'\nimport {\n  browserLogs,\n  findAssetFile,\n  getBg,\n  getColor,\n  isBuild,\n  page,\n} from '~utils'\n\nconst urlAssetMatch = isBuild\n  ? /http:\\/\\/localhost:\\d+\\/other-assets\\/asset-[-\\w]{8}\\.png/\n  : '/nested/asset.png'\n\nconst iconMatch = '/icon.png'\n\nconst absoluteIconMatch = isBuild\n  ? /http:\\/\\/localhost:\\d+\\/.*\\/icon-[-\\w]{8}\\.png/\n  : '/nested/icon.png'\n\nconst absolutePublicIconMatch = isBuild\n  ? /http:\\/\\/localhost:\\d+\\/icon\\.png/\n  : '/icon.png'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe('raw references from /public', () => {\n  test('load raw js from /public', async () => {\n    expect(await page.textContent('.raw-js')).toMatch('[success]')\n  })\n\n  test('load raw css from /public', async () => {\n    expect(await getColor('.raw-css')).toBe('red')\n  })\n})\n\ntest('import-expression from simple script', async () => {\n  expect(await page.textContent('.import-expression')).toMatch(\n    '[success][success]',\n  )\n})\n\ndescribe('asset imports from js', () => {\n  test('relative', async () => {\n    expect(await page.textContent('.asset-import-relative')).toMatch(\n      urlAssetMatch,\n    )\n  })\n\n  test('absolute', async () => {\n    expect(await page.textContent('.asset-import-absolute')).toMatch(\n      urlAssetMatch,\n    )\n  })\n\n  test('from /public', async () => {\n    expect(await page.textContent('.public-import')).toMatch(\n      absolutePublicIconMatch,\n    )\n  })\n})\n\ndescribe('css url() references', () => {\n  test('fonts', async () => {\n    expect(\n      await page.evaluate(() => document.fonts.check('700 32px Inter')),\n    ).toBe(true)\n  })\n\n  test('relative', async () => {\n    const bg = await getBg('.css-url-relative')\n    expect(bg).toMatch(urlAssetMatch)\n  })\n\n  test('image-set relative', async () => {\n    const imageSet = await getBg('.css-image-set-relative')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('image-set without the url() call', async () => {\n    const imageSet = await getBg('.css-image-set-without-url-call')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('image-set with var', async () => {\n    const imageSet = await getBg('.css-image-set-with-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('image-set with mix', async () => {\n    const imageSet = await getBg('.css-image-set-mix-url-var')\n    imageSet.split(', ').forEach((s) => {\n      expect(s).toMatch(urlAssetMatch)\n    })\n  })\n\n  test('relative in @import', async () => {\n    expect(await getBg('.css-url-relative-at-imported')).toMatch(urlAssetMatch)\n  })\n\n  test('absolute', async () => {\n    expect(await getBg('.css-url-absolute')).toMatch(urlAssetMatch)\n  })\n\n  test('from /public', async () => {\n    expect(await getBg('.css-url-public')).toMatch(iconMatch)\n  })\n\n  test('multiple urls on the same line', async () => {\n    const bg = await getBg('.css-url-same-line')\n    expect(bg).toMatch(urlAssetMatch)\n    expect(bg).toMatch(iconMatch)\n  })\n\n  test('aliased', async () => {\n    const bg = await getBg('.css-url-aliased')\n    expect(bg).toMatch(urlAssetMatch)\n  })\n})\n\ndescribe.runIf(isBuild)('index.css URLs', () => {\n  let css: string\n  beforeAll(() => {\n    css = findAssetFile(/index.*\\.css$/, 'url-base', 'other-assets')\n  })\n\n  test('use base URL for asset URL', () => {\n    expect(css).toMatch(urlAssetMatch)\n  })\n\n  test('preserve postfix query/hash', () => {\n    expect(css).toMatch('woff2?#iefix')\n  })\n})\n\ndescribe('image', () => {\n  test('srcset', async () => {\n    const img = await page.$('.img-src-set')\n    const srcset = await img.getAttribute('srcset')\n    srcset.split(', ').forEach((s) => {\n      expect(s).toMatch(\n        isBuild\n          ? /other-assets\\/asset-[-\\w]{8}\\.png \\dx/\n          : /\\.\\/nested\\/asset\\.png \\dx/,\n      )\n    })\n  })\n})\n\ndescribe('svg fragments', () => {\n  // 404 is checked already, so here we just ensure the urls end with #fragment\n  test('img url', async () => {\n    const img = await page.$('.svg-frag-img')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-clock-view$/)\n  })\n\n  test('via css url()', async () => {\n    expect(await getBg('.icon')).toMatch(/svg#icon-clock-view\"\\)$/)\n  })\n\n  test('from js import', async () => {\n    const img = await page.$('.svg-frag-import')\n    expect(await img.getAttribute('src')).toMatch(/svg#icon-heart-view$/)\n  })\n})\n\ntest('?raw import', async () => {\n  expect(await page.textContent('.raw')).toMatch('SVG')\n})\n\ntest('?url import', async () => {\n  expect(await page.textContent('.url')).toMatch(\n    isBuild\n      ? /http:\\/\\/localhost:\\d+\\/other-assets\\/foo-[-\\w]{8}\\.js/\n      : '/foo.js',\n  )\n})\n\ntest('?url import on css', async () => {\n  const txt = await page.textContent('.url-css')\n  expect(txt).toMatch(\n    isBuild\n      ? /http:\\/\\/localhost:\\d+\\/other-assets\\/icons-[-\\w]{8}\\.css/\n      : '/css/icons.css',\n  )\n})\n\ntest('new URL(..., import.meta.url)', async () => {\n  const urlImgMatch = isBuild\n    ? /http:\\/\\/localhost:\\d+\\/other-assets\\/img-[-\\w]{8}\\.png/\n    : '/import-meta-url/img.png'\n  expect(await page.textContent('.import-meta-url')).toMatch(urlImgMatch)\n})\n\ntest('new URL(`${dynamic}`, import.meta.url)', async () => {\n  const dynamic1 = await page.textContent('.dynamic-import-meta-url-1')\n  expect(dynamic1).toMatch(absoluteIconMatch)\n  const dynamic2 = await page.textContent('.dynamic-import-meta-url-2')\n  expect(dynamic2).toMatch(urlAssetMatch)\n})\n\ntest('new URL(`non-existent`, import.meta.url)', async () => {\n  expect(await page.textContent('.non-existent-import-meta-url')).toMatch(\n    '/non-existent',\n  )\n})\n\ntest('inline style test', async () => {\n  expect(await getBg('.inline-style')).toMatch(urlAssetMatch)\n  expect(await getBg('.style-url-assets')).toMatch(urlAssetMatch)\n})\n\ntest('html import word boundary', async () => {\n  expect(await page.textContent('.obj-import-express')).toMatch(\n    'ignore object import prop',\n  )\n  expect(await page.textContent('.string-import-express')).toMatch('no load')\n})\n\ntest('relative path in html asset', async () => {\n  expect(await page.textContent('.relative-js')).toMatch('hello')\n  expect(await getColor('.relative-css')).toMatch('red')\n})\n"
  },
  {
    "path": "playground/assets/asset/main.js",
    "content": "function text(el, text) {\n  document.querySelector(el).textContent = text\n}\ntext('.relative-js', 'hello')\n"
  },
  {
    "path": "playground/assets/asset/style.css",
    "content": ".relative-css {\n  color: red;\n}\n"
  },
  {
    "path": "playground/assets/css/css-url-url.css",
    "content": ".css-url-svg-in-url {\n  background: url(../nested/fragment-bg-hmr2.svg);\n  background-size: 10px;\n}\n"
  },
  {
    "path": "playground/assets/css/css-url.css",
    "content": "@import './nested/at-imported-css-url.css';\n\n.css-url-absolute {\n  background: url(/nested/asset.png);\n  background-size: 10px;\n}\n\n.css-url-relative {\n  background: url(../nested/asset.png);\n  background-size: 10px;\n}\n\n.css-url-encoded {\n  background: url('/nested/asset%5Bsmall%5D.png');\n  background-size: 10px;\n}\n\n.css-image-set-relative {\n  background-image: -webkit-image-set(\n    url('../nested/asset.png') 1x,\n    url('../nested/asset.png') 2x\n  );\n  background-size: 10px;\n}\n\n.css-image-set-without-url-call {\n  background-image: -webkit-image-set(\n    '../nested/asset.png' 1x,\n    '../nested/asset.png' 2x\n  );\n  background-size: 10px;\n}\n\n.css-image-set-with-var {\n  --bg-img: url('../nested/asset.png');\n  background-image: -webkit-image-set(var(--bg-img) 1x, var(--bg-img) 2x);\n  background-size: 10px;\n}\n\n.css-image-set-mix-url-var {\n  --bg-img: url('../nested/asset.png');\n  background-image: -webkit-image-set(\n    var(--bg-img) 1x,\n    url('../nested/asset.png') 2x\n  );\n  background-size: 10px;\n}\n\n.css-image-set-base64 {\n  background-image: -webkit-image-set(\n    url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA0AgMAAACrwbOMAAADI2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1MDI2QjVGQTg3RUIxMUVBQUFDMkQ3NTM0MUZGNzU3RSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1MDI2QjVGOTg3RUIxMUVBQUFDMkQ3NTM0MUZGNzU3RSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBNzc3MDZDRjg3QUIxMUUzQjcwREVFMDM3NzA2QzEyMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBNzc3MDZEMDg3QUIxMUUzQjcwREVFMDM3NzA2QzEyMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqfCcbEAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAADFBMVEVBuoQ0R10/qn8/qX7FyuqbAAAABHRSTlP9/QGEiU0+GwAAAPtJREFUGBkFwbFNXEEUBdDD/QSWmE7YYAogWNeAaMfaEuiD5HfAk9yIAwqYwIGRRvt8zkNdvckrzzcfjqDccdPIYnH1AJ4ywLs7m53Fhkcw0+DLDxZn0PCHQrrg2xWOCpS7m6bFAj/ZDLFY/AJbDDZ/WUzR4B84BRoURBeAo4Si0CBMFvBEGMBmExYbi0loACcBjQKhC3AUQVGaRjBhMxAsFlwQDLYFBA04EaAVEHSBoxAoPmkITBYDAovNhsAAEwINTggAINCFoyCg0CBgYoCAjQsIACCgcYKABhCgHAUClAYCTAMIsF2AAAACtBMIQAEB+jcggE9AAC+A/zyyZDSXstCbAAAAAElFTkSuQmCC)\n      1x,\n    url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA0CAYAAADWr1sfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTAyNkI1RkE4N0VCMTFFQUFBQzJENzUzNDFGRjc1N0UiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTAyNkI1Rjk4N0VCMTFFQUFBQzJENzUzNDFGRjc1N0UiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTc3NzA2Q0Y4N0FCMTFFM0I3MERFRTAzNzcwNkMxMjMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTc3NzA2RDA4N0FCMTFFM0I3MERFRTAzNzcwNkMxMjMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6nwnGxAAAJtklEQVR42txZ6W9c1RU/970373nsJHgZ27FThahSV8BCqGQTlIQ2EiUBReqHVpT8Af0r+NA/ogpqqWiDKrZuKYQPLGEpAlEFiqOgICSUBOKQhDjxeGY885bb37n3TGKPZ+4bx0uWK53Ec+cu53fPfkbtfu13B4noF6AQVAEpah0ak3cUSBU8qh46RfWj50ltKJDXXyBKdMtibI+TXlLqm2C87y/+eO/vlVIVnWbUcShFyld8T19ypvLbZKpyALOjVPCqrUcT1mWXYtIzMUV7Rqn315tJJyk+J51OZwb7QA3QkQD/fAL6JWiIXKMOhkOPwp1DFE/OkJ6NAQxn+fhuPhaFOc8DE9loern+hD9SfJVCdaLdOy5gif9rpHfyHp3pCX5cs6X1PfnORkr+SA9FO4bsgkZm1ykngm8ZK06ll0EvgWY6SwDn1fGKcykVfriewh2D5oKskhhw5KmFzLO0MJdO1yfS87UD2Uxc0tXErM+qLYQ5XUspK8el9JvagXSmPmH2W4lfG3wHNMHciXnmIfj+OvCVga8sD+yMYHyZAZ8H/Qk06dySaiNljf/DB0vklWAB1RQqnS0WA18eQE0Dz0++rjyRluOJDHuzWkwZNAPgLPHfPIeHTK/EEzHWKt/zDdh2asBmUUnJg3TDB0rQIuYptby5x6RgPO/JxIes304p44V1DMAzKQUbe4xqa62h2vbFyWuxeUie1RKqvVmXG/sxOaYKPqliQKp3HmEOB43pWaxJaTPvUV6rdK3Z6FloGUt35yD54EGXEwvaU3nSPSIYF7D5T/mio1rzS7Jaa1we4YWDzb1GUpptqJ1OGUl7BJX+jS7HP/OKEPlgRH5/SP5AZMjrCTz+jtdQQckxauEZ/IZ4bKyhYEsv7h6GpmGuhnsznafORwQbtQKGY6F/gy64pMxPnF2JSQ33UM/ecWNX/PJG3RbYsn15qCiYTQdhr49j9m4jQd8zXlkFZv3d/B087SBM4OodC+5kJYIX5r09+8ZIDYYAn4gqOdFeEEwn2gFmMb0BesEpZeOxARAOJ4SXjLbDlljKcbaQ0ebwrRNLy409oH1Xz1H2xrRc3wfaYx1dm/sgQTyYMZ1wZ4nC+4es76gnC3lqP14QTFk7wDymQH8DnXKCZibKiQHY89gY+aUeGwcT66xaw40JMUnWn52t7NWVeKt5GNaUarw1naruxXn9Rrrz9jRjLsd5PtsfZY3aaBZo9tT5qnxKsExRizto59EOccRzJQomHAC0DzsOHxwy3lvXk8VxU1u1VJFPaSW5B177SRtfNaVnq08izNyjQl9UefFe4zNwdoTI4I8XTfznu3NUORYMiyKP10HvD4neZy7VzqBaHEOjnw5TsKnXfgaDRjKqxWuzzRKtTy/Wt2W1ZAukuyX9tr4Ns+vZpheAVfKoOCuDKrNzDB8Ysp9Znd2qnAnvh9r5I8+hDs86HRhfCIlyQqGgbuHDI0Sz9gHaZj0sQXhhpJhbktOVp5Kvak/x31Sg9rarRXVxXvjwKJxk0Z7N/sOjPEf1bCez7LS1Ji/0iduBAUAD6JDpRFsHqfDjDZRdTqyU26gn2ykkXUovzf2KCV66ZGxXL9YeVtsMMb9w1x0U/WTAADWqnGO4wvMhwdA14PmqfbLjClZdTkaqCFPrAor2byIvUsZrd5Syp4BaFYW8RUmDeG8+wwsVRY+Pk7c+MJpkChXfCfhkJ1XuBjCPV0Bvt0nhFwoPiQfbVjixgaKHho3qGSlbgIu9ti/VEdHifJkdVc2aRoizwnv7kT+nNuy5hxZeX3EtygM8DfoX6FPnCcxL1Yap6NGNCCFFk5x0ETra2i7v9TcWqbh3zIbASmzvcHP7qfA6vRzAJIH7JWeYktRPz2a2bHuoZKpEdjgWdBeoWboMTpwea4o3GiF1lXzZPWLh8Y3ca7oAPAd6E/RubjLCkgBz4fYhCu6cl2d73UmX13KSUcDecNugqX2Np9a5mvKu8Di3EoB5HAP9WboGnZMRFiiXb0MhhYjNOrbeVsc5DPPexEqXz+C9HufLHHPT3PyxIbwd6wZIt4DnxCG81lG1JT9miZiaGeVj8L0+m3I2UrdaezY/z65Auj9ab0vPNLOlp+fEGwtPb3cj3aUA5nEWdDA3GTGMpqT6AupFmLLpYWaL9Hag2XZZdVHqcR1cfGzchDhdyWwFpnKTjIPCG600YFad96S+rHeOzZ5tB7Et3jeItLNk8+Fa2j6jYnU2YSyhaNcwFe4dMHv5DD7L1WUTXt5zmtoyADe7Bwfn15cdHZix3cxIzB+ObC+q2Z1Q6pq0E6gynF0A715ErasbqQWbH9JOCC8zSwGwVMA8Phb3X3a2g5BnZ5cRT78Dj7trxMRR7liY+lhdu5ntVnFDFLm4N1a0nr2e5rVtysLDx0tl/noAc9X7TLNH5KxZuC1Tg6puH0SYKtoaumFrYWPbsS0xg+/2UbjVVkNXW67u8aHwkKwFYB6fgQ47nYXXBBSbEBPtGjUtnWy6YcEm/F1q5sLdkO5AQTonuap8Vu7+7HoYv17APF4Fve6KrabEkzhcuH+AAuTFGmmjkeScbdsU7hswxGtMkqJzM7PX5W5aa8BfSDdwyt30I9Nw44qn+MgYef1IKC42SLN9D4TU8+iYCWGmKSfdEceYkju/uBGAebwvDW53KcOeFxlYcBeqqd3DBiznyCHCUPCDdUTsweM0765M7np/OQwvF/A5aYOedDcKmo23zP5qsalovTfny9wL4xQyP18+KXedu5GAmx0G9pizrsrAJCOQsuovUPTIKIU/HzG/SPKczks97dnPODswXY5gBQDXxK72g3a0fURT5yoTY7nw5w6ksVcAzZq/C7mbcv+TO2rLZXYlJMzjtNjXBedN7IlBXuibtq3ph8W5vw1dkLNPrwSjKwWY89oXQf9xNgqaXruaWLulXK8cy5kvOvP3GwC4mWc/50wImj+xaLrmpFRugvPcUvPltQJMUr0cXcHzjpLrF82bAHBN1O+dFTjrHTmrdjMD5vER6B/LZLQmZ3y00sytBuC65LtvLeOMt+SM+q0AmMekNNbK17G3LHsnV4Ox1QLM4wNRy3gJe2LZ88FqMbWagL8CPe2sptpXQ0/L3lsOMGcW3Cv+O+hyF+svy9pjsveWA9z0tn8Afd7F2s9lbW01GVptwJxTHZfE3/Uj17SsOU7ddLRuYsDN8decDOyorFn1sVaAvyT7k8iZNt+dke++vJ0A8+CfMw+3mT8s39HtBviSgDs+b+64zF26HQHz+C/o+Xmfn5c5ul0BXyT7w/U5oTdlbs1GQGs/vgb9cd7fazr+L8AAD0zRYMSYHQAAAAAASUVORK5CYII=)\n      2x\n  );\n  background-size: 10px;\n}\n\n.css-image-set-gradient {\n  background-image: -webkit-image-set(\n    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA0AgMAAACrwbOMAAADI2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1MDI2QjVGQTg3RUIxMUVBQUFDMkQ3NTM0MUZGNzU3RSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1MDI2QjVGOTg3RUIxMUVBQUFDMkQ3NTM0MUZGNzU3RSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBNzc3MDZDRjg3QUIxMUUzQjcwREVFMDM3NzA2QzEyMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBNzc3MDZEMDg3QUIxMUUzQjcwREVFMDM3NzA2QzEyMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqfCcbEAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAADFBMVEVBuoQ0R10/qn8/qX7FyuqbAAAABHRSTlP9/QGEiU0+GwAAAPtJREFUGBkFwbFNXEEUBdDD/QSWmE7YYAogWNeAaMfaEuiD5HfAk9yIAwqYwIGRRvt8zkNdvckrzzcfjqDccdPIYnH1AJ4ywLs7m53Fhkcw0+DLDxZn0PCHQrrg2xWOCpS7m6bFAj/ZDLFY/AJbDDZ/WUzR4B84BRoURBeAo4Si0CBMFvBEGMBmExYbi0loACcBjQKhC3AUQVGaRjBhMxAsFlwQDLYFBA04EaAVEHSBoxAoPmkITBYDAovNhsAAEwINTggAINCFoyCg0CBgYoCAjQsIACCgcYKABhCgHAUClAYCTAMIsF2AAAACtBMIQAEB+jcggE9AAC+A/zyyZDSXstCbAAAAAElFTkSuQmCC'\n      1x,\n    linear-gradient(#e66465, #9198e5) 2x\n  );\n  background-size: 10px;\n}\n\n.css-image-set-multiple-descriptor {\n  background-image: -webkit-image-set(\n    '../nested/asset.png' type('image/png') 1x,\n    '../nested/asset.png' type('image/png') 2x\n  );\n  background-size: 10px;\n}\n\n.css-url-public {\n  background: url('/icon.png');\n  background-size: 10px;\n}\n\n.css-url-data-uri {\n  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA0CAYAAADWr1sfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTAyNkI1RkE4N0VCMTFFQUFBQzJENzUzNDFGRjc1N0UiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTAyNkI1Rjk4N0VCMTFFQUFBQzJENzUzNDFGRjc1N0UiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTc3NzA2Q0Y4N0FCMTFFM0I3MERFRTAzNzcwNkMxMjMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTc3NzA2RDA4N0FCMTFFM0I3MERFRTAzNzcwNkMxMjMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6nwnGxAAAJtklEQVR42txZ6W9c1RU/970373nsJHgZ27FThahSV8BCqGQTlIQ2EiUBReqHVpT8Af0r+NA/ogpqqWiDKrZuKYQPLGEpAlEFiqOgICSUBOKQhDjxeGY885bb37n3TGKPZ+4bx0uWK53Ec+cu53fPfkbtfu13B4noF6AQVAEpah0ak3cUSBU8qh46RfWj50ltKJDXXyBKdMtibI+TXlLqm2C87y/+eO/vlVIVnWbUcShFyld8T19ypvLbZKpyALOjVPCqrUcT1mWXYtIzMUV7Rqn315tJJyk+J51OZwb7QA3QkQD/fAL6JWiIXKMOhkOPwp1DFE/OkJ6NAQxn+fhuPhaFOc8DE9loern+hD9SfJVCdaLdOy5gif9rpHfyHp3pCX5cs6X1PfnORkr+SA9FO4bsgkZm1ykngm8ZK06ll0EvgWY6SwDn1fGKcykVfriewh2D5oKskhhw5KmFzLO0MJdO1yfS87UD2Uxc0tXErM+qLYQ5XUspK8el9JvagXSmPmH2W4lfG3wHNMHciXnmIfj+OvCVga8sD+yMYHyZAZ8H/Qk06dySaiNljf/DB0vklWAB1RQqnS0WA18eQE0Dz0++rjyRluOJDHuzWkwZNAPgLPHfPIeHTK/EEzHWKt/zDdh2asBmUUnJg3TDB0rQIuYptby5x6RgPO/JxIes304p44V1DMAzKQUbe4xqa62h2vbFyWuxeUie1RKqvVmXG/sxOaYKPqliQKp3HmEOB43pWaxJaTPvUV6rdK3Z6FloGUt35yD54EGXEwvaU3nSPSIYF7D5T/mio1rzS7Jaa1we4YWDzb1GUpptqJ1OGUl7BJX+jS7HP/OKEPlgRH5/SP5AZMjrCTz+jtdQQckxauEZ/IZ4bKyhYEsv7h6GpmGuhnsznafORwQbtQKGY6F/gy64pMxPnF2JSQ33UM/ecWNX/PJG3RbYsn15qCiYTQdhr49j9m4jQd8zXlkFZv3d/B087SBM4OodC+5kJYIX5r09+8ZIDYYAn4gqOdFeEEwn2gFmMb0BesEpZeOxARAOJ4SXjLbDlljKcbaQ0ebwrRNLy409oH1Xz1H2xrRc3wfaYx1dm/sgQTyYMZ1wZ4nC+4es76gnC3lqP14QTFk7wDymQH8DnXKCZibKiQHY89gY+aUeGwcT66xaw40JMUnWn52t7NWVeKt5GNaUarw1naruxXn9Rrrz9jRjLsd5PtsfZY3aaBZo9tT5qnxKsExRizto59EOccRzJQomHAC0DzsOHxwy3lvXk8VxU1u1VJFPaSW5B177SRtfNaVnq08izNyjQl9UefFe4zNwdoTI4I8XTfznu3NUORYMiyKP10HvD4neZy7VzqBaHEOjnw5TsKnXfgaDRjKqxWuzzRKtTy/Wt2W1ZAukuyX9tr4Ns+vZpheAVfKoOCuDKrNzDB8Ysp9Znd2qnAnvh9r5I8+hDs86HRhfCIlyQqGgbuHDI0Sz9gHaZj0sQXhhpJhbktOVp5Kvak/x31Sg9rarRXVxXvjwKJxk0Z7N/sOjPEf1bCez7LS1Ji/0iduBAUAD6JDpRFsHqfDjDZRdTqyU26gn2ykkXUovzf2KCV66ZGxXL9YeVtsMMb9w1x0U/WTAADWqnGO4wvMhwdA14PmqfbLjClZdTkaqCFPrAor2byIvUsZrd5Syp4BaFYW8RUmDeG8+wwsVRY+Pk7c+MJpkChXfCfhkJ1XuBjCPV0Bvt0nhFwoPiQfbVjixgaKHho3qGSlbgIu9ti/VEdHifJkdVc2aRoizwnv7kT+nNuy5hxZeX3EtygM8DfoX6FPnCcxL1Yap6NGNCCFFk5x0ETra2i7v9TcWqbh3zIbASmzvcHP7qfA6vRzAJIH7JWeYktRPz2a2bHuoZKpEdjgWdBeoWboMTpwea4o3GiF1lXzZPWLh8Y3ca7oAPAd6E/RubjLCkgBz4fYhCu6cl2d73UmX13KSUcDecNugqX2Np9a5mvKu8Di3EoB5HAP9WboGnZMRFiiXb0MhhYjNOrbeVsc5DPPexEqXz+C9HufLHHPT3PyxIbwd6wZIt4DnxCG81lG1JT9miZiaGeVj8L0+m3I2UrdaezY/z65Auj9ab0vPNLOlp+fEGwtPb3cj3aUA5nEWdDA3GTGMpqT6AupFmLLpYWaL9Hag2XZZdVHqcR1cfGzchDhdyWwFpnKTjIPCG600YFad96S+rHeOzZ5tB7Et3jeItLNk8+Fa2j6jYnU2YSyhaNcwFe4dMHv5DD7L1WUTXt5zmtoyADe7Bwfn15cdHZix3cxIzB+ObC+q2Z1Q6pq0E6gynF0A715ErasbqQWbH9JOCC8zSwGwVMA8Phb3X3a2g5BnZ5cRT78Dj7trxMRR7liY+lhdu5ntVnFDFLm4N1a0nr2e5rVtysLDx0tl/noAc9X7TLNH5KxZuC1Tg6puH0SYKtoaumFrYWPbsS0xg+/2UbjVVkNXW67u8aHwkKwFYB6fgQ47nYXXBBSbEBPtGjUtnWy6YcEm/F1q5sLdkO5AQTonuap8Vu7+7HoYv17APF4Fve6KrabEkzhcuH+AAuTFGmmjkeScbdsU7hswxGtMkqJzM7PX5W5aa8BfSDdwyt30I9Nw44qn+MgYef1IKC42SLN9D4TU8+iYCWGmKSfdEceYkju/uBGAebwvDW53KcOeFxlYcBeqqd3DBiznyCHCUPCDdUTsweM0765M7np/OQwvF/A5aYOedDcKmo23zP5qsalovTfny9wL4xQyP18+KXedu5GAmx0G9pizrsrAJCOQsuovUPTIKIU/HzG/SPKczks97dnPODswXY5gBQDXxK72g3a0fURT5yoTY7nw5w6ksVcAzZq/C7mbcv+TO2rLZXYlJMzjtNjXBedN7IlBXuibtq3ph8W5vw1dkLNPrwSjKwWY89oXQf9xNgqaXruaWLulXK8cy5kvOvP3GwC4mWc/50wImj+xaLrmpFRugvPcUvPltQJMUr0cXcHzjpLrF82bAHBN1O+dFTjrHTmrdjMD5vER6B/LZLQmZ3y00sytBuC65LtvLeOMt+SM+q0AmMekNNbK17G3LHsnV4Ox1QLM4wNRy3gJe2LZ88FqMbWagL8CPe2sptpXQ0/L3lsOMGcW3Cv+O+hyF+svy9pjsveWA9z0tn8Afd7F2s9lbW01GVptwJxTHZfE3/Uj17SsOU7ddLRuYsDN8decDOyorFn1sVaAvyT7k8iZNt+dke++vJ0A8+CfMw+3mT8s39HtBviSgDs+b+64zF26HQHz+C/o+Xmfn5c5ul0BXyT7w/U5oTdlbs1GQGs/vgb9cd7fazr+L8AAD0zRYMSYHQAAAAAASUVORK5CYII=);\n  background-size: 10px;\n}\n\n.css-url-base64-inline {\n  background: url(../nested/icon.png);\n  background-size: 10px;\n}\n\n.css-url-quotes-base64-inline {\n  background: url('../nested/icon.png');\n  background-size: 10px;\n}\n\n.css-url-same-line {\n  background:\n    url('/nested/asset.png') top right / 10px no-repeat,\n    url('/icon.png') bottom right / 10px no-repeat;\n}\n\n.css-url-aliased {\n  background: url('@/asset.png');\n  background-size: 10px;\n}\n\n.css-url-preinlined-svg {\n  background: url('data:image/svg+xml,<svg fill=\"black\" width=\"48\" height=\"48\" viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M30.74,15.95c-.01-.1-.04-.2-.09-.28,0-.01,0-.03-.01-.05l-5.57-8.6c-.19-.29-.56-.42-.89-.3C8.21,12.62,3.37,14.48,1.9,15.3c-.27,.04-.5,.21-.59,.46-.05,.09-.05,.17-.05,.26v8.38c0,.41,.34,.75,.75,.75H30c.41,0,.75-.34,.75-.75v-8.38s0-.01,0-.02c0-.02,0-.04-.01-.06Zm-6.61-7.62l4.49,6.94H5.7c4.42-1.73,12.41-4.72,18.43-6.94Zm5.12,15.32H2.75v-6.88H29.25v6.88Z\"/><path d=\"M6.16,21.34c.99,0,1.79-.8,1.79-1.79s-.8-1.79-1.79-1.79-1.79,.8-1.79,1.79,.8,1.79,1.79,1.79Zm0-2.08c.16,0,.29,.13,.29,.29s-.13,.29-.29,.29-.29-.13-.29-.29,.13-.29,.29-.29Z\"/><path d=\"M15.15,23.04c.99,0,1.79-.8,1.79-1.79s-.8-1.79-1.79-1.79-1.79,.8-1.79,1.79,.8,1.79,1.79,1.79Zm0-2.08c.16,0,.29,.13,.29,.29s-.13,.29-.29,.29-.29-.13-.29-.29,.13-.29,.29-.29Z\"/><path d=\"M24.28,20.73c.99,0,1.79-.8,1.79-1.79s-.8-1.79-1.79-1.79-1.79,.8-1.79,1.79,.8,1.79,1.79,1.79Zm0-2.08c.16,0,.29,.13,.29,.29s-.13,.29-.29,.29-.29-.13-.29-.29,.13-.29,.29-.29Z\"/><path d=\"M22.78,10.16c-.99,0-1.79,.8-1.79,1.79s.8,1.79,1.79,1.79,1.79-.8,1.79-1.79-.8-1.79-1.79-1.79Zm0,2.08c-.16,0-.29-.13-.29-.29s.13-.29,.29-.29,.29,.13,.29,.29-.13,.29-.29,.29Z\"/></svg>');\n  background-size: 20px;\n}\n\n/*\nurls inside comments should be ignored\n\n.css-url-relative {\n  background: url(../nested/non-existent.png);\n  background-size: 10px;\n}\n*/\n\n.css-url-svg {\n  background: url(../nested/fragment-bg-hmr.svg);\n  background-size: 10px;\n}\n\n.css-image-set-svg {\n  background: -webkit-image-set(\n    url('../nested/fragment-bg.svg') 1x,\n    url('../nested/fragment-bg.svg') 2x\n  );\n  background-size: 10px;\n}\n\n.css-url-non-inline-hmr {\n  background: url(../nested/donuts-large.svg);\n  background-size: 20px;\n}\n"
  },
  {
    "path": "playground/assets/css/fonts.css",
    "content": "@font-face {\n  font-family: 'Inter';\n  font-style: italic;\n  font-weight: 400;\n  font-display: swap;\n  src:\n    url('../fonts/Inter-Italic.woff2?#iefix') format('woff2'),\n    url('/fonts/Inter-Italic.woff') format('woff');\n}\n\nbody {\n  font-family: 'Inter';\n}\n"
  },
  {
    "path": "playground/assets/css/foo.module.css",
    "content": ".foo-module {\n  color: red;\n}\n"
  },
  {
    "path": "playground/assets/css/icons.css",
    "content": "img {\n  width: 32px;\n  height: 32px;\n}\n\n.icon {\n  display: inline-block;\n  width: 32px;\n  height: 32px;\n}\n\n.icon-clock {\n  background: url(../nested/fragment-bg.svg#icon-clock-view) no-repeat;\n}\n\n.icon-heart {\n  background: url(../nested/fragment-bg.svg#icon-heart-view) no-repeat;\n}\n\n.icon-arrow-right {\n  background: url(../nested/fragment-bg.svg#icon-arrow-right-view) no-repeat;\n}\n\n.icon-clock-alias {\n  background: url('fragment#icon-clock-view') no-repeat;\n}\n"
  },
  {
    "path": "playground/assets/css/import.css",
    "content": ".import-css {\n  color: #0088ff;\n}\n"
  },
  {
    "path": "playground/assets/css/manual-chunks.css",
    "content": ".css-manual-chunks-relative {\n  background: url(../nested/asset.png);\n  background-size: 10px;\n}\n"
  },
  {
    "path": "playground/assets/css/nested/at-imported-css-url.css",
    "content": ".css-url-relative-at-imported {\n  background: url(../../nested/asset.png);\n  background-size: 10px;\n}\n"
  },
  {
    "path": "playground/assets/foo.js",
    "content": "console.log('hi')\n"
  },
  {
    "path": "playground/assets/index.html",
    "content": "<!doctype html>\n\n<head>\n  <meta charset=\"UTF-8\" />\n  <link class=\"ico\" rel=\"icon\" type=\"image/svg+xml\" href=\"favicon.ico\" />\n  <link rel=\"manifest\" href=\"manifest.json\" />\n  <meta\n    class=\"meta-og-image\"\n    property=\"og:image\"\n    content=\"./nested/asset.png\"\n  />\n</head>\n\n<link class=\"data-href\" rel=\"icon\" href=\"data:,\" />\n<link rel=\"stylesheet\" href=\"/raw.css\" />\n\n<h1>Assets</h1>\n\n<p class=\"base\"></p>\n\n<h2>Raw References from publicDir</h2>\n<ul>\n  <li class=\"raw-js\"></li>\n  <script src=\"/raw.js\"></script>\n  <li class=\"raw-css\">\n    Raw CSS from publicDir should load (this should be red)\n  </li>\n</ul>\n\n<h2>Asset Imports from JS</h2>\n<ul>\n  <li>Relative: <code class=\"asset-import-relative\"></code></li>\n  <li>Absolute: <code class=\"asset-import-absolute\"></code></li>\n  <li>From publicDir: <code class=\"public-import\"></code></li>\n  <li>\n    From publicDir (json): <code class=\"public-json-import\"></code> Content:\n    <code class=\"public-json-import-content\"></code>\n  </li>\n  <li>\n    From publicDir (js): <code class=\"public-js-import\"></code> Content:\n    <code class=\"public-js-import-content\"></code> Content-Type:\n    <code class=\"public-js-import-content-type\"></code>\n  </li>\n  <li>\n    From publicDir (ts): <code class=\"public-ts-import\"></code> Content:\n    <code class=\"public-ts-import-content\"></code> Content-Type:\n    <code class=\"public-ts-import-content-type\"></code>\n  </li>\n  <li>\n    From publicDir (mts): <code class=\"public-mts-import\"></code> Content:\n    <code class=\"public-mts-import-content\"></code> Content-Type:\n    <code class=\"public-mts-import-content-type\"></code>\n  </li>\n</ul>\n\n<h2>CSS url references</h2>\n<div>Font should be loaded (all text should be italic)</div>\n<div class=\"css-url-absolute\">\n  <span style=\"background: #fff\">CSS background (absolute)</span>\n</div>\n<div class=\"css-url-relative\">\n  <span style=\"background: #fff\">CSS background (relative)</span>\n</div>\n<div class=\"css-url-encoded\">\n  <span style=\"background: #fff\">CSS background (encoded)</span>\n</div>\n<div class=\"css-image-set-relative\">\n  <span style=\"background: #fff\"\n    >CSS background with image-set() (relative)</span\n  >\n</div>\n<div class=\"css-image-set-without-url-call\">\n  <span style=\"background: #fff\"\n    >CSS background with image-set() (relative)</span\n  >\n</div>\n<div class=\"css-image-set-with-var\">\n  <span style=\"background: #fff\">\n    CSS background image-set() (relative in var)\n  </span>\n</div>\n<div class=\"css-image-set-mix-url-var\">\n  <span style=\"background: #fff\">\n    CSS background image-set() (mix var and url)\n  </span>\n</div>\n<div class=\"css-image-set-base64\">\n  <span style=\"background: #fff\">\n    CSS background image-set() (with base64)\n  </span>\n</div>\n<div class=\"css-image-set-gradient\">\n  <span style=\"background: #fff\">\n    CSS background image-set() (with gradient)\n  </span>\n</div>\n<div class=\"css-image-set-multiple-descriptor\">\n  <span style=\"background: #fff\">\n    CSS background image-set() (with multiple descriptor)\n  </span>\n</div>\n<div\n  class=\"css-image-set-multiple-descriptor-inline-style\"\n  style=\"\n    background-image: -webkit-image-set(\n      './nested/asset.png' type('image/png') 1x,\n      './nested/asset.png' type('image/png') 2x\n    );\n    background-size: 10px;\n  \"\n>\n  <span style=\"background: #fff\">\n    CSS background image-set() inline style (with multiple descriptor)\n  </span>\n</div>\n<div\n  class=\"image-set-and-url-exsiting-at-same-time\"\n  style=\"\n    background-image:\n      image-set(url('./nested/asset.png')), url('./nested/asset.png');\n    background-size: 10px 10px;\n  \"\n>\n  <span style=\"background: #fff\"\n    >CSS background image-set() and url existing at the same time</span\n  >\n</div>\n<div class=\"css-url-relative-at-imported\">\n  <span style=\"background: #fff\"\n    >CSS background (relative from @imported file in different dir)</span\n  >\n</div>\n<div class=\"css-url-public\">\n  <span style=\"background: #fff\">CSS background (public)</span>\n</div>\n<div class=\"css-url-data-uri\">\n  <span style=\"background: #fff\">CSS background (data URI)</span>\n</div>\n<div class=\"css-url-base64-inline\">\n  <span style=\"background: #fff\">CSS background (base64 inline in prod)</span>\n</div>\n<div class=\"css-url-quotes-base64-inline\">\n  <span style=\"background: #fff\">CSS background (base64 inline in prod)</span>\n</div>\n<div class=\"css-url-same-line\">\n  <span style=\"background: #fff\"\n    >CSS background (multiple urls on same line)</span\n  >\n</div>\n<div class=\"css-url-aliased\">\n  <span style=\"background: #fff\">CSS background (aliased)</span>\n</div>\n<div class=\"css-url-preinlined-svg\">\n  <span style=\"background: #fff\">CSS background (pre inlined SVG)</span>\n</div>\n<div class=\"css-manual-chunks-relative\">\n  <span style=\"background: #fff\"\n    >CSS nested manual chunks relative base background</span\n  >\n</div>\n\n<div class=\"css-url-svg\">\n  <span style=\"background: #fff\">CSS SVG background</span>\n</div>\n<div class=\"css-url-svg-in-url\">\n  <span style=\"background: #fff\">CSS (?url) SVG background</span>\n</div>\n\n<div class=\"css-image-set-svg\">\n  <span style=\"background: #fff\">CSS SVG background with image-set</span>\n</div>\n\n<div class=\"css-url-non-inline-hmr\">\n  <span style=\"background: #fff\">CSS non-inlined background HMR</span>\n</div>\n\n<h2>Unicode URL</h2>\n<div>\n  <code class=\"unicode-url\"></code>\n  <img src=\"./nested/テスト-測試-white space.png\" />\n</div>\n\n<h2>Filename including single quote</h2>\n<div>\n  <code class=\"filename-including-single-quote\"></code>\n</div>\n\n<h2>Filename including percent</h2>\n<div>\n  <code class=\"percent-url\"></code>\n  <img src=\"./asset/percent%25.png\" />\n</div>\n\n<h2>encodeURI for the address</h2>\n<div>\n  <img\n    class=\"encodeURI\"\n    src=\"./nested/%E3%83%86%E3%82%B9%E3%83%88-%E6%B8%AC%E8%A9%A6-white%20space.png\"\n  />\n</div>\n\n<h2>Image Src Set</h2>\n<div>\n  <img\n    class=\"img-src-set\"\n    src=\"./nested/asset.png\"\n    srcset=\"./nested/asset.png 1x, ./nested/asset.png 2x\"\n    alt=\"\"\n  />\n  <img\n    class=\"img-src-set-public\"\n    src=\"/icon space.png\"\n    srcset=\"/icon.png 1x, /icon.png 2x\"\n    alt=\"\"\n  />\n  <img\n    class=\"img-src-set-mixed\"\n    src=\"/icon.png\"\n    srcset=\"https://vite.dev/logo-with-shadow.png 1x, ./nested/asset.png 2x\"\n    alt=\"\"\n  />\n</div>\n\n<h2>HTML only asset</h2>\n<div>\n  <img class=\"img-src\" src=\"./nested/html-only-asset.jpg\" alt=\"\" />\n</div>\n\n<h2>HTML inline asset</h2>\n<div>\n  <img class=\"img-src-inline\" src=\"./nested/inlined.svg\" alt=\"\" />\n</div>\n\n<h2>SVG Fragments</h2>\n<div>\n  <img\n    class=\"svg-frag-img\"\n    src=\"./nested/fragment.svg#icon-clock-view\"\n    alt=\"\"\n  />\n  <img\n    class=\"svg-frag-img\"\n    src=\"./nested/fragment.svg#icon-heart-view\"\n    alt=\"\"\n  />\n  <img\n    class=\"svg-frag-img\"\n    src=\"./nested/fragment.svg#icon-arrow-right-view\"\n    alt=\"\"\n  />\n</div>\n\n<h2>SVG Fragments via CSS background url</h2>\n<div>\n  <span class=\"icon icon-clock\"></span>\n  <span class=\"icon icon-heart\"></span>\n  <span class=\"icon icon-arrow-right\"></span>\n  <span class=\"icon icon-clock-alias\"></span>\n</div>\n\n<h2>SVG Fragments via JS Import</h2>\n<div>\n  <p>Imported path: <code class=\"svg-frag-import-path\"></code></p>\n  <img class=\"svg-frag-import\" alt=\"\" />\n</div>\n\n<h2>Unknown extension assets import</h2>\n<code class=\"unknown-ext\"></code>\n\n<h2>?raw import</h2>\n<code class=\"raw\"></code>\n<code class=\"raw-html\"></code>\n\n<h2>?no-inline svg import</h2>\n<code class=\"no-inline-svg\"></code>\n\n<h2>?no-inline svg import -- multiple postfix</h2>\n<code class=\"no-inline-svg-mp\"></code>\n\n<h2>?inline png import</h2>\n<code class=\"inline-png\"></code>\n\n<h2>?inline public png import</h2>\n<code class=\"inline-public-png\"></code>\n\n<h2>?url&inline public json import</h2>\n<code class=\"inline-public-json\"></code>\n\n<h2>?url import</h2>\n<code class=\"url\"></code>\n\n<h2>?url import with css</h2>\n<code class=\"url-css\"></code>\n\n<h2>new URL('...', import.meta.url)</h2>\n<img class=\"import-meta-url-img\" />\n<code class=\"import-meta-url\"></code>\n\n<h2>new URL('@/...', import.meta.url)</h2>\n<img class=\"import-meta-url-dep-img\" />\n<code class=\"import-meta-url-dep\"></code>\n\n<h2>new URL('/...', import.meta.url)</h2>\n<img class=\"import-meta-url-base-path-img\" />\n<code class=\"import-meta-url-base-path\"></code>\n\n<h2>new URL('data:...', import.meta.url)</h2>\n<img class=\"import-meta-url-data-uri-img\" />\n<code class=\"import-meta-url-data-uri\"></code>\n\n<h2>new URL('...', import.meta.url (without extension))</h2>\n<p>\n  <code class=\"import-meta-url-content-without-extension\"></code>\n</p>\n<p>\n  <code class=\"import-meta-url-without-extension\"></code>\n</p>\n\n<h2>new URL('...', import.meta.url,) (with comma)</h2>\n<img class=\"import-meta-url-img-comma\" />\n<code class=\"import-meta-url-comma\"></code>\n\n<h2>new URL('...', import.meta.url,) (with comma + new line)</h2>\n<img class=\"import-meta-url-img-comma-nl\" />\n<code class=\"import-meta-url-comma-nl\"></code>\n\n<h2>new URL(`./${dynamic}`, import.meta.url)</h2>\n<p>\n  <img class=\"dynamic-import-meta-url-img-1\" />\n  <code class=\"dynamic-import-meta-url-1\"></code>\n</p>\n<p>\n  <img class=\"dynamic-import-meta-url-img-2\" />\n  <code class=\"dynamic-import-meta-url-2\"></code>\n</p>\n<p>\n  <code class=\"dynamic-import-meta-url-js\"></code>\n</p>\n\n<h2>new URL(`./${dynamic}`, import.meta.url,) (with comma)</h2>\n<p>\n  <img class=\"dynamic-import-meta-url-img-1-comma\" />\n  <code class=\"dynamic-import-meta-url-1-comma\"></code>\n</p>\n<p>\n  <img class=\"dynamic-import-meta-url-img-2-comma\" />\n  <code class=\"dynamic-import-meta-url-2-comma\"></code>\n</p>\n\n<h2>new URL(`./${dynamic}?abc`, import.meta.url)</h2>\n<p>\n  <img class=\"dynamic-import-meta-url-img-1-query\" />\n  <code class=\"dynamic-import-meta-url-1-query\"></code>\n</p>\n<p>\n  <img class=\"dynamic-import-meta-url-img-2-query\" />\n  <code class=\"dynamic-import-meta-url-2-query\"></code>\n</p>\n\n<h2>new URL(`./${1 === 0 ? static : dynamic}?abc`, import.meta.url)</h2>\n<p>\n  <img class=\"dynamic-import-meta-url-img-1-ternary\" />\n  <code class=\"dynamic-import-meta-url-1-ternary\"></code>\n</p>\n<p>\n  <img class=\"dynamic-import-meta-url-img-2-ternary\" />\n  <code class=\"dynamic-import-meta-url-2-ternary\"></code>\n</p>\n\n<h2>new URL(/* @vite-ignore */ 'non-existent', import.meta.url)</h2>\n<p>\n  <code class=\"non-existent-import-meta-url\"></code>\n</p>\n\n<h2>new URL(`${dynamic}`, import.meta.url)</h2>\n<p>\n  <code class=\"dynamic-import-meta-url-all\"></code>\n</p>\n\n<h2>Multiline new URL(..., import.meta.url)</h2>\n<code class=\"import-meta-url-multiline\"></code>\n\n<h2>simple script tag import-expression</h2>\n<code class=\"import-expression\"></code>\n<code class=\"obj-import-express\"></code>\n<code class=\"string-import-express\"></code>\n<script>\n  const obj = {\n    import(t) {\n      text('.obj-import-express', t)\n    },\n  }\n  const stringImport = \"const t = import('package')\"\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n  import('./static/import-expression.js')\n  import('/import-expression.js')\n  // import('./static/raw.js')\n  /* import('./static/raw.js') */\n  obj.import('ignore object import prop')\n  try {\n    text('.string-import-express', t)\n  } catch {\n    text('.string-import-express', 'no load')\n  }\n</script>\n<h2>url in style tag</h2>\n<h3>url</h3>\n<style class=\"style-url\">\n  .style-url-assets {\n    background: url('./nested/asset.png');\n    background-size: 10px 10px;\n  }\n</style>\n<div\n  class=\"inline-style\"\n  style=\"background: url('./nested/asset.png'); background-size: 10px 10px\"\n>\n  inline style\n</div>\n<div class=\"style-url-assets\">use style class</div>\n\n<h3>base64</h3>\n<style class=\"style-base64\">\n  .style-base64-assets {\n    background: url('./static/icon.png');\n  }\n</style>\n<p class=\"inline-style-base64\" style=\"background: url(./static/icon.png)\">\n  inline style\n</p>\n<p class=\"style-base64-assets\">use style class</p>\n<h3>from publicDir</h3>\n<style>\n  .style-public-assets {\n    background: url('/icon.png');\n  }\n</style>\n<p class=\"inline-style-public\" style=\"background: url(/icon.png)\">\n  inline style\n</p>\n<p class=\"style-public-assets\">use style class</p>\n\n<h3 class=\"import-css\">@import</h3>\n<style class=\"style-import\">\n  @import url('./css/import.css');\n</style>\n\n<h3 class=\"foo-public\">\n  @import CSS from publicDir should load (this should be red)\n</h3>\n<h3 id=\"foo\">import module css</h3>\n\n<h3 class=\"raw-query\"></h3>\n\n<h3>style in svg</h3>\n<svg viewBox=\"0 0 512 512\" width=\"21\" height=\"21\" class=\"style-insvg\">\n  <style>\n    .style-insvg-color {\n      fill: #0088ff;\n    }\n  </style>\n  <g class=\"style-insvg-color\">\n    <rect x=\"224\" y=\"352\" width=\"64\" height=\"64\" />\n    <path\n      d=\"M128 128v96h64v-96h96v96h-32v32h-32v64h64v-64h64V128h-32V96H160v32h-32z\"\n    />\n  </g>\n</svg>\n\n<h3>assets in noscript</h3>\n<noscript>\n  <img class=\"noscript\" src=\"./nested/asset.png\" />\n</noscript>\n\n<h3>assets in template</h3>\n<template>\n  <img class=\"template\" src=\"./nested/asset.png\" />\n</template>\n\n<link rel=\"stylesheet\" href=\"asset/style.css\" />\n<div class=\"relative-css\">link style</div>\n<div class=\"relative-js\"></div>\n<script src=\"asset/main.js\" type=\"module\"></script>\n<style>\n  @import '/foo.css';\n</style>\n\n<script type=\"module\">\n  import './css/fonts.css'\n  import './css/css-url.css'\n  import './css/icons.css'\n  import './css/manual-chunks.css'\n  import { multilineUrl } from './multiline-import-meta-url.js'\n\n  text('.base', `import.meta.${``}env.BASE_URL: ${import.meta.env.BASE_URL}`)\n\n  import url from './nested/asset.png'\n  text('.asset-import-relative', url)\n\n  import absoluteUrl from '/nested/asset.png'\n  text('.asset-import-absolute', absoluteUrl)\n\n  import publicUrl from '/icon.png'\n  text('.public-import', publicUrl)\n\n  import publicJsonUrl from '/foo.json?url'\n  text('.public-json-import', publicJsonUrl)\n  ;(async () => {\n    const res = await fetch(publicJsonUrl)\n    text('.public-json-import-content', await res.text())\n  })()\n\n  import publicJsUrl from '/raw.js?url'\n  text('.public-js-import', publicJsUrl)\n  ;(async () => {\n    const res = await fetch(publicJsUrl)\n    text('.public-js-import-content', await res.text())\n    text(\n      '.public-js-import-content-type',\n      await res.headers.get('Content-Type'),\n    )\n  })()\n\n  import publicTsUrl from '/raw.ts?url'\n  text('.public-ts-import', publicTsUrl)\n  ;(async () => {\n    const res = await fetch(publicTsUrl)\n    text('.public-ts-import-content', await res.text())\n    text(\n      '.public-ts-import-content-type',\n      await res.headers.get('Content-Type'),\n    )\n  })()\n\n  import publicMtsUrl from '/raw.mts?url'\n  text('.public-mts-import', publicMtsUrl)\n  ;(async () => {\n    const res = await fetch(publicMtsUrl)\n    text('.public-mts-import-content', await res.text())\n    text(\n      '.public-mts-import-content-type',\n      await res.headers.get('Content-Type'),\n    )\n  })()\n\n  import svgFrag from './nested/fragment.svg'\n  text('.svg-frag-import-path', svgFrag)\n  document.querySelector('.svg-frag-import').src = svgFrag + '#icon-heart-view'\n\n  import unknownExtUrl from './nested/foo.unknown'\n  text('.unknown-ext', unknownExtUrl)\n\n  import rawSvg from './nested/fragment.svg?raw'\n  text('.raw', rawSvg)\n\n  import rawHtml from './nested/partial.html?raw'\n  text('.raw-html', rawHtml)\n  import.meta.hot?.accept('./nested/partial.html?raw', (m) => {\n    text('.raw-html', m.default)\n  })\n\n  import noInlineSvg from './nested/fragment.svg?no-inline'\n  text('.no-inline-svg', noInlineSvg)\n\n  import noInlineSvgMP from './nested/fragment.svg?no-inline&foo=bar'\n  text('.no-inline-svg-mp', noInlineSvgMP)\n\n  import inlinePng from './nested/asset.png?inline'\n  text('.inline-png', inlinePng)\n\n  import inlinePublicPng from '/icon.png?inline'\n  text('.inline-public-png', inlinePublicPng)\n\n  import inlinePublicJson from '/foo.json?url&inline'\n  text('.inline-public-json', inlinePublicJson)\n\n  import fooUrl from './foo.js?url'\n  text('.url', fooUrl)\n\n  import unicodeUrl from './テスト-測試-white space.js?url'\n  text('.unicode-url', unicodeUrl)\n\n  import filenameIncludingSingleQuoteUrl from \"./nested/with-single'quote.png\"\n  text('.filename-including-single-quote', filenameIncludingSingleQuoteUrl)\n\n  // TODO: is not supported yet (https://github.com/vitejs/vite/pull/16243)\n  // import percentUrl from './asset/percent%25.png?url'\n  // text('.percent-url', percentUrl)\n\n  import cssUrl from './css/icons.css?url'\n  text('.url-css', cssUrl)\n\n  import cssUrlUrl from './css/css-url-url.css?url'\n  const linkTag = document.createElement('link')\n  linkTag.href = cssUrlUrl\n  linkTag.rel = 'stylesheet'\n  document.body.appendChild(linkTag)\n\n  // const url = new URL('non_existent_file.png', import.meta.url)\n  const metaUrl = new URL('./import-meta-url/img.png', import.meta.url)\n  text('.import-meta-url', metaUrl)\n  document.querySelector('.import-meta-url-img').src = metaUrl\n\n  const metaUrlDep = new URL('@/asset.png', import.meta.url)\n  text('.import-meta-url-dep', metaUrlDep)\n  document.querySelector('.import-meta-url-dep-img').src = metaUrlDep\n\n  // testing URLs for public assets served at the public base path\n  // equivalent to `new URL(`${import.meta.env.BASE_URL}/icon.png`, import.meta.url)\n  const metaUrlBasePath = new URL('/icon.png', import.meta.url)\n  text('.import-meta-url-base-path', metaUrlBasePath)\n  document.querySelector('.import-meta-url-base-path-img').src = metaUrlBasePath\n\n  const metaUrlDataUri = new URL(\n    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA0CAYAAADWr1sfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTAyNkI1RkE4N0VCMTFFQUFBQzJENzUzNDFGRjc1N0UiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTAyNkI1Rjk4N0VCMTFFQUFBQzJENzUzNDFGRjc1N0UiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTc3NzA2Q0Y4N0FCMTFFM0I3MERFRTAzNzcwNkMxMjMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTc3NzA2RDA4N0FCMTFFM0I3MERFRTAzNzcwNkMxMjMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6nwnGxAAAJtklEQVR42txZ6W9c1RU/970373nsJHgZ27FThahSV8BCqGQTlIQ2EiUBReqHVpT8Af0r+NA/ogpqqWiDKrZuKYQPLGEpAlEFiqOgICSUBOKQhDjxeGY885bb37n3TGKPZ+4bx0uWK53Ec+cu53fPfkbtfu13B4noF6AQVAEpah0ak3cUSBU8qh46RfWj50ltKJDXXyBKdMtibI+TXlLqm2C87y/+eO/vlVIVnWbUcShFyld8T19ypvLbZKpyALOjVPCqrUcT1mWXYtIzMUV7Rqn315tJJyk+J51OZwb7QA3QkQD/fAL6JWiIXKMOhkOPwp1DFE/OkJ6NAQxn+fhuPhaFOc8DE9loern+hD9SfJVCdaLdOy5gif9rpHfyHp3pCX5cs6X1PfnORkr+SA9FO4bsgkZm1ykngm8ZK06ll0EvgWY6SwDn1fGKcykVfriewh2D5oKskhhw5KmFzLO0MJdO1yfS87UD2Uxc0tXErM+qLYQ5XUspK8el9JvagXSmPmH2W4lfG3wHNMHciXnmIfj+OvCVga8sD+yMYHyZAZ8H/Qk06dySaiNljf/DB0vklWAB1RQqnS0WA18eQE0Dz0++rjyRluOJDHuzWkwZNAPgLPHfPIeHTK/EEzHWKt/zDdh2asBmUUnJg3TDB0rQIuYptby5x6RgPO/JxIes304p44V1DMAzKQUbe4xqa62h2vbFyWuxeUie1RKqvVmXG/sxOaYKPqliQKp3HmEOB43pWaxJaTPvUV6rdK3Z6FloGUt35yD54EGXEwvaU3nSPSIYF7D5T/mio1rzS7Jaa1we4YWDzb1GUpptqJ1OGUl7BJX+jS7HP/OKEPlgRH5/SP5AZMjrCTz+jtdQQckxauEZ/IZ4bKyhYEsv7h6GpmGuhnsznafORwQbtQKGY6F/gy64pMxPnF2JSQ33UM/ecWNX/PJG3RbYsn15qCiYTQdhr49j9m4jQd8zXlkFZv3d/B087SBM4OodC+5kJYIX5r09+8ZIDYYAn4gqOdFeEEwn2gFmMb0BesEpZeOxARAOJ4SXjLbDlljKcbaQ0ebwrRNLy409oH1Xz1H2xrRc3wfaYx1dm/sgQTyYMZ1wZ4nC+4es76gnC3lqP14QTFk7wDymQH8DnXKCZibKiQHY89gY+aUeGwcT66xaw40JMUnWn52t7NWVeKt5GNaUarw1naruxXn9Rrrz9jRjLsd5PtsfZY3aaBZo9tT5qnxKsExRizto59EOccRzJQomHAC0DzsOHxwy3lvXk8VxU1u1VJFPaSW5B177SRtfNaVnq08izNyjQl9UefFe4zNwdoTI4I8XTfznu3NUORYMiyKP10HvD4neZy7VzqBaHEOjnw5TsKnXfgaDRjKqxWuzzRKtTy/Wt2W1ZAukuyX9tr4Ns+vZpheAVfKoOCuDKrNzDB8Ysp9Znd2qnAnvh9r5I8+hDs86HRhfCIlyQqGgbuHDI0Sz9gHaZj0sQXhhpJhbktOVp5Kvak/x31Sg9rarRXVxXvjwKJxk0Z7N/sOjPEf1bCez7LS1Ji/0iduBAUAD6JDpRFsHqfDjDZRdTqyU26gn2ykkXUovzf2KCV66ZGxXL9YeVtsMMb9w1x0U/WTAADWqnGO4wvMhwdA14PmqfbLjClZdTkaqCFPrAor2byIvUsZrd5Syp4BaFYW8RUmDeG8+wwsVRY+Pk7c+MJpkChXfCfhkJ1XuBjCPV0Bvt0nhFwoPiQfbVjixgaKHho3qGSlbgIu9ti/VEdHifJkdVc2aRoizwnv7kT+nNuy5hxZeX3EtygM8DfoX6FPnCcxL1Yap6NGNCCFFk5x0ETra2i7v9TcWqbh3zIbASmzvcHP7qfA6vRzAJIH7JWeYktRPz2a2bHuoZKpEdjgWdBeoWboMTpwea4o3GiF1lXzZPWLh8Y3ca7oAPAd6E/RubjLCkgBz4fYhCu6cl2d73UmX13KSUcDecNugqX2Np9a5mvKu8Di3EoB5HAP9WboGnZMRFiiXb0MhhYjNOrbeVsc5DPPexEqXz+C9HufLHHPT3PyxIbwd6wZIt4DnxCG81lG1JT9miZiaGeVj8L0+m3I2UrdaezY/z65Auj9ab0vPNLOlp+fEGwtPb3cj3aUA5nEWdDA3GTGMpqT6AupFmLLpYWaL9Hag2XZZdVHqcR1cfGzchDhdyWwFpnKTjIPCG600YFad96S+rHeOzZ5tB7Et3jeItLNk8+Fa2j6jYnU2YSyhaNcwFe4dMHv5DD7L1WUTXt5zmtoyADe7Bwfn15cdHZix3cxIzB+ObC+q2Z1Q6pq0E6gynF0A715ErasbqQWbH9JOCC8zSwGwVMA8Phb3X3a2g5BnZ5cRT78Dj7trxMRR7liY+lhdu5ntVnFDFLm4N1a0nr2e5rVtysLDx0tl/noAc9X7TLNH5KxZuC1Tg6puH0SYKtoaumFrYWPbsS0xg+/2UbjVVkNXW67u8aHwkKwFYB6fgQ47nYXXBBSbEBPtGjUtnWy6YcEm/F1q5sLdkO5AQTonuap8Vu7+7HoYv17APF4Fve6KrabEkzhcuH+AAuTFGmmjkeScbdsU7hswxGtMkqJzM7PX5W5aa8BfSDdwyt30I9Nw44qn+MgYef1IKC42SLN9D4TU8+iYCWGmKSfdEceYkju/uBGAebwvDW53KcOeFxlYcBeqqd3DBiznyCHCUPCDdUTsweM0765M7np/OQwvF/A5aYOedDcKmo23zP5qsalovTfny9wL4xQyP18+KXedu5GAmx0G9pizrsrAJCOQsuovUPTIKIU/HzG/SPKczks97dnPODswXY5gBQDXxK72g3a0fURT5yoTY7nw5w6ksVcAzZq/C7mbcv+TO2rLZXYlJMzjtNjXBedN7IlBXuibtq3ph8W5vw1dkLNPrwSjKwWY89oXQf9xNgqaXruaWLulXK8cy5kvOvP3GwC4mWc/50wImj+xaLrmpFRugvPcUvPltQJMUr0cXcHzjpLrF82bAHBN1O+dFTjrHTmrdjMD5vER6B/LZLQmZ3y00sytBuC65LtvLeOMt+SM+q0AmMekNNbK17G3LHsnV4Ox1QLM4wNRy3gJe2LZ88FqMbWagL8CPe2sptpXQ0/L3lsOMGcW3Cv+O+hyF+svy9pjsveWA9z0tn8Afd7F2s9lbW01GVptwJxTHZfE3/Uj17SsOU7ddLRuYsDN8decDOyorFn1sVaAvyT7k8iZNt+dke++vJ0A8+CfMw+3mT8s39HtBviSgDs+b+64zF26HQHz+C/o+Xmfn5c5ul0BXyT7w/U5oTdlbs1GQGs/vgb9cd7fazr+L8AAD0zRYMSYHQAAAAAASUVORK5CYII=',\n    import.meta.url,\n  )\n  text('.import-meta-url-data-uri', metaUrlDataUri)\n  document.querySelector('.import-meta-url-data-uri-img').src = metaUrlDataUri\n\n  const metaUrlWithoutExtension = new URL('./nested/test', import.meta.url)\n  text('.import-meta-url-without-extension', metaUrlWithoutExtension)\n  ;(async () => {\n    const res = await fetch(metaUrlWithoutExtension)\n    text('.import-meta-url-content-without-extension', await res.text())\n  })()\n\n  // prettier-ignore\n  const metaUrlWithComma = new URL('./nested/asset.png', import.meta.url,)\n  text('.import-meta-url-comma', metaUrlWithComma)\n  document.querySelector('.import-meta-url-img-comma').src = metaUrlWithComma\n\n  // testing trailing comma and new line\n  // prettier-ignore\n  const metaUrlWithCommaNL = new URL(\n    './nested/asset.png',\n    import.meta.url,\n  )\n  text('.import-meta-url-comma-nl', metaUrlWithCommaNL)\n  document.querySelector('.import-meta-url-img-comma-nl').src =\n    metaUrlWithCommaNL\n\n  import classNames from './css/foo.module.css'\n  document.querySelector('#foo').className = classNames['foo-module']\n\n  import someString from './static/foo.txt?raw'\n  document.querySelector('.raw-query').textContent = someString\n\n  // NOTE: add `'' +` to opt-out rolldown's transform: https://github.com/rolldown/rolldown/issues/2745\n  const metaUrlNonExistent = new URL(\n    /* @vite-ignore */ 'non-existent',\n    '' + import.meta.url,\n  ).pathname\n  text('.non-existent-import-meta-url', metaUrlNonExistent)\n\n  /**\n   * don't process the code in the comment\n   * const url = new URL('non_existent_file.png', import.meta.url)\n   */\n\n  function testDynamicImportMetaUrl(name, i) {\n    const metaUrl = new URL(`./nested/${name}.png`, import.meta.url)\n    text(`.dynamic-import-meta-url-${i}`, metaUrl)\n    document.querySelector(`.dynamic-import-meta-url-img-${i}`).src = metaUrl\n  }\n\n  testDynamicImportMetaUrl('icon', 1)\n  testDynamicImportMetaUrl('asset', 2)\n\n  function testDynamicImportMetaUrlWithComma(name, i) {\n    // prettier-ignore\n    const metaUrl = new URL(`./nested/${name}.png`, import.meta.url,)\n    text(`.dynamic-import-meta-url-${i}-comma`, metaUrl)\n    document.querySelector(`.dynamic-import-meta-url-img-${i}-comma`).src =\n      metaUrl\n  }\n\n  testDynamicImportMetaUrlWithComma('icon', 1)\n  testDynamicImportMetaUrlWithComma('asset', 2)\n\n  function testDynamicImportMetaUrlWithQuery(name, i) {\n    // prettier-ignore\n    const metaUrl = new URL(`./nested/${name}.png?abc`, import.meta.url,)\n    text(`.dynamic-import-meta-url-${i}-query`, metaUrl)\n    document.querySelector(`.dynamic-import-meta-url-img-${i}-query`).src =\n      metaUrl\n  }\n\n  testDynamicImportMetaUrlWithQuery('icon', 1)\n  testDynamicImportMetaUrlWithQuery('asset', 2)\n\n  function testDynamicImportMetaUrlWithTernaryOperator(name, i) {\n    // prettier-ignore\n    const metaUrl = new URL(`./nested/${1 === 0 ? 'failed' : name}.png?abc`, import.meta.url,)\n    text(`.dynamic-import-meta-url-${i}-ternary`, metaUrl)\n    document.querySelector(`.dynamic-import-meta-url-img-${i}-ternary`).src =\n      metaUrl\n  }\n\n  testDynamicImportMetaUrlWithTernaryOperator('icon', 1)\n  testDynamicImportMetaUrlWithTernaryOperator('asset', 2)\n\n  {\n    const name = 'test'\n    const js = new URL(`./nested/${name}.js`, import.meta.url).href\n    text('.dynamic-import-meta-url-js', js)\n  }\n\n  {\n    const name = './nested/icon'\n    const metaUrl = new URL(`${name}.png`, import.meta.url)\n    text(`.dynamic-import-meta-url-all`, metaUrl)\n  }\n\n  text('.import-meta-url-multiline', multilineUrl)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/assets/manifest.json",
    "content": "{}\n"
  },
  {
    "path": "playground/assets/multiline-import-meta-url.js",
    "content": "// Test for multiline expressions\n// This is a separate file to ensure the regex filter in assetImportMetaUrlPlugin\n// correctly detects and processes multiline expressions that span multiple lines.\nexport const multilineUrl = new URL(\n  './nested/asset.png',\n\n  import.meta.url,\n)\n"
  },
  {
    "path": "playground/assets/nested/foo.unknown",
    "content": "custom file\n"
  },
  {
    "path": "playground/assets/nested/partial.html",
    "content": "<div>partial</div>\n"
  },
  {
    "path": "playground/assets/nested/test.js",
    "content": "export default class a {\n  name = 'a'\n}\n"
  },
  {
    "path": "playground/assets/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-assets\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\",\n    \"dev:encoded-base\": \"vite --config ./vite.config-encoded-base.js dev\",\n    \"build:encoded-base\": \"vite --config ./vite.config-encoded-base.js build\",\n    \"preview:encoded-base\": \"vite --config ./vite.config-encoded-base.js preview\",\n    \"dev:relative-base\": \"vite --config ./vite.config-relative-base.js dev\",\n    \"build:relative-base\": \"vite --config ./vite.config-relative-base.js build\",\n    \"preview:relative-base\": \"vite --config ./vite.config-relative-base.js preview\",\n    \"dev:runtime-base\": \"vite --config ./vite.config-runtime-base.js dev\",\n    \"build:runtime-base\": \"vite --config ./vite.config-runtime-base.js build\",\n    \"preview:runtime-base\": \"vite --config ./vite.config-runtime-base.js preview\",\n    \"dev:url-base\": \"vite --config ./vite.config-url-base.js dev\",\n    \"build:url-base\": \"vite --config ./vite.config-url-base.js build\",\n    \"preview:url-base\": \"vite --config ./vite.config-url-base.js preview\"\n  }\n}\n"
  },
  {
    "path": "playground/assets/static/bar",
    "content": "bar\n"
  },
  {
    "path": "playground/assets/static/foo.css",
    "content": ".foo-public {\n  color: red;\n}\n"
  },
  {
    "path": "playground/assets/static/foo.json",
    "content": "{\n  \"foo\": \"bar\"\n}\n"
  },
  {
    "path": "playground/assets/static/foo.txt",
    "content": "foo"
  },
  {
    "path": "playground/assets/static/import-expression.js",
    "content": "document.querySelector('.import-expression').textContent += '[success]'\n"
  },
  {
    "path": "playground/assets/static/raw.css",
    "content": ".raw-css {\n  color: red;\n}\n"
  },
  {
    "path": "playground/assets/static/raw.js",
    "content": "document.querySelector('.raw-js').textContent =\n  '[success] Raw js from /public loaded'\n"
  },
  {
    "path": "playground/assets/static/raw.mts",
    "content": "export default function foobar() {\n  return 1 + 2\n}\n"
  },
  {
    "path": "playground/assets/static/raw.ts",
    "content": "export default function other() {\n  return 1 + 2\n}\n"
  },
  {
    "path": "playground/assets/vite.config-encoded-base.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\n/** see `ports` variable in test-utils.ts */\nconst port = 9524\n\nexport default defineConfig({\n  ...baseConfig,\n  // Vite should auto-encode  this as `/foo%20bar/` internally\n  base: '/foo bar/',\n  server: {\n    port,\n    strictPort: true,\n  },\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/encoded-base',\n    watch: null,\n    minify: false,\n    assetsInlineLimit: 0,\n    rollupOptions: {\n      output: {\n        entryFileNames: 'entries/[name].js',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        assetFileNames: 'other-assets/[name]-[hash][extname]',\n      },\n    },\n  },\n  preview: {\n    port,\n    strictPort: true,\n  },\n  cacheDir: 'node_modules/.vite-encoded-base',\n})\n"
  },
  {
    "path": "playground/assets/vite.config-relative-base.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nexport default defineConfig(({ isPreview }) => ({\n  ...baseConfig,\n  base: !isPreview ? './' : '/relative-base/', // relative base to make dist portable\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/relative-base',\n    watch: null,\n    minify: false,\n    assetsInlineLimit: 0,\n    rollupOptions: {\n      output: {\n        entryFileNames: 'entries/[name].js',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        assetFileNames: 'other-assets/[name]-[hash][extname]',\n        // manualChunks(id) {\n        //   if (id.includes('css/manual-chunks.css')) {\n        //     return 'css/manual-chunks'\n        //   }\n        // },\n      },\n    },\n  },\n  cacheDir: 'node_modules/.vite-relative-base',\n}))\n"
  },
  {
    "path": "playground/assets/vite.config-runtime-base.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nconst dynamicBaseAssetsCode = `\nglobalThis.__toAssetUrl = url => '/' + url\nglobalThis.__publicBase = '/'\n`\n\nexport default defineConfig({\n  ...baseConfig,\n  base: './', // overwrite the original base: '/foo/'\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/runtime-base',\n    watch: null,\n    minify: false,\n    assetsInlineLimit: 0,\n    rollupOptions: {\n      output: {\n        entryFileNames: 'entries/[name].js',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        assetFileNames: 'other-assets/[name]-[hash][extname]',\n      },\n    },\n  },\n  plugins: [\n    {\n      name: 'dynamic-base-assets-globals',\n      transformIndexHtml(_, ctx) {\n        if (ctx.bundle) {\n          // Only inject during build\n          return [\n            {\n              tag: 'script',\n              attrs: { type: 'module' },\n              children: dynamicBaseAssetsCode,\n            },\n          ]\n        }\n      },\n    },\n  ],\n  experimental: {\n    renderBuiltUrl(filename, { hostType, type }) {\n      if (type === 'asset') {\n        if (hostType === 'js') {\n          return {\n            runtime: `globalThis.__toAssetUrl(${JSON.stringify(filename)})`,\n          }\n        }\n      } else if (type === 'public') {\n        if (hostType === 'js') {\n          return {\n            runtime: `globalThis.__publicBase+${JSON.stringify(filename)}`,\n          }\n        }\n      }\n    },\n  },\n  cacheDir: 'node_modules/.vite-runtime-base',\n})\n"
  },
  {
    "path": "playground/assets/vite.config-url-base.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\n/** see `ports` variable in test-utils.ts */\nconst port = 9525\n\nexport default defineConfig({\n  ...baseConfig,\n  base: `http://localhost:${port}/`,\n  server: {\n    port,\n    strictPort: true,\n  },\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/url-base',\n    watch: null,\n    minify: false,\n    assetsInlineLimit: 0,\n    rollupOptions: {\n      output: {\n        entryFileNames: 'entries/[name].js',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        assetFileNames: 'other-assets/[name]-[hash][extname]',\n      },\n    },\n  },\n  preview: {\n    port,\n    strictPort: true,\n  },\n  cacheDir: 'node_modules/.vite-url-base',\n})\n"
  },
  {
    "path": "playground/assets/vite.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  base: '/foo/bar',\n  publicDir: 'static',\n  resolve: {\n    alias: {\n      '@': path.resolve(import.meta.dirname, 'nested'),\n      fragment: path.resolve(import.meta.dirname, 'nested/fragment-bg.svg'),\n    },\n  },\n  assetsInclude: ['**/*.unknown'],\n  build: {\n    outDir: 'dist/foo',\n    assetsInlineLimit: 8000, // 8 kB\n    manifest: true,\n    watch: {},\n  },\n})\n"
  },
  {
    "path": "playground/assets/テスト-測試-white space.js",
    "content": "console.log('test Unicode')\n"
  },
  {
    "path": "playground/assets-sanitize/__tests__/assets-sanitize.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getBg, isBuild, page, readManifest } from '~utils'\n\nif (!isBuild) {\n  test('importing asset with special char in filename works in dev', async () => {\n    expect(await getBg('.plus-circle')).toContain('+circle.svg')\n    expect(await page.textContent('.plus-circle')).toMatch('+circle.svg')\n    expect(await getBg('.underscore-circle')).toContain('_circle.svg')\n    expect(await page.textContent('.underscore-circle')).toMatch('_circle.svg')\n  })\n} else {\n  test('importing asset with special char in filename works in build', async () => {\n    const manifest = readManifest()\n    const plusCircleAsset = manifest['+circle.svg'].file\n    const underscoreCircleAsset = manifest['_circle.svg'].file\n    expect(await getBg('.plus-circle')).toMatch(plusCircleAsset)\n    expect(await page.textContent('.plus-circle')).toMatch(plusCircleAsset)\n    expect(await getBg('.underscore-circle')).toMatch(underscoreCircleAsset)\n    expect(await page.textContent('.underscore-circle')).toMatch(\n      underscoreCircleAsset,\n    )\n    expect(plusCircleAsset).toMatch('/_circle')\n    expect(underscoreCircleAsset).toMatch('/_circle')\n    expect(plusCircleAsset).not.toEqual(underscoreCircleAsset)\n    expect(Object.keys(manifest).length).toBe(3) // 2 svg, 1 index.js\n  })\n}\n\ntest.runIf(!isBuild)('denied .env', async () => {\n  expect(await page.textContent('.unsafe-dotenv')).toBe('403')\n  expect(await page.textContent('.unsafe-dotenv-double-slash')).toBe('200') // SPA fallback\n})\n"
  },
  {
    "path": "playground/assets-sanitize/index.html",
    "content": "<script type=\"module\" src=\"./index.js\"></script>\n<style>\n  .test-el {\n    background-repeat: no-repeat;\n    padding-left: 2rem;\n    margin-bottom: 1rem;\n  }\n</style>\n<h3>test elements below should show circles and their url</h3>\n<div class=\"test-el plus-circle\"></div>\n<div class=\"test-el underscore-circle\"></div>\n\n<h3>Denied .env</h3>\n<div class=\"unsafe-dotenv\"></div>\n<div class=\"unsafe-dotenv-double-slash\"></div>\n\n<script type=\"module\">\n  // .env, denied by default. See fs-serve playground for other fs tests\n  // these checks ensure that a project without a custom root respects fs.deny\n\n  fetch('/.env')\n    .then((r) => {\n      text('.unsafe-dotenv', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  fetch(window.location + '/.env')\n    .then((r) => {\n      text('.unsafe-dotenv-double-slash', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/assets-sanitize/index.js",
    "content": "import plusCircle from './+circle.svg'\nimport underscoreCircle from './_circle.svg'\nfunction setData(classname, file) {\n  const el = document.body.querySelector(classname)\n  el.style.backgroundImage = `url(${file})`\n  el.textContent = file\n}\nsetData('.plus-circle', plusCircle)\nsetData('.underscore-circle', underscoreCircle)\n"
  },
  {
    "path": "playground/assets-sanitize/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-assets-sanitize\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/assets-sanitize/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    //speed up build\n    minify: false,\n    target: 'esnext',\n    assetsInlineLimit: 0,\n    manifest: true,\n  },\n})\n"
  },
  {
    "path": "playground/backend-integration/__tests__/backend-integration.spec.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\nimport {\n  browserErrors,\n  browserLogs,\n  editFile,\n  getColor,\n  getCssRuleBg,\n  isBuild,\n  isServe,\n  listAssets,\n  page,\n  ports,\n  readManifest,\n  serverLogs,\n  untilBrowserLogAfter,\n} from '~utils'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe('asset imports from js', () => {\n  test('file outside root', async () => {\n    // assert valid image src https://github.com/microsoft/playwright/issues/6046#issuecomment-1799585719\n    await vi.waitUntil(() =>\n      page\n        .locator('.asset-reference.outside-root .asset-preview')\n        .evaluate((el: HTMLImageElement) => el.naturalWidth > 0),\n    )\n\n    const text = await page.textContent(\n      '.asset-reference.outside-root .asset-url',\n    )\n    if (isBuild) {\n      expect(text).toMatch(/\\/dev\\/assets\\/logo-[-\\w]{8}\\.png/)\n    } else {\n      // asset url is prefixed with server.origin\n      expect(text).toMatch(\n        `http://localhost:${ports['backend-integration']}/dev/@fs/`,\n      )\n      expect(text).toMatch(/\\/dev\\/@fs\\/.+?\\/images\\/logo\\.png/)\n    }\n  })\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('manifest', async () => {\n    const manifest = readManifest('dev')\n    const htmlEntry = manifest['index.html']\n    const mainTsEntry = manifest['main.ts']\n    const cssAssetEntry = manifest['global.css']\n    const pcssAssetEntry = manifest['foo.pcss']\n    const scssAssetEntry = manifest['nested/blue.scss']\n    const imgAssetEntry = manifest['../images/logo.png']\n    const dirFooAssetEntry = manifest['../../dir/foo.css']\n    const customNameAssetEntry = manifest['../../dir/custom.css']\n    const iconEntrypointEntry = manifest['icon.png']\n    const waterContainerEntry = manifest['water-container.svg']\n    expect(htmlEntry.css.length).toEqual(1)\n    expect(htmlEntry.assets.length).toEqual(1)\n    expect(mainTsEntry.assets?.length ?? 0).toBeGreaterThanOrEqual(1)\n    expect(mainTsEntry.assets).toContainEqual(\n      expect.stringMatching(/assets\\/url-[-\\w]{8}\\.css/),\n    )\n    expect(cssAssetEntry?.file).not.toBeUndefined()\n    expect(cssAssetEntry?.isEntry).toEqual(true)\n    expect(pcssAssetEntry?.file).not.toBeUndefined()\n    expect(pcssAssetEntry?.isEntry).toEqual(true)\n    expect(scssAssetEntry?.file).not.toBeUndefined()\n    expect(scssAssetEntry?.src).toEqual('nested/blue.scss')\n    expect(scssAssetEntry?.isEntry).toEqual(true)\n    expect(imgAssetEntry?.file).not.toBeUndefined()\n    expect(imgAssetEntry?.isEntry).toBeUndefined()\n    expect(dirFooAssetEntry).not.toBeUndefined() // '\\\\' should not be used even on windows\n    // use the entry name\n    expect(dirFooAssetEntry.file).toMatch('assets/bar-')\n    expect(dirFooAssetEntry.name).toStrictEqual('bar.css')\n    expect(dirFooAssetEntry.assets.length).toEqual(1)\n    expect(customNameAssetEntry.name).toStrictEqual('bar.custom')\n    expect(iconEntrypointEntry?.file).not.toBeUndefined()\n    expect(waterContainerEntry?.file).not.toBeUndefined()\n  })\n\n  test('CSS imported from JS entry should have a non-nested chunk name', () => {\n    const manifest = readManifest('dev')\n    const mainTsEntryCss = manifest['nested/sub.ts'].css\n    expect(mainTsEntryCss.length).toBe(1)\n    expect(mainTsEntryCss[0].replace('assets/', '')).not.toContain('/')\n  })\n\n  test('entrypoint assets should not generate empty JS file', () => {\n    expect(serverLogs).not.toContainEqual(\n      'Generated an empty chunk: \"icon.png\".',\n    )\n\n    const assets = listAssets('dev')\n    expect(assets).not.toContainEqual(\n      expect.stringMatching(/icon.png-[-\\w]{8}\\.js$/),\n    )\n  })\n})\n\ndescribe.runIf(isServe)('serve', () => {\n  test('No ReferenceError', async () => {\n    browserErrors.forEach((error) => {\n      expect(error.name).not.toBe('ReferenceError')\n    })\n  })\n\n  test('preserve the base in CSS HMR', async () => {\n    await expect.poll(() => getColor('body')).toBe('black') // sanity check\n    editFile('frontend/entrypoints/global.css', (code) =>\n      code.replace('black', 'red'),\n    )\n    await expect.poll(() => getColor('body')).toBe('red') // successful HMR\n\n    // Verify that the base (/dev/) was added during the css-update\n    const link = await page.$('link[rel=\"stylesheet\"]:last-of-type')\n    expect(await link.getAttribute('href')).toContain('/dev/global.css?t=')\n  })\n\n  test('server.origin is applied to non-public CSS url()', async () => {\n    const bg = await getCssRuleBg('.outside-root--aliased')\n    expect(bg).toContain(\n      `http://localhost:${ports['backend-integration']}/dev/`,\n    )\n  })\n\n  test('server.origin is applied to public CSS url()', async () => {\n    const bg = await getCssRuleBg('.public-asset')\n    expect(bg).toContain(\n      `http://localhost:${ports['backend-integration']}/dev/icon.png`,\n    )\n  })\n\n  test('CSS dependencies are tracked for HMR', async () => {\n    const el = await page.$('h1')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('frontend/entrypoints/main.ts', (code) =>\n          code.replace('text-black', 'text-[rgb(204,0,0)]'),\n        ),\n      '[vite] css hot updated: /global.css',\n    )\n    await expect.poll(() => getColor(el)).toBe('rgb(204, 0, 0)')\n  })\n})\n"
  },
  {
    "path": "playground/backend-integration/dir/custom.css",
    "content": ".custom {\n  color: red;\n}\n"
  },
  {
    "path": "playground/backend-integration/dir/foo.css",
    "content": ".windows-path-foo {\n  color: blue;\n}\n.foo-background-image {\n  background-image: url('./foo-background.svg?no-inline');\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/entrypoints/foo.pcss",
    "content": ".foo_pcss {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/entrypoints/global.css",
    "content": "@import '~/styles/background.css';\n@import '~/styles/tailwind.css';\n@import '../../references.css';\n\nhtml,\nbody {\n  font-family: sans-serif;\n  line-height: 2.4rem;\n}\n\nbody {\n  color: black;\n  margin: 4vh auto;\n  max-width: 800px;\n  padding: 0 4vw;\n}\n\nul {\n  padding: 0 0.4em;\n  margin: 0;\n}\n\nli {\n  display: flex;\n  align-items: center;\n}\n\nimg {\n  height: 32px;\n  width: 32px;\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/entrypoints/index.html",
    "content": "<!doctype html>\n\n<link rel=\"stylesheet\" href=\"/global.css\" />\n\n<h1 class=\"text-black\">Backend Integration</h1>\n\n<p>\n  This test configures the <code>root</code> to simulate a Laravel/Rails setup.\n</p>\n\n<h2>JS Asset References</h2>\n\n<ul>\n  <li class=\"asset-reference outside-root\">Asset Outside Root</li>\n</ul>\n\n<h2>CSS Asset References</h2>\n\n<ul>\n  <li>\n    Background URL with Alias:\n    <div class=\"background-asset outside-root--aliased\"></div>\n  </li>\n  <li>\n    Background URL with Relative Path:\n    <div class=\"background-asset outside-root--relative\"></div>\n  </li>\n  <li>\n    Background URL with Public Asset:\n    <div class=\"background-asset public-asset\"></div>\n  </li>\n</ul>\n\n<h2>CSS imported from JS</h2>\n\n<p class=\"imported\">text</p>\n\n<script type=\"module\" src=\"./main.ts\"></script>\n<script type=\"module\" src=\"./nested/sub.ts\"></script>\n<script type=\"module\">\n  import './global.css'\n\n  // Importing a file outside the `root` should provide an @fs path.\n  import outsideRootUrl from '~/images/logo.png'\n  setAssetReference('.outside-root', outsideRootUrl)\n\n  // Helper: Allows to test the URL content as well as the request being served.\n  function setAssetReference(elSelector, url) {\n    const text = document.createElement('code')\n    text.classList.add('asset-url')\n    text.textContent = url\n\n    const img = document.createElement('img')\n    img.classList.add('asset-preview')\n    img.src = url\n\n    const el = document.querySelector(`.asset-reference${elSelector}`)\n    el.appendChild(img)\n    el.appendChild(text)\n  }\n</script>\n"
  },
  {
    "path": "playground/backend-integration/frontend/entrypoints/main.ts",
    "content": "import 'vite/modulepreload-polyfill'\nimport cssUrl from '../styles/url.css?url'\nimport waterContainer from './water-container.svg'\n\nconst cssLink = document.createElement('link')\ncssLink.rel = 'stylesheet'\ncssLink.href = cssUrl\ndocument.querySelector('head').prepend(cssLink)\n\nconst dummyMeta = document.createElement('meta')\ndummyMeta.name = 'dummy'\ndummyMeta.content = waterContainer\ndocument.querySelector('head').append(dummyMeta)\n\nexport const colorClass = 'text-black'\n\nexport function colorHeading() {\n  document.querySelector('h1').className = colorClass\n}\n\ncolorHeading()\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/entrypoints/nested/blue.scss",
    "content": "$primary: #cc0000;\n\n.text-primary {\n  color: $primary;\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/entrypoints/nested/sub.ts",
    "content": "import '../../styles/imported.css'\n"
  },
  {
    "path": "playground/backend-integration/frontend/styles/background.css",
    "content": ".background-asset {\n  background-repeat: no-repeat;\n  background-size: 100%;\n  display: inline-block;\n  height: 32px;\n  width: 32px;\n}\n\n.outside-root--aliased {\n  background-image: url('~/images/logo.png');\n}\n\n.outside-root--relative {\n  background-image: url('../images/logo.png');\n}\n\n.public-asset {\n  background-image: url('/icon.png');\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/styles/imported.css",
    "content": ".imported {\n  color: green;\n}\n"
  },
  {
    "path": "playground/backend-integration/frontend/styles/tailwind.css",
    "content": "@import 'tailwindcss';\n"
  },
  {
    "path": "playground/backend-integration/frontend/styles/url.css",
    "content": ".url {\n  color: red;\n}\n"
  },
  {
    "path": "playground/backend-integration/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-backend-integration\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/vite\": \"^4.2.1\",\n    \"sass\": \"^1.98.0\",\n    \"tailwindcss\": \"^4.2.1\",\n    \"tinyglobby\": \"^0.2.15\"\n  }\n}\n"
  },
  {
    "path": "playground/backend-integration/references.css",
    "content": ".asset-reference {\n  display: grid;\n  grid-template-areas:\n    'summary preview .'\n    'url url url';\n}\n\n.asset-url {\n  grid-area: url;\n  white-space: nowrap;\n}\n"
  },
  {
    "path": "playground/backend-integration/vite.config.js",
    "content": "import path from 'node:path'\nimport { globSync } from 'tinyglobby'\nimport { defineConfig, normalizePath } from 'vite'\nimport tailwind from '@tailwindcss/vite'\n\n/**\n * @returns {import('vite').Plugin}\n */\nfunction BackendIntegrationExample() {\n  return {\n    name: 'backend-integration',\n    config() {\n      const projectRoot = import.meta.dirname\n      const sourceCodeDir = path.join(projectRoot, 'frontend')\n      const root = path.join(sourceCodeDir, 'entrypoints')\n      const outDir = path.relative(root, path.join(projectRoot, 'dist/dev'))\n\n      const entrypoints = globSync(`${normalizePath(root)}/**/*`, {\n        absolute: true,\n        expandDirectories: false,\n        onlyFiles: true,\n      }).map((filename) => [path.relative(root, filename), filename])\n\n      entrypoints.push(['tailwindcss-colors', 'tailwindcss/colors.js'])\n      entrypoints.push(['bar.css', path.resolve(projectRoot, './dir/foo.css')])\n      entrypoints.push([\n        'bar.custom',\n        path.resolve(projectRoot, './dir/custom.css'),\n      ])\n\n      return {\n        server: {\n          // same port in playground/test-utils.ts\n          port: 5009,\n          strictPort: true,\n          origin: 'http://localhost:5009',\n        },\n        preview: {\n          port: 5009,\n        },\n        build: {\n          manifest: true,\n          outDir,\n          rollupOptions: {\n            input: Object.fromEntries(entrypoints),\n          },\n        },\n        root,\n        resolve: {\n          alias: {\n            '~': sourceCodeDir,\n          },\n        },\n      }\n    },\n  }\n}\n\nexport default defineConfig({\n  base: '/dev/',\n  plugins: [BackendIntegrationExample(), tailwind()],\n})\n"
  },
  {
    "path": "playground/base-conflict/__tests__/base-conflict.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from '~utils'\n\ntest('absolute imports keep base prefix', async () => {\n  await expect.poll(() => page.textContent('.message')).toBe('absolute import')\n})\n"
  },
  {
    "path": "playground/base-conflict/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Base Conflict</title>\n  </head>\n  <body>\n    <div id=\"app\" class=\"message\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/base-conflict/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-base-conflict\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/base-conflict/src/importee.ts",
    "content": "export default 'absolute import'\n"
  },
  {
    "path": "playground/base-conflict/src/main.ts",
    "content": "import message from 'absolute-importer'\n\ndocument.querySelector('.message')!.textContent = message\n"
  },
  {
    "path": "playground/base-conflict/src/virtualModules.d.ts",
    "content": "declare module 'absolute-importer' {\n  const msg: string\n  export default msg\n}\n"
  },
  {
    "path": "playground/base-conflict/vite.config.ts",
    "content": "import { defineConfig, normalizePath } from 'vite'\n\nconst rootPath = normalizePath(import.meta.dirname)\nconst absoluteRoot = rootPath.startsWith('/') ? rootPath : `/${rootPath}`\nconst [firstSegment] = absoluteRoot.split('/').filter(Boolean)\nconst base = firstSegment ? `/${firstSegment}/` : '/'\n\nconst VIRTUAL_MODULE_ID = 'absolute-importer'\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID\n\nconst absoluteDepPath = `${rootPath}/src/importee.ts`\nexport default defineConfig({\n  base,\n  plugins: [\n    {\n      name: 'absolute-path-import',\n      resolveId(id) {\n        if (id === VIRTUAL_MODULE_ID) {\n          return RESOLVED_VIRTUAL_MODULE_ID\n        }\n      },\n      load(id) {\n        if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n          return (\n            `import dep from ${JSON.stringify(absoluteDepPath)}\\n` +\n            `export default dep`\n          )\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/build-old/__tests__/build-old.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { findAssetFile, isBuild, page } from '~utils'\n\ndescribe('syntax preserve', () => {\n  test('import.meta.url', async () => {\n    await expect.poll(() => page.textContent('.import-meta-url')).toBe('string')\n  })\n  test('dynamic import', async () => {\n    await expect.poll(() => page.textContent('.dynamic-import')).toBe('success')\n  })\n})\n\ndescribe('syntax is lowered', () => {\n  test('private field', async () => {\n    await expect.poll(() => page.textContent('.private-field')).toBe('private')\n\n    if (isBuild) {\n      const content = findAssetFile(/index-[-\\w]{8}\\.js/)\n      expect(content).not.toMatch(/this\\.#\\w+/)\n    }\n  })\n})\n"
  },
  {
    "path": "playground/build-old/dynamic.js",
    "content": "export default 'success'\n"
  },
  {
    "path": "playground/build-old/index.html",
    "content": "<h1>Build Old</h1>\n\n<h2>import meta url</h2>\n<p class=\"import-meta-url\"></p>\n\n<h2>dynamic import</h2>\n<p class=\"dynamic-import\"></p>\n\n<h2>private field</h2>\n<p class=\"private-field\"></p>\n\n<script type=\"module\">\n  text('.import-meta-url', typeof import.meta.url)\n\n  import('./dynamic.js').then((m) => {\n    text('.dynamic-import', m.default)\n  })\n\n  class PrivateField {\n    #privateField = 'private'\n    get val() {\n      return this.#privateField\n    }\n  }\n  text('.private-field', new PrivateField().val)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/build-old/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-build-old\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/build-old/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    // old browsers only\n    target: ['chrome60'],\n  },\n})\n"
  },
  {
    "path": "playground/cli/__tests__/cli.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port, streams } from './serve'\nimport { editFile, isServe, page } from '~utils'\n\ntest('cli should work', async () => {\n  // this test uses a custom serve implementation, so regular helpers for browserLogs and goto don't work\n  // do the same thing manually\n  const logs = []\n  const onConsole = (msg) => {\n    logs.push(msg.text())\n  }\n  try {\n    page.on('console', onConsole)\n    await page.goto(`http://localhost:${port}/`)\n\n    expect(await page.textContent('.app')).toBe('vite cli works!')\n    expect(logs.some((msg) => msg.match('vite cli works!'))).toBe(true)\n  } finally {\n    page.off('console', onConsole)\n  }\n})\n\ntest.runIf(isServe)('should restart', async () => {\n  const logsLengthBeforeEdit = streams.server.out.length\n  editFile('./vite.config.js', (content) => content)\n  await expect\n    .poll(() => {\n      const logs = streams.server.out.slice(logsLengthBeforeEdit)\n      expect(logs).toEqual(\n        expect.arrayContaining([expect.stringMatching('server restarted')]),\n      )\n      // Don't reprint the server URLs as they are the same\n      expect(logs).not.toEqual(\n        expect.arrayContaining([expect.stringMatching('http://localhost')]),\n      )\n      expect(logs).not.toEqual(\n        expect.arrayContaining([expect.stringMatching('error')]),\n      )\n    })\n    .toSatisfy(() => true)\n})\n"
  },
  {
    "path": "playground/cli/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport { stripVTControlCharacters } from 'node:util'\nimport { execaCommand } from 'execa'\nimport kill from 'kill-port'\nimport {\n  isBuild,\n  isWindows,\n  killProcess,\n  ports,\n  rootDir,\n  viteBinPath,\n} from '~utils'\n\nexport const port = ports.cli\nexport const streams = {} as {\n  build: { out: string[]; err: string[] }\n  server: { out: string[]; err: string[] }\n}\nexport async function serve() {\n  // collect stdout and stderr streams from child processes here to avoid interfering with regular vitest output\n  Object.assign(streams, {\n    build: { out: [], err: [] },\n    server: { out: [], err: [] },\n  })\n  // helpers to collect streams\n  const collectStreams = (name, process) => {\n    process.stdout.on('data', (d) => streams[name].out.push(d.toString()))\n    process.stderr.on('data', (d) => streams[name].err.push(d.toString()))\n  }\n  const collectErrorStreams = (name, e) => {\n    e.stdout && streams[name].out.push(e.stdout)\n    e.stderr && streams[name].err.push(e.stderr)\n  }\n\n  // helper to output stream content on error\n  const printStreamsToConsole = async (name) => {\n    const std = streams[name]\n    if (std.out && std.out.length > 0) {\n      console.log(`stdout of ${name}\\n${std.out.join('\\n')}\\n`)\n    }\n    if (std.err && std.err.length > 0) {\n      console.log(`stderr of ${name}\\n${std.err.join('\\n')}\\n`)\n    }\n  }\n\n  // only run `vite build` when needed\n  if (isBuild) {\n    const buildCommand = `${viteBinPath} build`\n    try {\n      const buildProcess = execaCommand(buildCommand, {\n        cwd: rootDir,\n        stdio: 'pipe',\n      })\n      collectStreams('build', buildProcess)\n      await buildProcess\n    } catch (e) {\n      console.error(`error while executing cli command \"${buildCommand}\":`, e)\n      collectErrorStreams('build', e)\n      await printStreamsToConsole('build')\n      throw e\n    }\n  }\n\n  await kill(port)\n\n  // run `vite --port x` or `vite preview --port x` to start server\n  const viteServerArgs = ['--port', `${port}`, '--strict-port']\n  if (isBuild) {\n    viteServerArgs.unshift('preview')\n  }\n  const serverCommand = `${viteBinPath} ${viteServerArgs.join(' ')}`\n  const serverProcess = execaCommand(serverCommand, {\n    cwd: rootDir,\n    stdio: 'pipe',\n    forceKillAfterDelay: 3000,\n  })\n  collectStreams('server', serverProcess)\n\n  // close server helper, send SIGTERM followed by SIGKILL if needed, give up after 3sec\n  const close = async () => {\n    if (serverProcess) {\n      const timeoutError = `server process still alive after 3s`\n      try {\n        await killProcess(serverProcess)\n        await resolvedOrTimeout(serverProcess, 5173, timeoutError)\n      } catch (e) {\n        if (e === timeoutError || (!serverProcess.killed && !isWindows)) {\n          collectErrorStreams('server', e)\n          console.error(\n            `error while killing cli command \"${serverCommand}\":`,\n            e,\n          )\n          await printStreamsToConsole('server')\n        }\n      }\n    }\n  }\n\n  try {\n    await startedOnPort(serverProcess, port, 5173)\n    return { close }\n  } catch (e) {\n    collectErrorStreams('server', e)\n    console.error(`error while executing cli command \"${serverCommand}\":`, e)\n    await printStreamsToConsole('server')\n    try {\n      await close()\n    } catch (e1) {\n      console.error(\n        `error while killing cli command after failed execute \"${serverCommand}\":`,\n        e1,\n      )\n    }\n  }\n}\n\n// helper to validate that server was started on the correct port\nasync function startedOnPort(serverProcess, port, timeout) {\n  let checkPort\n  const startedPromise = new Promise<void>((resolve, reject) => {\n    checkPort = (data) => {\n      const str = stripVTControlCharacters(data.toString())\n      const match = str.match(\n        /http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\]):(\\d{4})/,\n      )\n      if (match) {\n        const startedPort = parseInt(match[1], 10)\n        if (startedPort === port) {\n          resolve()\n        } else {\n          const msg = `server listens on port ${startedPort} instead of ${port}`\n          reject(msg)\n        }\n      }\n    }\n    serverProcess.stdout.on('data', checkPort)\n  })\n  return resolvedOrTimeout(\n    startedPromise,\n    timeout,\n    `failed to start within ${timeout}ms`,\n  ).finally(() => serverProcess.stdout.off('data', checkPort))\n}\n\n// helper function that rejects with errorMessage if promise isn't settled within ms\nasync function resolvedOrTimeout(promise, ms, errorMessage) {\n  let timer\n  return Promise.race([\n    promise,\n    new Promise((_, reject) => {\n      timer = setTimeout(() => reject(errorMessage), ms)\n    }),\n  ]).finally(() => {\n    clearTimeout(timer)\n    timer = null\n  })\n}\n"
  },
  {
    "path": "playground/cli/index.html",
    "content": "<script type=\"module\" src=\"./index.js\"></script>\n\n<div class=\"app\">vite cli works!</div>\n"
  },
  {
    "path": "playground/cli/index.js",
    "content": "console.log('vite cli works!')\n"
  },
  {
    "path": "playground/cli/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-cli\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"commonjs\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/cli/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  server: {\n    host: 'localhost',\n    headers: {\n      'Cache-Control': 'no-store',\n    },\n  },\n  build: {\n    //speed up build\n    minify: false,\n    target: 'esnext',\n  },\n})\n"
  },
  {
    "path": "playground/cli-module/__tests__/cli-module.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port } from './serve'\nimport { page } from '~utils'\n\ntest('cli should work in \"type\":\"module\" package', async () => {\n  // this test uses a custom serve implementation, so regular helpers for browserLogs and goto don't work\n  // do the same thing manually\n  const logs = []\n  const onConsole = (msg) => {\n    logs.push(msg.text())\n  }\n  try {\n    page.on('console', onConsole)\n    await page.goto(`http://localhost:${port}/`)\n    expect(await page.textContent('.app')).toBe(\n      'vite cli in \"type\":\"module\" package works!',\n    )\n    expect(\n      logs.some((msg) =>\n        msg.match('vite cli in \"type\":\"module\" package works!'),\n      ),\n    ).toBe(true)\n  } finally {\n    page.off('console', onConsole)\n  }\n})\n"
  },
  {
    "path": "playground/cli-module/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport { stripVTControlCharacters } from 'node:util'\nimport { execaCommand } from 'execa'\nimport kill from 'kill-port'\nimport {\n  isBuild,\n  isWindows,\n  killProcess,\n  ports,\n  rootDir,\n  viteBinPath,\n} from '~utils'\n\nexport const port = ports['cli-module']\n\nexport async function serve() {\n  // collect stdout and stderr streams from child processes here to avoid interfering with regular vitest output\n  const streams = {\n    build: { out: [], err: [] },\n    server: { out: [], err: [] },\n  }\n  // helpers to collect streams\n  const collectStreams = (name, process) => {\n    process.stdout.on('data', (d) => streams[name].out.push(d.toString()))\n    process.stderr.on('data', (d) => streams[name].err.push(d.toString()))\n  }\n  const collectErrorStreams = (name, e) => {\n    e.stdout && streams[name].out.push(e.stdout)\n    e.stderr && streams[name].err.push(e.stderr)\n  }\n\n  // helper to output stream content on error\n  const printStreamsToConsole = async (name) => {\n    const std = streams[name]\n    if (std.out && std.out.length > 0) {\n      console.log(`stdout of ${name}\\n${std.out.join('\\n')}\\n`)\n    }\n    if (std.err && std.err.length > 0) {\n      console.log(`stderr of ${name}\\n${std.err.join('\\n')}\\n`)\n    }\n  }\n\n  // only run `vite build` when needed\n  if (isBuild) {\n    const buildCommand = `${viteBinPath} build`\n    try {\n      const buildProcess = execaCommand(buildCommand, {\n        cwd: rootDir,\n        stdio: 'pipe',\n      })\n      collectStreams('build', buildProcess)\n      await buildProcess\n    } catch (e) {\n      console.error(`error while executing cli command \"${buildCommand}\":`, e)\n      collectErrorStreams('build', e)\n      await printStreamsToConsole('build')\n      throw e\n    }\n  }\n\n  await kill(port)\n\n  // run `vite --port x` or `vite preview --port x` to start server\n  const viteServerArgs = ['--port', `${port}`, '--strict-port']\n  if (isBuild) {\n    viteServerArgs.unshift('preview')\n  }\n  const serverCommand = `${viteBinPath} ${viteServerArgs.join(' ')}`\n  const serverProcess = execaCommand(serverCommand, {\n    cwd: rootDir,\n    stdio: 'pipe',\n    forceKillAfterDelay: 3000,\n  })\n  collectStreams('server', serverProcess)\n\n  // close server helper, send SIGTERM followed by SIGKILL if needed, give up after 3sec\n  const close = async () => {\n    if (serverProcess) {\n      const timeoutError = `server process still alive after 3s`\n      try {\n        await killProcess(serverProcess)\n        await resolvedOrTimeout(serverProcess, 10000, timeoutError)\n      } catch (e) {\n        if (e === timeoutError || (!serverProcess.killed && !isWindows)) {\n          collectErrorStreams('server', e)\n          console.error(\n            `error while killing cli command \"${serverCommand}\":`,\n            e,\n          )\n          await printStreamsToConsole('server')\n        }\n      }\n    }\n  }\n\n  try {\n    await startedOnPort(serverProcess, port, 5173)\n    return { close }\n  } catch (e) {\n    collectErrorStreams('server', e)\n    console.error(`error while executing cli command \"${serverCommand}\":`, e)\n    await printStreamsToConsole('server')\n    try {\n      await close()\n    } catch (e1) {\n      console.error(\n        `error while killing cli command after failed execute \"${serverCommand}\":`,\n        e1,\n      )\n    }\n  }\n}\n\n// helper to validate that server was started on the correct port\nasync function startedOnPort(serverProcess, port, timeout) {\n  let checkPort\n  const startedPromise = new Promise<void>((resolve, reject) => {\n    checkPort = (data) => {\n      const str = stripVTControlCharacters(data.toString())\n      const match = str.match(\n        /http:\\/\\/(?:localhost|127\\.0\\.0\\.1|\\[::1\\]):(\\d{4})/,\n      )\n      if (match) {\n        const startedPort = parseInt(match[1], 10)\n        if (startedPort === port) {\n          resolve()\n        } else {\n          const msg = `server listens on port ${startedPort} instead of ${port}`\n          reject(msg)\n        }\n      }\n    }\n    serverProcess.stdout.on('data', checkPort)\n  })\n  return resolvedOrTimeout(\n    startedPromise,\n    timeout,\n    `failed to start within ${timeout}ms`,\n  ).finally(() => serverProcess.stdout.off('data', checkPort))\n}\n\n// helper function that rejects with errorMessage if promise isn't settled within ms\nasync function resolvedOrTimeout(promise, ms, errorMessage) {\n  let timer\n  return Promise.race([\n    promise,\n    new Promise((_, reject) => {\n      timer = setTimeout(() => reject(errorMessage), ms)\n    }),\n  ]).finally(() => {\n    clearTimeout(timer)\n    timer = null\n  })\n}\n"
  },
  {
    "path": "playground/cli-module/index.html",
    "content": "<script type=\"module\" src=\"./index.js\"></script>\n\n<div class=\"app\">vite cli in \"type\":\"module\" package works!</div>\n"
  },
  {
    "path": "playground/cli-module/index.js",
    "content": "console.log('vite cli in \"type\":\"module\" package works!')\n"
  },
  {
    "path": "playground/cli-module/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-cli-module\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"serve\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"url\": \"^0.11.4\"\n  }\n}\n"
  },
  {
    "path": "playground/cli-module/vite.config.js",
    "content": "// eslint-disable-next-line n/prefer-node-protocol\nimport { URL } from 'url'\nimport { defineConfig } from 'vite'\n\n// make sure bundling works even if `url` refers to the locally installed\n// `url` package instead of the built-in `url` nodejs module\nglobalThis.__test_url = URL\n\nexport default defineConfig({\n  server: {\n    host: 'localhost',\n  },\n  build: {\n    //speed up build\n    minify: false,\n    target: 'esnext',\n  },\n})\n"
  },
  {
    "path": "playground/client-reload/__tests__/client-reload.spec.ts",
    "content": "import path from 'node:path'\nimport { type ServerOptions, type ViteDevServer, createServer } from 'vite'\nimport { afterEach, describe, expect, test } from 'vitest'\nimport { hmrPorts, isServe, page, ports } from '~utils'\n\nlet server: ViteDevServer\n\nafterEach(async () => {\n  await server?.close()\n})\n\nasync function testClientReload(serverOptions: ServerOptions) {\n  // start server\n  server = await createServer({\n    root: path.resolve(import.meta.dirname, '..'),\n    logLevel: 'silent',\n    server: {\n      strictPort: true,\n      ...serverOptions,\n    },\n  })\n\n  await server.listen()\n  const serverUrl = server.resolvedUrls.local[0]\n\n  // open page and wait for connection\n  const connectedPromise = page.waitForEvent('console', {\n    predicate: (message) => message.text().includes('[vite] connected.'),\n    timeout: 5000,\n  })\n  await page.goto(serverUrl)\n  await connectedPromise\n\n  // input state\n  await page.locator('input').fill('hello')\n\n  // restart and wait for reconnection after reload\n  const reConnectedPromise = page.waitForEvent('console', {\n    predicate: (message) => message.text().includes('[vite] connected.'),\n    timeout: 5000,\n  })\n  await server.restart()\n  await reConnectedPromise\n  expect(await page.textContent('input')).toBe('')\n}\n\ndescribe.runIf(isServe)('client-reload', () => {\n  test('default', async () => {\n    await testClientReload({\n      port: ports['client-reload'],\n    })\n  })\n\n  test('custom hmr port', async () => {\n    await testClientReload({\n      port: ports['client-reload/hmr-port'],\n      hmr: {\n        port: hmrPorts['client-reload/hmr-port'],\n      },\n    })\n  })\n\n  test('custom hmr port and cross origin isolation', async () => {\n    await testClientReload({\n      port: ports['client-reload/cross-origin'],\n      hmr: {\n        port: hmrPorts['client-reload/cross-origin'],\n      },\n      headers: {\n        'Cross-Origin-Embedder-Policy': 'require-corp',\n        'Cross-Origin-Opener-Policy': 'same-origin',\n      },\n    })\n  })\n})\n"
  },
  {
    "path": "playground/client-reload/__tests__/serve.ts",
    "content": "// do nothing here since server is managed inside spec\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  return {\n    close: () => Promise.resolve(),\n  }\n}\n"
  },
  {
    "path": "playground/client-reload/index.html",
    "content": "<body>\n  <h4>Test Client Reload</h4>\n  <input />\n</body>\n"
  },
  {
    "path": "playground/client-reload/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-client-reload\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/client-reload/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  server: {},\n})\n"
  },
  {
    "path": "playground/csp/__tests__/csp.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getColor, page } from '~utils'\n\ntest('linked css', async () => {\n  expect(await getColor('.linked')).toBe('blue')\n})\n\ntest('inline style tag', async () => {\n  expect(await getColor('.inline')).toBe('green')\n})\n\ntest('imported css', async () => {\n  expect(await getColor('.from-js')).toBe('blue')\n})\n\ntest('dynamic css', async () => {\n  expect(await getColor('.dynamic')).toBe('red')\n})\n\ntest('script tag', async () => {\n  await expect.poll(() => page.textContent('.js')).toBe('js: ok')\n})\n\ntest('dynamic js', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-js'))\n    .toBe('dynamic-js: ok')\n})\n\ntest('inline js', async () => {\n  await expect.poll(() => page.textContent('.inline-js')).toBe('inline-js: ok')\n})\n\ntest('nonce attributes are not repeated', async () => {\n  const htmlSource = await page.content()\n  expect(htmlSource).not.toContain(/nonce=\"\"[^>]*nonce=\"\"/)\n  await expect\n    .poll(() => page.textContent('.double-nonce-js'))\n    .toBe('double-nonce-js: ok')\n})\n\ntest('meta[property=csp-nonce] is injected', async () => {\n  const meta = await page.$('meta[property=csp-nonce]')\n  expect(await (await meta.getProperty('nonce')).jsonValue()).not.toBe('')\n})\n"
  },
  {
    "path": "playground/csp/dynamic.css",
    "content": ".dynamic {\n  color: red;\n}\n"
  },
  {
    "path": "playground/csp/dynamic.js",
    "content": "import './dynamic.css'\n\ndocument.querySelector('.dynamic-js').textContent = 'dynamic-js: ok'\n"
  },
  {
    "path": "playground/csp/from-js.css",
    "content": ".from-js {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/csp/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./linked.css\" />\n<style>\n  .inline {\n    color: green;\n  }\n</style>\n<script type=\"module\" src=\"./index.js\"></script>\n<p class=\"linked\">direct</p>\n<p class=\"inline\">inline</p>\n<p class=\"from-js\">from-js</p>\n<p class=\"dynamic\">dynamic</p>\n<p class=\"js\">js: error</p>\n<p class=\"dynamic-js\">dynamic-js: error</p>\n<p class=\"inline-js\">inline-js: error</p>\n<p class=\"double-nonce-js\">double-nonce-js: error</p>\n<script>\n  document.querySelector('.inline-js').textContent = 'inline-js: ok'\n</script>\n<script nonce=\"#$NONCE$#\">\n  // this test case is to ensure that the nonce isn't being\n  // double-applied if an existing attribute is present.\n  document.querySelector('.double-nonce-js').textContent = 'double-nonce-js: ok'\n</script>\n"
  },
  {
    "path": "playground/csp/index.js",
    "content": "import './from-js.css'\n\ndocument.querySelector('.js').textContent = 'js: ok'\n\nimport('./dynamic.js')\n"
  },
  {
    "path": "playground/csp/linked.css",
    "content": ".linked {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/csp/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-csp\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/csp/vite.config.js",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport crypto from 'node:crypto'\nimport { defineConfig } from 'vite'\n\nconst noncePlaceholder = '#$NONCE$#'\nconst createNonce = () => crypto.randomBytes(16).toString('base64')\n\n/**\n * @param {import('node:http').ServerResponse} res\n * @param {string} nonce\n */\nconst setNonceHeader = (res, nonce) => {\n  res.setHeader(\n    'Content-Security-Policy',\n    `default-src 'nonce-${nonce}'; connect-src 'self'`,\n  )\n}\n\n/**\n * @param {string} file\n * @param {(input: string, originalUrl: string) => Promise<string>} transform\n * @returns {import('vite').Connect.NextHandleFunction}\n */\nconst createMiddleware = (file, transform) => async (req, res) => {\n  const nonce = createNonce()\n  setNonceHeader(res, nonce)\n  const content = await fs.readFile(\n    path.join(import.meta.dirname, file),\n    'utf-8',\n  )\n  const transformedContent = await transform(content, req.originalUrl)\n  res.setHeader('Content-Type', 'text/html')\n  res.end(transformedContent.replaceAll(noncePlaceholder, nonce))\n}\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'nonce-inject',\n      config() {\n        return {\n          appType: 'custom',\n          html: {\n            cspNonce: noncePlaceholder,\n          },\n        }\n      },\n      configureServer({ transformIndexHtml, middlewares }) {\n        return () => {\n          middlewares.use(\n            createMiddleware('./index.html', (input, originalUrl) =>\n              transformIndexHtml(originalUrl, input),\n            ),\n          )\n        }\n      },\n      configurePreviewServer({ middlewares }) {\n        return () => {\n          middlewares.use(\n            createMiddleware('./dist/index.html', async (input) => input),\n          )\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/css/__tests__/css.spec.ts",
    "content": "import { tests } from './tests'\n\ntests(false)\n"
  },
  {
    "path": "playground/css/__tests__/lightningcss/lightningcss.spec.ts",
    "content": "// NOTE: a separate directory from `playground/css` is created by playground/vitestGlobalSetup.ts\nimport { tests } from '../tests'\n\ntests(true)\n"
  },
  {
    "path": "playground/css/__tests__/no-css-minify/css-no-css-minify.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { findAssetFile, isBuild } from '~utils'\n\ndescribe.runIf(isBuild)('no css minify', () => {\n  test('js minified but css not minified', () => {\n    expect(findAssetFile(/index-[-\\w]+\\.js$/, 'no-css-minify')).not.toMatch(\n      '(function polyfill() {',\n    )\n    expect(findAssetFile(/index-[-\\w]+\\.css$/, 'no-css-minify')).toMatch(`\\\n.test-minify {\n  color: rgba(255, 255, 0, 0.7);\n}`)\n  })\n})\n"
  },
  {
    "path": "playground/css/__tests__/postcss-plugins-different-dir/css-postcss-plugins-different-dir.spec.ts",
    "content": "import path from 'node:path'\nimport { createServer } from 'vite'\nimport { expect, test } from 'vitest'\nimport { getBgColor, getColor, isServe, page, ports } from '~utils'\n\n// Regression test for https://github.com/vitejs/vite/issues/4000\ntest.runIf(isServe)('postcss plugins in different dir', async () => {\n  const port = ports['css/postcss-plugins-different-dir']\n  const server = await createServer({\n    root: path.join(import.meta.dirname, '..', '..', '..', 'tailwind'),\n    logLevel: 'silent',\n    server: {\n      port,\n      strictPort: true,\n    },\n    build: {\n      // skip transpilation during tests to make it faster\n      target: 'esnext',\n    },\n  })\n  await server.listen()\n  try {\n    await page.goto(`http://localhost:${port}`)\n    const tailwindStyle = page.locator('#tailwind-style')\n    expect(await getBgColor(tailwindStyle)).toBe('oklch(0.936 0.032 17.717)')\n    expect(await getColor(tailwindStyle)).toBe('rgb(136, 136, 136)')\n  } finally {\n    await server.close()\n  }\n})\n"
  },
  {
    "path": "playground/css/__tests__/postcss-plugins-different-dir/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\n// The server is started in the test, so we need to have a custom serve\n// function or a default server will be created\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  return {\n    close: () => Promise.resolve(),\n  }\n}\n"
  },
  {
    "path": "playground/css/__tests__/same-file-name/css-same-file-name.spec.ts",
    "content": "import { beforeEach, describe, expect, test } from 'vitest'\nimport { findAssetFile, isBuild, startDefaultServe } from '~utils'\n\nbeforeEach(async () => {\n  await startDefaultServe()\n})\n\nfor (let i = 0; i < 5; i++) {\n  describe.runIf(isBuild)('css files has same basename', () => {\n    test('emit file name should consistent', () => {\n      expect(findAssetFile('sub.css', 'same-file-name', '.')).toMatch(\n        '.sub1-sub',\n      )\n      expect(findAssetFile('sub2.css', 'same-file-name', '.')).toMatch(\n        '.sub2-sub',\n      )\n    })\n  })\n}\n"
  },
  {
    "path": "playground/css/__tests__/sass-modern-compiler-build/sass-modern-compiler.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { findAssetFile, isBuild } from '~utils'\n\ntest.runIf(isBuild)('sass modern compiler build multiple entries', () => {\n  expect(findAssetFile(/entry1/, 'sass-modern-compiler-build'))\n    .toMatchInlineSnapshot(`\n    \".entry1{color:red}\n    \"\n  `)\n  expect(findAssetFile(/entry2/, 'sass-modern-compiler-build'))\n    .toMatchInlineSnapshot(`\n    \".entry2{color:#00f}\n    \"\n  `)\n})\n"
  },
  {
    "path": "playground/css/__tests__/sass-tests.ts",
    "content": "import { expect, test } from 'vitest'\nimport { editFile, getBg, getColor, isBuild, page, viteTestUrl } from '~utils'\n\nexport const sassTest = () => {\n  test('sass', async () => {\n    const imported = await page.$('.sass')\n    const atImport = await page.$('.sass-at-import')\n    const atImportAlias = await page.$('.sass-at-import-alias')\n    const atImportRelative = await page.$('.sass-at-import-relative')\n    const atImportReplacementAlias = await page.$(\n      '.sass-at-import-replacement-alias',\n    )\n    const urlStartsWithVariable = await page.$('.sass-url-starts-with-variable')\n    const urlStartsWithVariableInterpolation1 = await page.$(\n      '.sass-url-starts-with-interpolation1',\n    )\n    const urlStartsWithVariableInterpolation2 = await page.$(\n      '.sass-url-starts-with-interpolation2',\n    )\n    const urlStartsWithVariableConcat = await page.$(\n      '.sass-url-starts-with-variable-concat',\n    )\n    const urlStartsWithFunctionCall = await page.$(\n      '.sass-url-starts-with-function-call',\n    )\n    const partialImport = await page.$('.sass-partial')\n\n    expect(await getColor(imported)).toBe('orange')\n    expect(await getColor(atImport)).toBe('olive')\n    expect(await getBg(atImport)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(atImportAlias)).toBe('olive')\n    expect(await getBg(atImportAlias)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(atImportRelative)).toBe('olive')\n    expect(await getBg(atImportRelative)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(atImportReplacementAlias)).toBe('olive')\n    expect(await getBg(urlStartsWithVariable)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n    expect(await getBg(urlStartsWithVariableInterpolation1)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n    expect(await getBg(urlStartsWithVariableInterpolation2)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n    expect(await getBg(urlStartsWithVariableConcat)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n    expect(await getBg(urlStartsWithFunctionCall)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n    expect(await getColor(partialImport)).toBe('orchid')\n    expect(await getColor(await page.$('.sass-file-absolute'))).toBe('orange')\n    expect(await getColor(await page.$('.sass-dir-index'))).toBe('orange')\n    expect(await getColor(await page.$('.sass-root-relative'))).toBe('orange')\n\n    if (isBuild) return\n\n    editFile('sass.scss', (code) =>\n      code.replace('color: $injectedColor', 'color: red'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('red')\n\n    editFile('nested/_index.scss', (code) =>\n      code.replace('color: olive', 'color: blue'),\n    )\n    await expect.poll(() => getColor(atImport)).toBe('blue')\n\n    editFile('nested/_partial.scss', (code) =>\n      code.replace('color: orchid', 'color: green'),\n    )\n    await expect.poll(() => getColor(partialImport)).toBe('green')\n  })\n}\n\nexport const sassModuleTests = (enableHmrTests = false) => {\n  test('sass modules composes/from path resolving', async () => {\n    const imported = await page.$('.path-resolved-modules-sass')\n    expect(await getColor(imported)).toBe('orangered')\n\n    // check if the generated CSS module class name is indeed using the\n    // format specified in vite.config.js\n    expect(await imported.getAttribute('class')).toMatch(\n      /.composed-module__apply-color___[\\w-]{5}/,\n    )\n\n    expect(await imported.getAttribute('class')).toMatch(\n      /.composes-path-resolving-module__path-resolving-sass___[\\w-]{5}/,\n    )\n\n    // @todo HMR is not working on this situation.\n    // editFile('composed.module.scss', (code) =>\n    //   code.replace('color: orangered', 'color: red')\n    // )\n    // await expect.poll(() => getColor(imported)).toMatch('red')\n  })\n\n  test('css modules w/ sass', async () => {\n    const imported = await page.$('.modules-sass')\n    expect(await getColor(imported)).toBe('orangered')\n    expect(await imported.getAttribute('class')).toMatch(\n      /.mod-module__apply-color___[\\w-]{5}/,\n    )\n\n    if (isBuild) return\n\n    editFile('mod.module.scss', (code) =>\n      code.replace('color: orangered', 'color: blue'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('blue')\n  })\n}\n\nexport const sassOtherTests = () => {\n  test('@import dependency w/ sass entry', async () => {\n    expect(await getColor('.css-dep-sass')).toBe('orange')\n  })\n\n  test('@import dependency w/ sass export mapping', async () => {\n    expect(await getColor('.css-dep-exports-sass')).toBe('orange')\n  })\n\n  test('@import dependency w/ sass export mapping (deep)', async () => {\n    expect(await getColor('.css-dep-exports-deep-sass')).toBe('orange')\n  })\n\n  test('@import dependency w/out package scss', async () => {\n    expect(await getColor('.sass-dep')).toBe('lavender')\n  })\n}\n"
  },
  {
    "path": "playground/css/__tests__/tests.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { expect, test } from 'vitest'\nimport { sassModuleTests, sassOtherTests, sassTest } from './sass-tests'\nimport {\n  editFile,\n  findAssetFile,\n  getBg,\n  getBgColor,\n  getColor,\n  isBuild,\n  page,\n  removeFile,\n  serverLogs,\n  viteTestUrl,\n} from '~utils'\n\nexport const tests = (isLightningCSS: boolean) => {\n  // note: tests should retrieve the element at the beginning of test and reuse it\n  // in later assertions to ensure CSS HMR doesn't reload the page\n  test('imported css', async () => {\n    const glob = await page.textContent('.imported-css-glob')\n    expect(glob).toContain('.dir-import')\n    const globEager = await page.textContent('.imported-css-globEager')\n    expect(globEager).toContain('.dir-import')\n  })\n\n  test('linked css', async () => {\n    const linked = await page.$('.linked')\n    const atImport = await page.$('.linked-at-import')\n\n    expect(await getColor(linked)).toBe('blue')\n    expect(await getColor(atImport)).toBe('red')\n\n    if (isBuild) return\n\n    editFile('linked.css', (code) => code.replace('color: blue', 'color: red'))\n    await expect.poll(() => getColor(linked)).toBe('red')\n\n    editFile('linked-at-import.css', (code) =>\n      code.replace('color: red', 'color: blue'),\n    )\n    await expect.poll(() => getColor(atImport)).toBe('blue')\n  })\n\n  test('css import from js', async () => {\n    const imported = await page.$('.imported')\n    const atImport = await page.$('.imported-at-import')\n\n    expect(await getColor(imported)).toBe('green')\n    expect(await getColor(atImport)).toBe('purple')\n\n    if (isBuild) return\n\n    editFile('imported.css', (code) =>\n      code.replace('color: green', 'color: red'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('red')\n\n    editFile('imported-at-import.css', (code) =>\n      code.replace('color: purple', 'color: blue'),\n    )\n    await expect.poll(() => getColor(atImport)).toBe('blue')\n  })\n\n  test('css import asset with space', async () => {\n    const importedWithSpace = await page.$('.import-with-space')\n\n    expect(await getBg(importedWithSpace)).toMatch(/.*\\/ok.*\\.png/)\n  })\n\n  test('postcss config', async () => {\n    const imported = await page.$('.postcss .nesting')\n    expect(await getColor(imported)).toBe('pink')\n\n    if (isBuild) return\n\n    editFile('imported.css', (code) =>\n      code.replace('color: pink', 'color: red'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('red')\n  })\n\n  test('postcss plugin that injects url()', async () => {\n    const imported = await page.$('.inject-url')\n    // alias should be resolved\n    expect(await getBg(imported)).toMatch(\n      /localhost(?::\\d+)?\\/(?:assets\\/)?ok.*\\.png/,\n    )\n  })\n\n  sassTest()\n\n  test('less', async () => {\n    const imported = await page.$('.less')\n    const atImport = await page.$('.less-at-import')\n    const atImportAlias = await page.$('.less-at-import-alias')\n    const atImportUrlOmmer = await page.$('.less-at-import-url-ommer')\n    const urlStartsWithVariable = await page.$('.less-url-starts-with-variable')\n    const urlStartsWithInterpolation = await page.$(\n      '.less-url-starts-with-interpolation',\n    )\n\n    expect(await getColor(imported)).toBe('blue')\n    expect(await getColor(atImport)).toBe('darkslateblue')\n    expect(await getBg(atImport)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(atImportAlias)).toBe('darkslateblue')\n    expect(await getBg(atImportAlias)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(atImportUrlOmmer)).toBe('darkorange')\n    expect(await getBg(urlStartsWithVariable)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n    expect(await getBg(urlStartsWithInterpolation)).toMatch(\n      isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n    )\n\n    if (isBuild) return\n\n    editFile('less.less', (code) => code.replace('@color: blue', '@color: red'))\n    await expect.poll(() => getColor(imported)).toBe('red')\n\n    editFile('nested/nested.less', (code) =>\n      code.replace('color: darkslateblue', 'color: blue'),\n    )\n    await expect.poll(() => getColor(atImport)).toBe('blue')\n  })\n\n  test('less-plugin', async () => {\n    const body = await page.$('.less-js-plugin')\n    expect(await getBg(body)).toBe(\n      'url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdjYGD4/x8AAwIB/8myre4AAAAASUVORK5CYII=\")',\n    )\n  })\n\n  test('stylus', async () => {\n    const imported = await page.$('.stylus')\n    const additionalData = await page.$('.stylus-additional-data')\n    const relativeImport = await page.$('.stylus-import')\n    const relativeImportAlias = await page.$('.stylus-import-alias')\n    const optionsRelativeImport = await page.$(\n      '.stylus-options-relative-import',\n    )\n    const optionsAbsoluteImport = await page.$(\n      '.stylus-options-absolute-import',\n    )\n    const optionsDefineVar = await page.$('.stylus-options-define-var')\n    const optionsDefineFunc = await page.$('.stylus-options-define-func')\n\n    expect(await getColor(imported)).toBe('blue')\n    expect(await getColor(additionalData)).toBe('orange')\n    expect(await getColor(relativeImport)).toBe('darkslateblue')\n    expect(await getColor(relativeImportAlias)).toBe('darkslateblue')\n    expect(await getBg(relativeImportAlias)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(optionsRelativeImport)).toBe('green')\n    expect(await getColor(optionsAbsoluteImport)).toBe('red')\n    expect(await getColor(optionsDefineVar)).toBe('rgb(51, 197, 255)')\n    expect(await getColor(optionsDefineFunc)).toBe('rgb(255, 0, 98)')\n\n    if (isBuild) return\n\n    editFile('stylus.styl', (code) =>\n      code.replace('$color ?= blue', '$color ?= red'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('red')\n\n    editFile('nested/nested.styl', (code) =>\n      code.replace('color darkslateblue', 'color blue'),\n    )\n    await expect.poll(() => getColor(relativeImport)).toBe('blue')\n  })\n\n  test('css modules', async () => {\n    const imported = await page.$('.modules')\n    expect(await getColor(imported)).toBe('turquoise')\n\n    // check if the generated CSS module class name is indeed using the\n    // format specified in vite.config.js\n    expect(await imported.getAttribute('class')).toMatch(\n      /.mod-module__apply-color___[\\w-]{5}/,\n    )\n\n    if (isBuild) return\n\n    editFile('mod.module.css', (code) =>\n      code.replace('color: turquoise', 'color: red'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('red')\n  })\n\n  test('css modules composes/from path resolving', async () => {\n    const imported = await page.$('.path-resolved-modules-css')\n    expect(await getColor(imported)).toBe('turquoise')\n\n    // check if the generated CSS module class name is indeed using the\n    // format specified in vite.config.js\n    expect(await imported.getAttribute('class')).toMatch(\n      /.composed-module__apply-color___[\\w-]{5}/,\n    )\n\n    expect(await imported.getAttribute('class')).toMatch(\n      /.composes-path-resolving-module__path-resolving-css___[\\w-]{5}/,\n    )\n\n    // @todo HMR is not working on this situation.\n    // editFile('composed.module.css', (code) =>\n    //   code.replace('color: turquoise', 'color: red')\n    // )\n    // await expect.poll(() => getColor(imported)).toBe('red')\n  })\n\n  sassModuleTests()\n\n  test('less modules composes/from path resolving', async () => {\n    const imported = await page.$('.path-resolved-modules-less')\n    expect(await getColor(imported)).toBe('blue')\n\n    // check if the generated CSS module class name is indeed using the\n    // format specified in vite.config.js\n    expect(await imported.getAttribute('class')).toMatch(\n      /.composed-module__apply-color___[\\w-]{5}/,\n    )\n\n    expect(await imported.getAttribute('class')).toMatch(\n      /.composes-path-resolving-module__path-resolving-less___[\\w-]{5}/,\n    )\n\n    // @todo HMR is not working on this situation.\n    // editFile('composed.module.scss', (code) =>\n    //   code.replace('color: orangered', 'color: red')\n    // )\n    // await expect.poll(() => getColor(imported)).toBe('red')\n  })\n\n  test('inline css modules', async () => {\n    const css = await page.textContent('.modules-inline')\n    expect(css).toMatch(/\\.inline-module__apply-color-inline___[\\w-]{5}/)\n  })\n\n  test.runIf(isBuild)('@charset hoist', async () => {\n    serverLogs.forEach((log) => {\n      // no warning from esbuild css minifier\n      expect(log).not.toMatch('\"@charset\" must be the first rule in the file')\n    })\n  })\n\n  test('layers', async () => {\n    expect(await getColor('.layers-blue')).toMatch('blue')\n    expect(await getColor('.layers-green')).toMatch('green')\n  })\n\n  test('@import dependency w/ style entry', async () => {\n    expect(await getColor('.css-dep')).toBe('purple')\n  })\n\n  test('@import dependency w/ style export mapping', async () => {\n    expect(await getColor('.css-dep-exports')).toBe('purple')\n  })\n\n  test('@import dependency that @import another dependency', async () => {\n    expect(await getColor('.css-proxy-dep')).toBe('purple')\n  })\n\n  test('@import scss dependency that has @import with a css extension pointing to another dependency', async () => {\n    expect(await getColor('.scss-proxy-dep')).toBe('purple')\n  })\n\n  sassOtherTests()\n\n  test('async chunk', async () => {\n    const el = await page.$('.async')\n    expect(await getColor(el)).toBe('teal')\n\n    if (isBuild) {\n      // assert that the css is extracted into its own file instead of in the\n      // main css file\n      expect(findAssetFile(/index-[-\\w]{8}\\.css$/)).not.toMatch('teal')\n      expect(findAssetFile(/async-[-\\w]{8}\\.css$/)).toMatch(\n        '.async{color:teal}',\n      )\n    } else {\n      // test hmr\n      editFile('async.css', (code) =>\n        code.replace('color: teal', 'color: blue'),\n      )\n      await expect.poll(() => getColor(el)).toBe('blue')\n    }\n  })\n\n  test('treeshaken async chunk', async () => {\n    if (isBuild) {\n      // should be absent in prod\n      expect(\n        await page.evaluate(() => {\n          return document.querySelector('.async-treeshaken')\n        }),\n      ).toBeNull()\n      // assert that the css is not present anywhere\n      expect(findAssetFile(/\\.css$/)).not.toMatch('plum')\n      expect(findAssetFile(/index-[-\\w]+\\.js$/)).not.toMatch(\n        '.async{color:plum}',\n      )\n      expect(findAssetFile(/async-[-\\w]+\\.js$/)).not.toMatch(\n        '.async{color:plum}',\n      )\n      // should have no chunk!\n      expect(findAssetFile(/async-treeshaken/)).toBeUndefined()\n    } else {\n      // should be present in dev\n      const el = await page.$('.async-treeshaken')\n      editFile('async-treeshaken.css', (code) =>\n        code.replace('color: plum', 'color: blue'),\n      )\n      await expect.poll(() => getColor(el)).toBe('blue')\n    }\n  })\n\n  test('PostCSS dir-dependency', async () => {\n    const el1 = await page.$('.dir-dep')\n    const el2 = await page.$('.dir-dep-2')\n    const el3 = await page.$('.dir-dep-3')\n\n    expect(await getColor(el1)).toBe('grey')\n    expect(await getColor(el2)).toBe('grey')\n    expect(await getColor(el3)).toBe('grey')\n\n    // NOTE: lightningcss does not support registering dependencies in plugins\n    if (!isBuild && !isLightningCSS) {\n      editFile('glob-dep/foo.css', (code) =>\n        code.replace('color: grey', 'color: blue'),\n      )\n      await expect.poll(() => getColor(el1)).toBe('blue')\n      expect(await getColor(el2)).toBe('grey')\n\n      editFile('glob-dep/bar.css', (code) =>\n        code.replace('color: grey', 'color: red'),\n      )\n      await expect.poll(() => getColor(el2)).toBe('red')\n      expect(await getColor(el1)).toBe('blue')\n\n      editFile('glob-dep/nested (dir)/baz.css', (code) =>\n        code.replace('color: grey', 'color: green'),\n      )\n      await expect.poll(() => getColor(el3)).toBe('green')\n      expect(await getColor(el1)).toBe('blue')\n      expect(await getColor(el2)).toBe('red')\n\n      // test add/remove\n      removeFile('glob-dep/bar.css')\n      await expect.poll(() => getColor(el2)).toBe('black')\n    }\n  })\n\n  test('import dependency includes css import', async () => {\n    expect(await getColor('.css-js-dep')).toBe('green')\n    expect(await getColor('.css-js-dep-module')).toBe('green')\n  })\n\n  test('URL separation', async () => {\n    const urlSeparated = await page.$('.url-separated')\n    const baseUrl = 'url(images/dog.webp)'\n    const cases = new Array(5)\n      .fill('')\n      .flatMap((_, i) =>\n        [',', ' ,', ', ', ' , '].map(\n          (sep) =>\n            `background-image:${new Array(i + 1).fill(baseUrl).join(sep)};`,\n        ),\n      )\n\n    // Insert the base case\n    cases.unshift('background-image:url(images/cat.webp),url(images/dog.webp)')\n\n    for (const [c, i] of cases.map((c, i) => [c, i]) as [string, number][]) {\n      // Replace the previous case\n      if (i > 0)\n        editFile('imported.css', (code) => code.replace(cases[i - 1], c))\n\n      expect(await getBg(urlSeparated)).toMatch(\n        /^url\\(.+\\)(?:\\s*,\\s*url\\(.+\\))*$/,\n      )\n    }\n  })\n\n  test('inlined', async () => {\n    // should not insert css\n    expect(await getColor('.inlined')).toBe('black')\n  })\n\n  test('inlined-code', async () => {\n    const code = await page.textContent('.inlined-code')\n    // should resolve assets\n    expect(code).toContain('background:')\n    expect(code).not.toContain('__VITE_ASSET__')\n\n    if (isBuild) {\n      expect(code.trim()).not.toContain('\\n') // check minified\n    }\n  })\n\n  test('minify css', async () => {\n    if (!isBuild) {\n      return\n    }\n\n    // should keep the rgba() syntax\n    const cssFile = findAssetFile(/index-[-\\w]+\\.css$/)\n    expect(cssFile).toMatch('rgba(')\n    expect(cssFile).not.toMatch('#ffff00b3')\n  })\n\n  test('?url', async () => {\n    expect(await getColor('.url-imported-css')).toBe('yellow')\n  })\n\n  test('?raw', async () => {\n    const rawImportCss = await page.$('.raw-imported-css')\n\n    expect(await rawImportCss.textContent()).toBe(\n      readFileSync(require.resolve('../raw-imported.css'), 'utf-8'),\n    )\n\n    if (!isBuild) {\n      editFile('raw-imported.css', (code) =>\n        code.replace('color: yellow', 'color: blue'),\n      )\n      await expect\n        .poll(() => page.textContent('.raw-imported-css'))\n        .toMatch('color: blue')\n    }\n  })\n\n  test('import css in less', async () => {\n    expect(await getColor('.css-in-less')).toBe('yellow')\n    expect(await getColor('.css-in-less-2')).toBe('blue')\n  })\n\n  test(\"relative path rewritten in Less's data-uri\", async () => {\n    // relative path passed to Less's data-uri is rewritten to absolute,\n    // the Less inlines it\n    expect(await getBg('.form-box-data-uri')).toMatch(\n      /^url\\(\"data:image\\/svg\\+xml,%3Csvg/,\n    )\n  })\n\n  test('PostCSS source.input.from includes query', async () => {\n    const code = await page.textContent('.postcss-source-input')\n    // should resolve assets\n    expect(code).toContain('/postcss-source-input.css?inline&query=foo')\n  })\n\n  test('aliased css has content', async () => {\n    expect(await getColor('.aliased')).toBe('blue')\n    // skipped: currently not supported see #8936\n    // expect(await page.textContent('.aliased-content')).toMatch('.aliased')\n    expect(await getColor('.aliased-module')).toBe('blue')\n  })\n\n  test('resolve imports field in CSS', async () => {\n    expect(await getColor('.imports-field')).toBe('red')\n  })\n\n  test.runIf(isBuild)(\n    'warning can be suppressed by esbuild.logOverride',\n    () => {\n      serverLogs.forEach((log) => {\n        // no warning from esbuild css minifier\n        expect(log).not.toMatch('unsupported-css-property')\n      })\n    },\n  )\n\n  test('sugarss', async () => {\n    const imported = await page.$('.sugarss')\n    const atImport = await page.$('.sugarss-at-import')\n    const atImportAlias = await page.$('.sugarss-at-import-alias')\n\n    expect(await getColor(imported)).toBe('blue')\n    expect(await getColor(atImport)).toBe('darkslateblue')\n    expect(await getBg(atImport)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n    expect(await getColor(atImportAlias)).toBe('darkslateblue')\n    expect(await getBg(atImportAlias)).toMatch(\n      isBuild ? /base64/ : '/nested/icon.png',\n    )\n\n    if (isBuild) return\n\n    editFile('sugarss.sss', (code) =>\n      code.replace('color: blue', 'color: coral'),\n    )\n    await expect.poll(() => getColor(imported)).toBe('coral')\n\n    editFile('nested/nested.sss', (code) =>\n      code.replace('color: darkslateblue', 'color: blue'),\n    )\n    await expect.poll(() => getColor(atImport)).toBe('blue')\n  })\n\n  // NOTE: the match inline snapshot should generate by build mode\n  test('async css order', async () => {\n    await expect.poll(() => getColor('.async-green')).toBe('green')\n    await expect.poll(() => getColor('.async-blue')).toBe('blue')\n  })\n\n  test('async css order with css modules', async () => {\n    await expect.poll(() => getColor('.modules-pink')).toBe('pink')\n  })\n\n  test('@import scss', async () => {\n    expect(await getColor('.at-import-scss')).toBe('red')\n  })\n\n  // TODO: skipped because of https://github.com/rolldown/rolldown/issues/7315\n  test.runIf(isBuild).skip('manual chunk path', async () => {\n    // assert that the manual-chunk css is output in the directory specified in manualChunk (#12072)\n    expect(\n      findAssetFile(\n        /manual-chunk-[-\\w]{8}\\.css$/,\n        undefined,\n        'assets/dir/dir2',\n      ),\n    ).not.toBeUndefined()\n  })\n\n  test.runIf(isBuild)('CSS modules should be treeshaken if not used', () => {\n    const css = findAssetFile(/\\.css$/, undefined, undefined, true)\n    expect(css).not.toContain('treeshake-module-b')\n  })\n\n  test.runIf(isBuild)('Scoped CSS via cssScopeTo should be treeshaken', () => {\n    const css = findAssetFile(/\\.css$/, undefined, undefined, true)\n    expect(css).not.toMatch(/\\btreeshake-scoped-b\\b/)\n    expect(css).not.toMatch(/\\btreeshake-scoped-c\\b/)\n  })\n\n  test('Scoped CSS should have a correct order', async () => {\n    await page.goto(viteTestUrl + '/treeshake-scoped/')\n    expect(await getColor('.treeshake-scoped-order')).toBe('red')\n    expect(await getBgColor('.treeshake-scoped-order')).toBe('blue')\n  })\n\n  test.runIf(isBuild)(\n    'empty CSS files should generate .css assets, not .js assets',\n    () => {\n      // Check that empty CSS entry point generates a .css file, not a .js file\n      expect(findAssetFile(/empty-[-\\w]{8}\\.css$/)).not.toBeUndefined()\n      expect(findAssetFile(/empty-[-\\w]{8}\\.js$/)).toBeUndefined()\n    },\n  )\n}\n"
  },
  {
    "path": "playground/css/aliased/bar.module.css",
    "content": ".aliasedModule {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/aliased/foo.css",
    "content": ".aliased {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/async/async-1.css",
    "content": ".async-blue {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/async/async-1.js",
    "content": "import { createButton } from './base'\nimport './async-1.css'\n\ncreateButton('async-blue')\n"
  },
  {
    "path": "playground/css/async/async-2.css",
    "content": ".async-green {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css/async/async-2.js",
    "content": "import { createButton } from './base'\nimport './async-2.css'\n\ncreateButton('async-green')\n"
  },
  {
    "path": "playground/css/async/async-3.js",
    "content": "import { createButton } from './base'\nimport styles from './async-3.module.css'\n\ncreateButton(`${styles['async-pink']} modules-pink`)\n"
  },
  {
    "path": "playground/css/async/async-3.module.css",
    "content": ".async-pink {\n  color: pink;\n}\n"
  },
  {
    "path": "playground/css/async/base.css",
    "content": ".btn {\n  color: black;\n}\n"
  },
  {
    "path": "playground/css/async/base.js",
    "content": "import './base.css'\n\nexport function createButton(className) {\n  const button = document.createElement('button')\n  button.className = `btn ${className}`\n  document.body.appendChild(button)\n  button.textContent = `button ${getComputedStyle(button).color}`\n}\n"
  },
  {
    "path": "playground/css/async/index.js",
    "content": "import('./async-1.js')\nimport('./async-2.js')\nimport('./async-3.js')\n"
  },
  {
    "path": "playground/css/async-treeshaken.css",
    "content": ".async-treeshaken {\n  color: plum;\n}\n"
  },
  {
    "path": "playground/css/async-treeshaken.js",
    "content": "import './async-treeshaken.css'\n\nconst div = document.createElement('div')\ndiv.className = 'async-treeshaken'\ndiv.textContent =\n  'async treeshaken chunk (this should be plum and should not show up in prod)'\ndocument.body.appendChild(div)\n"
  },
  {
    "path": "playground/css/async.css",
    "content": ".async {\n  color: teal;\n}\n"
  },
  {
    "path": "playground/css/async.js",
    "content": "import './async.css'\n\nconst div = document.createElement('div')\ndiv.className = 'async'\ndocument.body.appendChild(div)\ndiv.textContent = `async chunk (this should be teal) ${\n  getComputedStyle(div).color\n}`\n"
  },
  {
    "path": "playground/css/charset.css",
    "content": "@charset \"utf-8\";\n\n.utf8 {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css/composed.module.css",
    "content": ".apply-color {\n  color: turquoise;\n}\n"
  },
  {
    "path": "playground/css/composed.module.less",
    "content": ".apply-color {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/composed.module.scss",
    "content": ".apply-color {\n  color: orangered;\n}\n"
  },
  {
    "path": "playground/css/composes-path-resolving.module.css",
    "content": ".path-resolving-css {\n  composes: apply-color from '=/composed.module.css';\n}\n\n.path-resolving-sass {\n  composes: apply-color from '=/composed.module.scss';\n}\n\n.path-resolving-less {\n  composes: apply-color from '=/composed.module.less';\n}\n"
  },
  {
    "path": "playground/css/css-dep/index.css",
    "content": ".css-dep {\n  color: purple;\n}\n"
  },
  {
    "path": "playground/css/css-dep/index.js",
    "content": "throw new Error('should not be imported')\n"
  },
  {
    "path": "playground/css/css-dep/index.scss",
    "content": ".css-dep-sass {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/css-dep/index.styl",
    "content": ".css-dep-stylus\n  color red\n"
  },
  {
    "path": "playground/css/css-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-dep\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"style\": \"index.css\",\n  \"sass\": \"index.scss\"\n}\n"
  },
  {
    "path": "playground/css/css-dep-exports/foo1.scss",
    "content": ".css-dep-exports-deep-sass {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/css-dep-exports/index.js",
    "content": "throw new Error('should not be imported')\n"
  },
  {
    "path": "playground/css/css-dep-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-dep-exports\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \".\": {\n      \"sass\": \"./style.scss\",\n      \"style\": \"./style.css\",\n      \"import\": \"./index.js\"\n    },\n    \"./foo.scss\": {\n      \"sass\": \"./foo1.scss\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/css/css-dep-exports/style.css",
    "content": ".css-dep-exports {\n  color: purple;\n}\n"
  },
  {
    "path": "playground/css/css-dep-exports/style.scss",
    "content": ".css-dep-exports-sass {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/css-js-dep/bar.module.css",
    "content": ".cssJsDepModule {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css/css-js-dep/foo.css",
    "content": ".css-js-dep {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css/css-js-dep/index.js",
    "content": "import './foo.css'\nimport barModuleClasses from './bar.module.css'\n\nexport { barModuleClasses }\n"
  },
  {
    "path": "playground/css/css-js-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-js-dep\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/css/css-proxy-dep/index.css",
    "content": "@import '@vitejs/test-css-proxy-dep-nested';\n"
  },
  {
    "path": "playground/css/css-proxy-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-proxy-dep\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"style\": \"index.css\",\n  \"dependencies\": {\n    \"@vitejs/test-css-proxy-dep-nested\": \"file:../css-proxy-dep-nested\"\n  }\n}\n"
  },
  {
    "path": "playground/css/css-proxy-dep-nested/index.css",
    "content": ".css-proxy-dep {\n  color: purple;\n}\n"
  },
  {
    "path": "playground/css/css-proxy-dep-nested/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-proxy-dep-nested\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"style\": \"index.css\"\n}\n"
  },
  {
    "path": "playground/css/dep.css",
    "content": "@import '@vitejs/test-css-dep';\n@import '@vitejs/test-css-dep-exports';\n@import '@vitejs/test-css-proxy-dep';\n"
  },
  {
    "path": "playground/css/empty.css",
    "content": ""
  },
  {
    "path": "playground/css/file-absolute.scss",
    "content": ".sass-file-absolute {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/folder with space/space.css",
    "content": ".import-with-space {\n  color: green;\n  background: url(spacefolder/ok.png);\n  background-position: center;\n}\n"
  },
  {
    "path": "playground/css/glob-dep/bar.css",
    "content": ".dir-dep-2 {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/css/glob-dep/foo.css",
    "content": ".dir-dep {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/css/glob-dep/nested (dir)/baz.css",
    "content": ".dir-dep-3 {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/css/glob-dep.css",
    "content": "@test;\n"
  },
  {
    "path": "playground/css/glob-import/bar.css",
    "content": ".dir-import-2 {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/css/glob-import/foo.css",
    "content": ".dir-import {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/css/imported-at-import.css",
    "content": ".imported-at-import {\n  color: purple;\n}\n"
  },
  {
    "path": "playground/css/imported.css",
    "content": "@import './imported-at-import.css';\n@import 'spacefolder/space.css';\n\n.imported {\n  color: green;\n}\n\npre {\n  background-color: #eee;\n  width: 500px;\n  padding: 1em 1.5em;\n  border-radius: 10px;\n}\n\n/* test postcss nesting */\n.postcss {\n  .nesting {\n    color: pink;\n  }\n}\n\n/* test url comma separation */\n.url-separated {\n  /* prettier-ignore */\n  background-image:url(images/cat.webp),url(images/dog.webp);\n}\n"
  },
  {
    "path": "playground/css/imported.scss",
    "content": "$color: red;\n\n.at-import-scss {\n  color: $color;\n}\n"
  },
  {
    "path": "playground/css/imports-field.css",
    "content": ".imports-field {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/imports-imports-field.css",
    "content": "@import '#imports';\n"
  },
  {
    "path": "playground/css/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./linked.css\" />\n\n<div class=\"wrapper\">\n  <h1>CSS</h1>\n\n  <p class=\"linked\">&lt;link&gt;: This should be blue</p>\n  <p class=\"linked-at-import\">@import in &lt;link&gt;: This should be red</p>\n\n  <p class=\"imported\">import from js: This should be green</p>\n  <p class=\"imported-at-import\">\n    @import in import from js: This should be purple\n  </p>\n  <p class=\"import-with-space\">\n    @import from file with space: This should be green and have a background\n    image\n  </p>\n  <p>Imported css string:</p>\n  <pre class=\"imported-css-glob\"></pre>\n  <pre class=\"imported-css-globEager\"></pre>\n\n  <p class=\"scoped\">Imported scoped CSS</p>\n\n  <p class=\"postcss\">\n    <span class=\"nesting\">PostCSS nesting plugin: this should be pink</span>\n  </p>\n  <p class=\"inject-url\">PostCSS plugin: this should have a background image</p>\n\n  <p class=\"sass\">SASS: This should be orange</p>\n  <p class=\"sass-at-import\">\n    @import from SASS _index: This should be olive and have bg image\n  </p>\n  <p class=\"sass-at-import-alias\">\n    @import from SASS _index: This should be olive and have bg image which url\n    contains alias\n  </p>\n  <p class=\"sass-at-import-relative\">\n    @import from SASS relative: This should be olive and have bg image\n  </p>\n  <p class=\"sass-at-import-replacement-alias\">\n    @import with replacement alias from SASS: This should be olive\n  </p>\n  <p class=\"sass-partial\">@import from SASS _partial: This should be orchid</p>\n  <p class=\"sass-url-starts-with-variable\">url starts with variable</p>\n  <p class=\"sass-url-starts-with-interpolation1\">\n    url starts with interpolation 1\n  </p>\n  <p class=\"sass-url-starts-with-interpolation2\">\n    url starts with interpolation 2\n  </p>\n  <p class=\"sass-url-starts-with-variable-concat\">\n    url starts with variable and contains concat\n  </p>\n  <p class=\"sass-url-starts-with-function-call\">\n    url starts with function call\n  </p>\n  <p>Imported SASS string:</p>\n  <p class=\"sass-dep\">\n    @import dependency w/ no scss entrypoint: this should be lavender\n  </p>\n  <p class=\"sass-file-absolute\">\n    @import \"file:///xxx/absolute-path.scss\" should be orange\n  </p>\n  <p class=\"sass-dir-index\">@import \"./dir\" should be orange</p>\n  <p class=\"sass-root-relative\">\n    @import \"/nested/root-relative.scss\" should be orange\n  </p>\n\n  <p class=\"less\">Less: This should be blue</p>\n  <p class=\"less-at-import\">\n    @import from Less: This should be darkslateblue and have bg image\n  </p>\n  <p class=\"less-at-import-alias\">\n    @import from Less: This should be darkslateblue and have bg image which url\n    contains alias\n  </p>\n  <p class=\"less-at-import-url-ommer\">\n    @import url() from Less: This should be darkorange\n  </p>\n  <p class=\"less-url-starts-with-variable\">url starts with variable</p>\n  <p class=\"less-url-starts-with-interpolation\">\n    url starts with interpolation\n  </p>\n\n  <div class=\"form-box-data-uri\">\n    tests Less's `data-uri()` function with relative image paths\n  </div>\n  <div>\n    url in Less's JS plugin: This should have a blue square below\n    <div class=\"less-js-plugin\"></div>\n  </div>\n\n  <p class=\"stylus\">Stylus: This should be blue</p>\n  <p class=\"stylus-additional-data\">\n    Stylus additionalData: This should be orange\n  </p>\n  <p class=\"stylus-import\">@import from Stylus: This should be darkslateblue</p>\n  <p class=\"stylus-import-alias\">\n    @import from Stylus: This should be darkslateblue and have bg image which\n    url contains alias\n  </p>\n  <p class=\"stylus-options-relative-import\">\n    Stylus import (relative path) via vite config preprocessor options: This\n    should be green\n  </p>\n  <p class=\"stylus-options-absolute-import\">\n    Stylus import (absolute path) via vite config preprocessor options: This\n    should be red\n  </p>\n  <p class=\"stylus-options-define-var\">\n    Stylus define variable via vite config preprocessor options: This should be\n    rgb(51, 197, 255)\n  </p>\n  <p class=\"stylus-options-define-func\">\n    Stylus define function via vite config preprocessor options: This should be\n    rgb(255, 0, 98)\n  </p>\n\n  <p class=\"sugarss\">SugarSS: This should be blue</p>\n  <p class=\"sugarss-at-import\">\n    @import from SugarSS: This should be darkslateblue and have bg image\n  </p>\n  <p class=\"sugarss-at-import-alias\">\n    @import from SugarSS: This should be darkslateblue and have bg image which\n    url contains alias\n  </p>\n\n  <p class=\"modules\">CSS modules: this should be turquoise</p>\n  <p>Imported CSS module:</p>\n  <pre class=\"modules-code\"></pre>\n\n  <p class=\"modules-sass\">CSS modules w/ SASS: this should be orangered</p>\n  <p>Imported SASS module:</p>\n  <pre class=\"modules-sass-code\"></pre>\n\n  <p class=\"modules-treeshake\">CSS modules should treeshake in build</p>\n\n  <p>Imported compose/from CSS/SASS module:</p>\n  <p class=\"path-resolved-modules-css\">\n    CSS modules composes path resolving: this should be turquoise\n  </p>\n  <p class=\"path-resolved-modules-sass\">\n    CSS modules composes path resolving: this should be orangered\n  </p>\n  <p class=\"path-resolved-modules-less\">\n    CSS modules composes path resolving: this should be blue\n  </p>\n  <pre class=\"path-resolved-modules-code\"></pre>\n\n  <p>Inline CSS module:</p>\n  <pre class=\"modules-inline\"></pre>\n\n  <p>CSS with @charset:</p>\n  <pre class=\"charset-css\"></pre>\n\n  <p>\n    @import with layers:\n    <span class=\"layers-blue\">blue</span>\n    <span class=\"layers-green\">green</span>\n  </p>\n\n  <p class=\"css-dep\">\n    @import dependency w/ style entrypoints: this should be purple\n  </p>\n  <p class=\"css-dep-sass\">\n    @import dependency w/ sass entrypoints: this should be orange\n  </p>\n\n  <p class=\"css-dep-exports\">\n    @import dependency w/ style export mapping: this should be purple\n  </p>\n  <p class=\"css-dep-exports-sass\">\n    @import dependency w/ sass export mapping: this should be orange\n  </p>\n  <p class=\"css-dep-exports-deep-sass\">\n    @import dependency w/ sass export mapping (deep): this should be orange\n  </p>\n\n  <p class=\"css-proxy-dep\">\n    @import dependency that @import another dependency: this should be purple\n  </p>\n  <p class=\"scss-proxy-dep\">\n    @import dependency that has @import with a css extension pointing to another\n    dependency: this should be purple\n  </p>\n\n  <p class=\"dir-dep\">PostCSS dir-dependency: this should be grey</p>\n  <p class=\"dir-dep-2\">\n    PostCSS dir-dependency (file 2): this should be grey too\n  </p>\n  <p class=\"dir-dep-3\">\n    PostCSS dir-dependency (file 3): this should be grey too\n  </p>\n\n  <p class=\"css-js-dep\">\n    import dependency includes 'import \"./foo.css\"': this should be green\n  </p>\n  <p class=\"css-js-dep-module\">\n    import dependency includes 'import \"./bar.module.css\"': this should be green\n  </p>\n\n  <p class=\"url-separated\">\n    URL separation preservation: should have valid background-image\n  </p>\n\n  <p class=\"inlined\">Inlined import - this should NOT be red.</p>\n\n  <div class=\"css-in-less\">\n    test import css in less, this color will be yellow\n  </div>\n  <div class=\"css-in-less-2\">\n    test for import less in less, this color will be blue\n  </div>\n\n  <div class=\"css-in-scss\">\n    test import css in scss, this color will be orange\n  </div>\n\n  <pre class=\"inlined-code\"></pre>\n\n  <p class=\"url-imported-css\">URL Support</p>\n\n  <p>Raw Support</p>\n  <pre class=\"raw-imported-css\"></pre>\n\n  <p>PostCSS source.input.from. Should include query</p>\n  <pre class=\"postcss-source-input\"></pre>\n\n  <p>Import from jsfile.css.js without the extension</p>\n  <pre class=\"jsfile-css-js\"></pre>\n\n  <p>Aliased</p>\n  <p class=\"aliased\">import '#alias': this should be blue</p>\n  <pre class=\"aliased-content\"></pre>\n  <p class=\"aliased-module\">import '#alias-module': this should be blue</p>\n\n  <p>Imports field</p>\n  <p class=\"imports-field\">import '#imports': this should be red</p>\n</div>\n<style>\n  @import url(./imported.scss);\n</style>\n<div class=\"at-import-scss\">@import scss: this should be red</div>\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/css/inline.module.css",
    "content": ".apply-color-inline {\n  color: turquoise;\n}\n"
  },
  {
    "path": "playground/css/inlined.css",
    "content": ".inlined {\n  color: green;\n  background: url('./ok.png');\n}\n"
  },
  {
    "path": "playground/css/jsfile.css.js",
    "content": "const message = 'from jsfile.css.js'\nexport default message\n"
  },
  {
    "path": "playground/css/layered/blue.css",
    "content": "@media screen {\n  .layers-blue {\n    color: blue;\n  }\n}\n"
  },
  {
    "path": "playground/css/layered/green.css",
    "content": "@media screen {\n  .layers-green {\n    color: green;\n  }\n}\n"
  },
  {
    "path": "playground/css/layered/index.css",
    "content": "@layer base;\n\n@import './blue.css' layer;\n@import './green.css' layer;\n\n@layer base {\n  .layers-blue {\n    color: black;\n  }\n  .layers-green {\n    color: black;\n  }\n}\n"
  },
  {
    "path": "playground/css/less/components/form.less",
    "content": "@import url('../../less/ommer.less');\n\n.form-box-data-uri {\n  // data-uri() calls with relative paths should be replaced just like urls.\n  background-image: data-uri('../images/backgrounds/form-select.svg');\n}\n"
  },
  {
    "path": "playground/css/less/ommer.less",
    "content": ".less-at-import-url-ommer {\n  color: darkorange;\n}\n"
  },
  {
    "path": "playground/css/less-plugin/test.js",
    "content": "functions.add('test', function test() {\n  const transparentPng =\n    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdjYGD4/x8AAwIB/8myre4AAAAASUVORK5CYII='\n  return `url(${transparentPng})`\n})\n"
  },
  {
    "path": "playground/css/less-plugin.less",
    "content": "@plugin \"less-plugin/test.js\";\n\n.less-js-plugin {\n  height: 1em;\n  width: 1em;\n  background-image: test();\n}\n"
  },
  {
    "path": "playground/css/less.less",
    "content": "@import '=/nested/nested';\n@import './nested/css-in-less.less';\n\n// Test data-uri calls with relative images.\n@import './less/components/form.less';\n\n@color: blue;\n\n.less {\n  color: @color;\n}\n"
  },
  {
    "path": "playground/css/lightningcss-plugins.js",
    "content": "import path from 'node:path'\nimport { normalizePath } from 'vite'\nimport { bundle as bundleWithLightningCss } from 'lightningcss'\nimport { globSync } from 'tinyglobby'\n\n/**\n * @param {string} filename\n * @returns {import('lightningcss').StyleSheet}\n *\n * based on https://github.com/sardinedev/lightningcss-plugins/blob/9fb379486e402a4b4b8950d09e655b4cbf8a118b/packages/global-custom-queries/src/globalCustomQueries.ts#L9-L29\n * https://github.com/sardinedev/lightningcss-plugins/blob/main/LICENSE\n */\nfunction obtainLightningCssAst(filename) {\n  let ast\n  try {\n    bundleWithLightningCss({\n      filename,\n      visitor: {\n        StyleSheet(stylesheet) {\n          ast = stylesheet\n        },\n      },\n    })\n    return ast\n  } catch (error) {\n    throw Error(`failed to obtain lightning css AST`, { cause: error })\n  }\n}\n\n/** @returns {import('lightningcss').Visitor} */\nexport function testDirDep() {\n  /** @type {string[]} */\n  let currentStyleSheetSources\n  return {\n    StyleSheet(stylesheet) {\n      currentStyleSheetSources = stylesheet.sources\n    },\n    Rule: {\n      unknown: {\n        test(rule) {\n          const location = rule.loc\n          const from = currentStyleSheetSources[location.source_index]\n          const pattern = normalizePath(\n            path.resolve(path.dirname(from), './glob-dep/**/*.css'),\n          )\n          // FIXME: there's no way to add a dependency\n          const files = globSync(pattern, {\n            expandDirectories: false,\n            absolute: true,\n          })\n          return files.flatMap((file) => obtainLightningCssAst(file).rules)\n        },\n      },\n    },\n  }\n}\n\n/** @returns {import('lightningcss').Visitor} */\nexport function testSourceInput() {\n  /** @type {string[]} */\n  let currentStyleSheetSources\n  return {\n    StyleSheet(stylesheet) {\n      currentStyleSheetSources = stylesheet.sources\n    },\n    Rule: {\n      unknown: {\n        'source-input': (rule) => {\n          const location = rule.loc\n          const from = currentStyleSheetSources[location.source_index]\n          return [\n            {\n              type: 'style',\n              value: {\n                // .source-input::before\n                selectors: [\n                  [\n                    { type: 'class', name: 'source-input' },\n                    { type: 'pseudo-element', kind: 'before' },\n                  ],\n                ],\n                // content: ${JSON.stringify(from)};\n                declarations: {\n                  declarations: [\n                    {\n                      property: 'custom',\n                      value:\n                        /** @satisfies {import('lightningcss').CustomProperty} */ ({\n                          name: 'content',\n                          value: [\n                            {\n                              type: 'token',\n                              value: { type: 'string', value: from },\n                            },\n                          ],\n                        }),\n                    },\n                  ],\n                },\n                loc: rule.loc,\n              },\n            },\n          ]\n        },\n      },\n    },\n  }\n}\n\n/**\n * really simplified implementation of https://github.com/postcss/postcss-nested\n *\n * @returns {import('lightningcss').Visitor}\n */\nexport function nestedLikePlugin() {\n  return {\n    Rule: {\n      style(rule) {\n        // NOTE: multiple selectors are not supported\n        if (rule.value.selectors.length > 1) {\n          return\n        }\n        const parentSelector = rule.value.selectors[0]\n\n        const nestedRules = rule.value.rules\n        /** @type {import('lightningcss').Rule[]} */\n        const additionalRules = []\n        if (nestedRules) {\n          const filteredNestedRules = []\n          for (const nestedRule of nestedRules) {\n            if (nestedRule.type === 'style') {\n              const selectors = nestedRule.value.selectors\n              // NOTE: multiple selectors are not supported\n              if (selectors.length === 1) {\n                const selector = selectors[0]\n                if (\n                  selector.length >= 2 &&\n                  selector[0].type === 'nesting' &&\n                  selector[1].type === 'type'\n                ) {\n                  const lastParentSelectorComponent =\n                    parentSelector[parentSelector.length - 1]\n                  if ('name' in lastParentSelectorComponent) {\n                    const newSelector = [\n                      ...parentSelector.slice(0, -1),\n                      {\n                        ...lastParentSelectorComponent,\n                        name:\n                          lastParentSelectorComponent.name + selector[1].name,\n                      },\n                    ]\n                    additionalRules.push({\n                      type: 'style',\n                      value: {\n                        selectors: [newSelector],\n                        declarations: nestedRule.value.declarations,\n                        loc: nestedRule.value.loc,\n                      },\n                    })\n                    continue\n                  }\n                }\n              }\n            }\n            filteredNestedRules.push(nestedRule)\n          }\n          rule.value.rules = filteredNestedRules\n        }\n        return [rule, ...additionalRules]\n      },\n    },\n  }\n}\n\n/** @returns {import('lightningcss').Visitor} */\nexport function testInjectUrl() {\n  return {\n    Rule: {\n      unknown: {\n        'inject-url': (rule) => {\n          return [\n            {\n              type: 'style',\n              value: {\n                selectors: [[{ type: 'class', name: 'inject-url' }]],\n                declarations: {\n                  declarations: [\n                    {\n                      property: 'background-image',\n                      value: [\n                        {\n                          type: 'url',\n                          value: {\n                            url: '=/ok.png',\n                            loc: rule.loc,\n                          },\n                        },\n                      ],\n                    },\n                  ],\n                },\n                loc: rule.loc,\n              },\n            },\n          ]\n        },\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "playground/css/linked-at-import.css",
    "content": ".linked-at-import {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/linked.css",
    "content": "@import '=/linked-at-import.css';\n\n/* test postcss nesting */\n.wrapper {\n  .linked {\n    color: blue;\n  }\n}\n"
  },
  {
    "path": "playground/css/main.js",
    "content": "import './minify.css'\nimport './imported.css'\nimport './sugarss.sss'\nimport './sass.scss'\nimport './less.less'\nimport './less-plugin.less'\nimport './stylus.styl'\nimport './manual-chunk.css'\nimport './postcss-inject-url.css'\n\nimport urlCss from './url-imported.css?url'\nappendLinkStylesheet(urlCss)\n\nimport rawCss from './raw-imported.css?raw'\ntext('.raw-imported-css', rawCss)\n\nimport { cUsed, a as treeshakeScopedA } from './treeshake-scoped/index.js'\ndocument.querySelector('.scoped').classList.add(treeshakeScopedA(), cUsed())\n\nimport mod from './mod.module.css'\ndocument.querySelector('.modules').classList.add(mod['apply-color'])\ntext('.modules-code', JSON.stringify(mod, null, 2))\n\nimport sassMod from './mod.module.scss'\ndocument.querySelector('.modules-sass').classList.add(sassMod['apply-color'])\ntext('.modules-sass-code', JSON.stringify(sassMod, null, 2))\n\nimport { a as treeshakeMod } from './treeshake-module/index.js'\ndocument\n  .querySelector('.modules-treeshake')\n  .classList.add(treeshakeMod()['treeshake-module-a'])\n\nimport composesPathResolvingMod from './composes-path-resolving.module.css'\ndocument\n  .querySelector('.path-resolved-modules-css')\n  .classList.add(...composesPathResolvingMod['path-resolving-css'].split(' '))\ndocument\n  .querySelector('.path-resolved-modules-sass')\n  .classList.add(...composesPathResolvingMod['path-resolving-sass'].split(' '))\ndocument\n  .querySelector('.path-resolved-modules-less')\n  .classList.add(...composesPathResolvingMod['path-resolving-less'].split(' '))\ntext(\n  '.path-resolved-modules-code',\n  JSON.stringify(composesPathResolvingMod, null, 2),\n)\n\nimport inlineMod from './inline.module.css?inline'\ntext('.modules-inline', inlineMod)\n\nimport charset from './charset.css?inline'\ntext('.charset-css', charset)\n\nimport './layered/index.css'\n\nimport './dep.css'\nimport './glob-dep.css'\n\n// eslint-disable-next-line import-x/order\nimport { barModuleClasses } from '@vitejs/test-css-js-dep'\ndocument\n  .querySelector('.css-js-dep-module')\n  .classList.add(barModuleClasses.cssJsDepModule)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nfunction appendLinkStylesheet(href) {\n  const link = document.createElement('link')\n  link.rel = 'stylesheet'\n  link.href = href\n  document.head.appendChild(link)\n}\n\nif (import.meta.hot) {\n  import.meta.hot.accept('./mod.module.css', (newMod) => {\n    const list = document.querySelector('.modules').classList\n    list.remove(mod.applyColor)\n    list.add(newMod.applyColor)\n    text('.modules-code', JSON.stringify(newMod.default, null, 2))\n  })\n\n  import.meta.hot.accept('./mod.module.scss', (newMod) => {\n    const list = document.querySelector('.modules-sass').classList\n    list.remove(mod.applyColor)\n    list.add(newMod.applyColor)\n    text('.modules-sass-code', JSON.stringify(newMod.default, null, 2))\n  })\n}\n\n// async\nimport('./async')\n\nif (import.meta.env.DEV) {\n  import('./async-treeshaken')\n}\n\n// inlined\nimport inlined from './inlined.css?inline'\ntext('.inlined-code', inlined)\n\n// glob\nconst glob = import.meta.glob('./glob-import/*.css', { query: '?inline' })\nPromise.all(\n  Object.keys(glob).map((key) => glob[key]().then((i) => i.default)),\n).then((res) => {\n  text('.imported-css-glob', JSON.stringify(res, null, 2))\n})\n\n// globEager\nconst globEager = import.meta.glob('./glob-import/*.css', {\n  eager: true,\n  query: '?inline',\n})\ntext('.imported-css-globEager', JSON.stringify(globEager, null, 2))\n\nimport postcssSourceInput from './postcss-source-input.css?inline&query=foo'\ntext('.postcss-source-input', postcssSourceInput)\n\n// The file is jsfile.css.js, and we should be able to import it without extension\nimport jsFileMessage from './jsfile.css'\ntext('.jsfile-css-js', jsFileMessage)\n\nimport '#alias'\nimport aliasContent from '#alias?inline'\ntext('.aliased-content', aliasContent)\nimport aliasModule from '#alias-module'\ndocument\n  .querySelector('.aliased-module')\n  .classList.add(aliasModule.aliasedModule)\n\nimport './unsupported.css'\n\nimport './async/index'\n\nimport('./same-name/sub1/sub')\nimport('./same-name/sub2/sub')\n\nimport './imports-imports-field.css'\n"
  },
  {
    "path": "playground/css/manual-chunk.css",
    "content": ".manual-chunk {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/minify.css",
    "content": ".test-minify {\n  color: rgba(255, 255, 0, 0.7);\n}\n"
  },
  {
    "path": "playground/css/mod.module.css",
    "content": ".apply-color {\n  color: turquoise;\n}\n"
  },
  {
    "path": "playground/css/mod.module.scss",
    "content": ".apply-color {\n  color: orangered;\n}\n"
  },
  {
    "path": "playground/css/nested/_index.scss",
    "content": "@use 'sass:string';\n@use '/nested/root-relative'; // root relative path\n@use '../weapp.wxss'; // test user's custom importer in a file loaded by vite's custom importer\n\n@import './css-in-scss.css';\n\n.sass-at-import {\n  color: olive;\n  background: url(./icon.png) 10px no-repeat;\n}\n\n.sass-at-import-alias {\n  color: olive;\n  background: url(=/nested/icon.png) 10px no-repeat;\n}\n\n$var: '/ok.png';\n.sass-url-starts-with-variable {\n  background: url($var);\n  background-position: center;\n}\n\n.sass-url-starts-with-interpolation1 {\n  background: url(#{$var});\n  background-position: center;\n}\n\n.sass-url-starts-with-interpolation2 {\n  background: url('#{$var}');\n  background-position: center;\n}\n\n$var-c1: '/ok';\n$var-c2: '.png';\n.sass-url-starts-with-variable-concat {\n  background: url($var-c1 + $var-c2);\n  background-position: center;\n}\n\n$var2: '/OK.PNG';\n.sass-url-starts-with-function-call {\n  background: url(string.to-lower-case($var2));\n  background-position: center;\n}\n"
  },
  {
    "path": "playground/css/nested/_partial.scss",
    "content": ".sass-partial {\n  color: orchid;\n}\n"
  },
  {
    "path": "playground/css/nested/css-in-less-2.less",
    "content": ".css-in-less-2 {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/nested/css-in-less.css",
    "content": ".css-in-less {\n  color: yellow;\n}\n"
  },
  {
    "path": "playground/css/nested/css-in-less.less",
    "content": "@import url('./css-in-less.css');\n@import './css-in-less.css';\n\n@import './css-in-less-2.less';\n"
  },
  {
    "path": "playground/css/nested/css-in-scss.css",
    "content": ".css-in-scss {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/nested/nested.less",
    "content": ".less-at-import {\n  color: darkslateblue;\n  background: url(./icon.png) 10px no-repeat;\n}\n\n.less-at-import-alias {\n  color: darkslateblue;\n  background: url(=/nested/icon.png) 10px no-repeat;\n}\n\n@var: '/ok.png';\n.less-url-starts-with-variable {\n  background: url(@var);\n  background-position: center;\n}\n\n.less-url-starts-with-interpolation {\n  background: url('@{var}');\n  background-position: center;\n}\n"
  },
  {
    "path": "playground/css/nested/nested.sss",
    "content": ".sugarss-at-import\n  color: darkslateblue\n  background: url(./icon.png) 10px no-repeat\n\n\n.sugarss-at-import-alias\n  color: darkslateblue\n  background: url(=/nested/icon.png) 10px no-repeat\n"
  },
  {
    "path": "playground/css/nested/nested.styl",
    "content": ".stylus-import\n  color darkslateblue\n\n.stylus-import-alias\n  color darkslateblue\n  background url('=/nested/icon.png') 10px no-repeat\n"
  },
  {
    "path": "playground/css/nested/relative.scss",
    "content": ".sass-at-import-relative {\n  color: olive;\n  background: url(./icon.png) 10px no-repeat;\n}\n"
  },
  {
    "path": "playground/css/nested/replacement-alias.scss",
    "content": ".sass-at-import-replacement-alias {\n  color: olive;\n}\n"
  },
  {
    "path": "playground/css/nested/root-relative.scss",
    "content": ".sass-root-relative {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/options/absolute-import.styl",
    "content": ".stylus-options-absolute-import\n  /* imported via vite.config.js */\n  color red\n"
  },
  {
    "path": "playground/css/options/relative-import.styl",
    "content": ".stylus-options-relative-import\n  /* imported via vite.config.js */\n  color green\n"
  },
  {
    "path": "playground/css/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\",\n    \"dev:relative-base\": \"vite --config ./vite.config-relative-base.js dev\",\n    \"build:relative-base\": \"vite --config ./vite.config-relative-base.js build\",\n    \"preview:relative-base\": \"vite --config ./vite.config-relative-base.js preview\",\n    \"dev:no-css-minify\": \"vite --config ./vite.config-no-css-minify.js dev\",\n    \"build:no-css-minify\": \"vite --config ./vite.config-no-css-minify.js build\",\n    \"preview:no-css-minify\": \"vite --config ./vite.config-no-css-minify.js preview\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/test-css-dep\": \"link:./css-dep\",\n    \"@vitejs/test-css-dep-exports\": \"link:./css-dep-exports\",\n    \"@vitejs/test-css-js-dep\": \"file:./css-js-dep\",\n    \"@vitejs/test-css-proxy-dep\": \"file:./css-proxy-dep\",\n    \"@vitejs/test-scss-proxy-dep\": \"file:./scss-proxy-dep\",\n    \"less\": \"^4.6.4\",\n    \"lightningcss\": \"^1.32.0\",\n    \"postcss-nested\": \"^7.0.2\",\n    \"sass\": \"^1.98.0\",\n    \"stylus\": \"^0.64.0\",\n    \"sugarss\": \"^5.0.1\",\n    \"tinyglobby\": \"^0.2.15\"\n  },\n  \"imports\": {\n    \"#imports\": \"./imports-field.css\"\n  }\n}\n"
  },
  {
    "path": "playground/css/pkg-dep/_index.scss",
    "content": ".sass-dep {\n  color: lavender;\n}\n"
  },
  {
    "path": "playground/css/pkg-dep/index.js",
    "content": ""
  },
  {
    "path": "playground/css/pkg-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-pkg-dep\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/blue-app/imported.css",
    "content": ".postcss-a {\n  color: pink;\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/blue-app/index.html",
    "content": "<div class=\"wrapper\">\n  <h1>CSS</h1>\n\n  <p>Imported css string:</p>\n  <pre class=\"imported-css\"></pre>\n\n  <p class=\"postcss-a\">This should be blue</p>\n\n  <p class=\"postcss-b\">This should be black</p>\n</div>\n\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/css/postcss-caching/blue-app/main.js",
    "content": "import './imported.css'\nimport css from './imported.css?inline'\ntext('.imported-css', css)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/blue-app/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-blue-app\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/blue-app/postcss.config.js",
    "content": "export default {\n  plugins: [replacePinkWithBlue],\n}\n\nfunction replacePinkWithBlue() {\n  return {\n    postcssPlugin: 'replace-pink-with-blue',\n    Declaration(decl) {\n      if (decl.value === 'pink') {\n        decl.value = 'blue'\n      }\n    },\n  }\n}\nreplacePinkWithBlue.postcss = true\n"
  },
  {
    "path": "playground/css/postcss-caching/css.spec.ts",
    "content": "import path from 'node:path'\nimport { createServer } from 'vite'\nimport { expect, test } from 'vitest'\nimport { getColor, isServe, page, ports } from '~utils'\n\ntest.runIf(isServe)('postcss config', async () => {\n  const port = ports['css/postcss-caching']\n  const startServer = async (root) => {\n    const server = await createServer({\n      root,\n      logLevel: 'silent',\n      server: {\n        port,\n        strictPort: true,\n      },\n      build: {\n        // skip transpilation during tests to make it faster\n        target: 'esnext',\n      },\n    })\n    await server.listen()\n    return server\n  }\n\n  const blueAppDir = path.join(import.meta.dirname, 'blue-app')\n  const greenAppDir = path.join(import.meta.dirname, 'green-app')\n  let blueApp\n  let greenApp\n  try {\n    const hmrConnectionPromise = page.waitForEvent('console', (msg) =>\n      msg.text().includes('connected'),\n    )\n\n    blueApp = await startServer(blueAppDir)\n\n    await page.goto(`http://localhost:${port}`, { waitUntil: 'load' })\n    const blueA = await page.$('.postcss-a')\n    expect(await getColor(blueA)).toBe('blue')\n    const blueB = await page.$('.postcss-b')\n    expect(await getColor(blueB)).toBe('black')\n\n    // wait for hmr connection because: if server stops before connection, auto reload does not happen\n    await hmrConnectionPromise\n    await blueApp.close()\n    blueApp = null\n\n    const loadPromise = page.waitForEvent('load') // wait for server restart auto reload\n    greenApp = await startServer(greenAppDir)\n    await loadPromise\n\n    const greenA = await page.$('.postcss-a')\n    expect(await getColor(greenA)).toBe('black')\n    const greenB = await page.$('.postcss-b')\n    expect(await getColor(greenB)).toBe('green')\n    await greenApp.close()\n    greenApp = null\n  } finally {\n    if (blueApp) {\n      await blueApp.close()\n    }\n    if (greenApp) {\n      await greenApp.close()\n    }\n  }\n})\n"
  },
  {
    "path": "playground/css/postcss-caching/green-app/imported.css",
    "content": ".postcss-b {\n  color: pink;\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/green-app/index.html",
    "content": "<div class=\"wrapper\">\n  <h1>CSS</h1>\n\n  <p>Imported css string:</p>\n  <pre class=\"imported-css\"></pre>\n\n  <p class=\"postcss-a\">This should be black</p>\n\n  <p class=\"postcss-b\">This should be green</p>\n</div>\n\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/css/postcss-caching/green-app/main.js",
    "content": "import './imported.css'\nimport css from './imported.css?inline'\ntext('.imported-css', css)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/green-app/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-green-app\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/css/postcss-caching/green-app/postcss.config.js",
    "content": "export default {\n  plugins: [replacePinkWithGreen],\n}\n\nfunction replacePinkWithGreen() {\n  return {\n    postcssPlugin: 'replace-pink-with-green',\n    Declaration(decl) {\n      if (decl.value === 'pink') {\n        decl.value = 'green'\n      }\n    },\n  }\n}\nreplacePinkWithGreen.postcss = true\n"
  },
  {
    "path": "playground/css/postcss-caching/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\n// The server is started in the test, so we need to have a custom serve\n// function or a default server will be created\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  return {\n    close: () => Promise.resolve(),\n  }\n}\n"
  },
  {
    "path": "playground/css/postcss-inject-url.css",
    "content": "@inject-url;\n"
  },
  {
    "path": "playground/css/postcss-source-input.css",
    "content": "@source-input;\n"
  },
  {
    "path": "playground/css/postcss.config.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { globSync } from 'tinyglobby'\nimport { normalizePath } from 'vite'\nimport postcssNested from 'postcss-nested'\n\nexport default {\n  plugins: [postcssNested, testDirDep, testSourceInput, testInjectUrl],\n}\n\n/**\n * A plugin for testing the `dir-dependency` message handling.\n */\nfunction testDirDep() {\n  return {\n    postcssPlugin: 'dir-dep',\n    AtRule(atRule, { result, Comment }) {\n      if (atRule.name === 'test') {\n        const pattern = normalizePath(\n          path.resolve(path.dirname(result.opts.from), './glob-dep/**/*.css'),\n        )\n        const files = globSync(pattern, { expandDirectories: false })\n        const text = files.map((f) => fs.readFileSync(f, 'utf-8')).join('\\n')\n        atRule.parent.insertAfter(atRule, text)\n        atRule.remove()\n\n        result.messages.push({\n          type: 'dir-dependency',\n          plugin: 'dir-dep',\n          dir: './glob-dep',\n          glob: '*.css',\n          parent: result.opts.from,\n        })\n\n        result.messages.push({\n          type: 'dir-dependency',\n          plugin: 'dir-dep',\n          dir: './glob-dep/nested (dir)', // includes special characters in glob\n          glob: '*.css',\n          parent: result.opts.from,\n        })\n      }\n    },\n  }\n}\ntestDirDep.postcss = true\n\nfunction testSourceInput() {\n  return {\n    postcssPlugin: 'source-input',\n    AtRule(atRule) {\n      if (atRule.name === 'source-input') {\n        atRule.after(\n          `.source-input::before { content: ${JSON.stringify(\n            atRule.source.input.from,\n          )}; }`,\n        )\n        atRule.remove()\n      }\n    },\n  }\n}\ntestSourceInput.postcss = true\n\nfunction testInjectUrl() {\n  return {\n    postcssPlugin: 'inject-url',\n    Once(root, { Rule }) {\n      root.walkAtRules('inject-url', (atRule) => {\n        const rule = new Rule({\n          selector: '.inject-url',\n          source: atRule.source,\n        })\n        rule.append({\n          prop: 'background',\n          value: \"url('=/ok.png')\",\n          source: atRule.source,\n        })\n        atRule.after(rule)\n        atRule.remove()\n      })\n    },\n  }\n}\ntestInjectUrl.postcss = true\n"
  },
  {
    "path": "playground/css/raw-imported.css",
    "content": ".raw {\n  /* should not be transformed by postcss */\n  &-imported {\n    color: yellow;\n  }\n}\n"
  },
  {
    "path": "playground/css/same-name/sub1/sub.css",
    "content": ".sub1-sub {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/same-name/sub1/sub.js",
    "content": "import './sub.css'\n\nexport default 'sub1-name'\n"
  },
  {
    "path": "playground/css/same-name/sub2/sub.css",
    "content": ".sub2-sub {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/same-name/sub2/sub.js",
    "content": "import './sub.css'\n\nexport default 'sub2-name'\n"
  },
  {
    "path": "playground/css/sass-modern-compiler-build/entry1.scss",
    "content": ".entry1 {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/sass-modern-compiler-build/entry2.scss",
    "content": ".entry2 {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/sass.scss",
    "content": "@use '=/nested'; // alias + custom index resolving -> /nested/_index.scss\n@use '=/nested/partial'; // sass convention: omitting leading _ for partials\n@use './nested/relative'; // relative path\n@use '@vitejs/test-css-dep'; // package w/ sass entry points\n@use '@vitejs/test-css-dep-exports'; // package with a sass export mapping\n@use '@vitejs/test-css-dep-exports/foo.scss'; // package with a sass export mapping (deep)\n@use '@vitejs/test-scss-proxy-dep'; // package with a sass proxy import\n@use 'virtual-dep'; // virtual file added through importer\n@use '=/pkg-dep'; // package w/out sass field\n@use '=/weapp.wxss'; // wxss file\n@use 'virtual-file-absolute';\n@use '=/scss-dir/main.scss'; // \"./dir\" reference from vite custom importer\n@use '=replace/nested/replacement-alias.scss';\n\n.sass {\n  /* injected via vite.config.js */\n  color: $injectedColor;\n}\n"
  },
  {
    "path": "playground/css/scss-dir/dir/index.scss",
    "content": ".sass-dir-index {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/css/scss-dir/main.scss",
    "content": "@use './dir';\n"
  },
  {
    "path": "playground/css/scss-proxy-dep/index.scss",
    "content": "@use '@vitejs/test-scss-proxy-dep-nested/index.css';\n"
  },
  {
    "path": "playground/css/scss-proxy-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-scss-proxy-dep\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"sass\": \"index.scss\",\n  \"dependencies\": {\n    \"@vitejs/test-scss-proxy-dep-nested\": \"file:../scss-proxy-dep-nested\"\n  }\n}\n"
  },
  {
    "path": "playground/css/scss-proxy-dep-nested/index.css",
    "content": ".scss-proxy-dep {\n  color: purple;\n}\n"
  },
  {
    "path": "playground/css/scss-proxy-dep-nested/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-scss-proxy-dep-nested\",\n  \"private\": true,\n  \"version\": \"1.0.0\"\n}\n"
  },
  {
    "path": "playground/css/stylus.styl",
    "content": "@import './nested/nested'\n\n$color ?= blue\n\n.stylus\n  color $color\n\n.stylus-additional-data\n  /* injected via vite.config.js */\n  color $injectedColor\n\n.stylus-options-define-var\n  /* defined in vite.config.js */\n  color $definedColor\n\n.stylus-options-define-func\n  /* defined in vite.config.js */\n  color definedFunction()\n"
  },
  {
    "path": "playground/css/sugarss.sss",
    "content": "@import '=/nested/nested.sss'\n\n.sugarss\n  color: blue\n"
  },
  {
    "path": "playground/css/treeshake-module/a.js",
    "content": "import style from './a.module.css'\n\nexport function a() {\n  return style\n}\n"
  },
  {
    "path": "playground/css/treeshake-module/a.module.css",
    "content": ".treeshake-module-a {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-module/b.js",
    "content": "import style from './b.module.css'\n\nexport function b() {\n  return style\n}\n"
  },
  {
    "path": "playground/css/treeshake-module/b.module.css",
    "content": ".treeshake-module-b {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-module/index.js",
    "content": "export { a } from './a.js'\nexport { b } from './b.js'\n"
  },
  {
    "path": "playground/css/treeshake-scoped/a-scoped.css",
    "content": ".treeshake-scoped-a {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/a.js",
    "content": "import './a-scoped.css' // should be treeshaken away if `a` is not used\n\nexport default function a() {\n  return 'treeshake-scoped-a'\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/b-scoped.css",
    "content": ".treeshake-scoped-b {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/b.js",
    "content": "import './b-scoped.css' // should be treeshaken away if `b` is not used\n\nexport default function b() {\n  return 'treeshake-scoped-b'\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/c-scoped.css",
    "content": ".treeshake-scoped-c {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/c.js",
    "content": "import './c-scoped.css' // should be treeshaken away if `b` is not used\n\nexport default function c() {\n  return 'treeshake-scoped-c'\n}\n\nexport function cUsed() {\n  // used but does not depend on scoped css\n  return 'c-used'\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/d-scoped.css",
    "content": ".treeshake-scoped-d {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/d.js",
    "content": "import './d-scoped.css' // should be treeshaken away if `d` is not used\n\nexport default function d() {\n  return 'treeshake-scoped-d'\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/index.html",
    "content": "<h1>treeshake-scoped</h1>\n<p class=\"scoped-index\">Imported scoped CSS</p>\n<p class=\"treeshake-scoped-order\">\n  scoped CSS order (this should be red text with blue background)\n</p>\n\n<script type=\"module\">\n  import { d } from './index.js'\n  import order from './order/a.js'\n  document.querySelector('.scoped-index').classList.add(d())\n  document.querySelector('.treeshake-scoped-order').classList.add(order())\n</script>\n"
  },
  {
    "path": "playground/css/treeshake-scoped/index.js",
    "content": "export { default as a } from './a.js'\nexport { default as b } from './b.js'\nexport { default as c, cUsed } from './c.js'\nexport { default as d } from './d.js'\n"
  },
  {
    "path": "playground/css/treeshake-scoped/order/a-scoped.css",
    "content": ".treeshake-scoped-order {\n  color: red;\n  background: red;\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/order/a.js",
    "content": "import './before.css'\nimport './a-scoped.css'\nimport './after.css'\n\nexport default function a() {\n  return 'treeshake-scoped-order-a'\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/order/after.css",
    "content": ".treeshake-scoped-order {\n  color: red;\n  background: blue;\n}\n"
  },
  {
    "path": "playground/css/treeshake-scoped/order/before.css",
    "content": ".treeshake-scoped-order {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css/unsupported.css",
    "content": ".unsupported {\n  overflow-x: hidden;\n}\n"
  },
  {
    "path": "playground/css/url-imported.css",
    "content": ".url {\n  /* should be transformed by postcss */\n  &-imported-css {\n    color: yellow;\n  }\n}\n"
  },
  {
    "path": "playground/css/vite.config-lightningcss.js",
    "content": "import { defineConfig } from 'vite'\nimport { composeVisitors } from 'lightningcss'\nimport baseConfig from './vite.config.js'\nimport {\n  nestedLikePlugin,\n  testDirDep,\n  testInjectUrl,\n  testSourceInput,\n} from './lightningcss-plugins'\n\nexport default defineConfig({\n  ...baseConfig,\n  css: {\n    ...baseConfig.css,\n    transformer: 'lightningcss',\n    lightningcss: {\n      cssModules: {\n        pattern: '[name]__[local]___[hash]',\n      },\n      visitor: composeVisitors([\n        nestedLikePlugin(),\n        testDirDep(),\n        testSourceInput(),\n        testInjectUrl(),\n      ]),\n    },\n  },\n  cacheDir: 'node_modules/.vite-no-css-minify',\n})\n"
  },
  {
    "path": "playground/css/vite.config-no-css-minify.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nexport default defineConfig({\n  ...baseConfig,\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/no-css-minify',\n    minify: true,\n    cssMinify: false,\n  },\n  cacheDir: 'node_modules/.vite-no-css-minify',\n})\n"
  },
  {
    "path": "playground/css/vite.config-relative-base.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nexport default defineConfig(({ isPreview }) => ({\n  ...baseConfig,\n  base: !isPreview ? './' : '/relative-base/', // relative base to make dist portable\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/relative-base',\n    watch: null,\n    minify: false,\n    assetsInlineLimit: 0,\n    rollupOptions: {\n      output: {\n        entryFileNames: 'entries/[name].js',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        assetFileNames: 'other-assets/[name]-[hash][extname]',\n      },\n    },\n  },\n  cacheDir: 'node_modules/.vite-relative-base',\n}))\n"
  },
  {
    "path": "playground/css/vite.config-same-file-name.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nexport default defineConfig({\n  ...baseConfig,\n  build: {\n    ...baseConfig.build,\n    outDir: 'dist/same-file-name',\n    rollupOptions: {\n      output: {\n        entryFileNames: '[name].js',\n        chunkFileNames: '[name].[hash].js',\n        assetFileNames: '[name].[ext]',\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/css/vite.config-sass-modern-compiler-build.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    outDir: 'dist/sass-modern-compiler-build',\n    rollupOptions: {\n      input: {\n        entry1: path.join(\n          import.meta.dirname,\n          'sass-modern-compiler-build/entry1.scss',\n        ),\n        entry2: path.join(\n          import.meta.dirname,\n          'sass-modern-compiler-build/entry2.scss',\n        ),\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/css/vite.config.js",
    "content": "import path from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport stylus from 'stylus'\nimport { defineConfig } from 'vite'\n\n// trigger scss bug: https://github.com/sass/dart-sass/issues/710\n// make sure Vite handles safely\n// @ts-expect-error refer to https://github.com/vitejs/vite/pull/11079\nglobalThis.window = {}\n// @ts-expect-error refer to https://github.com/vitejs/vite/pull/11079\nglobalThis.location = new URL('http://localhost/')\n\nconst dirname = import.meta.dirname\n\nexport default defineConfig({\n  plugins: [\n    {\n      // Emulate a UI framework component where a framework module would import\n      // scoped CSS files that should treeshake if the default export is not used.\n      name: 'treeshake-scoped-css',\n      enforce: 'pre',\n      async resolveId(id, importer) {\n        if (!importer || !id.endsWith('-scoped.css')) return\n\n        const resolved = await this.resolve(id, importer)\n        if (!resolved) return\n\n        return {\n          ...resolved,\n          meta: {\n            vite: {\n              cssScopeTo: [\n                importer,\n                resolved.id.includes('barrel') ? undefined : 'default',\n              ],\n            },\n          },\n        }\n      },\n    },\n  ],\n  build: {\n    cssTarget: 'chrome61',\n    rollupOptions: {\n      input: {\n        index: path.resolve(dirname, './index.html'),\n        treeshakeScoped: path.resolve(dirname, './treeshake-scoped/index.html'),\n        empty: path.resolve(dirname, './empty.css'),\n      },\n      output: {\n        manualChunks(id) {\n          if (id.includes('manual-chunk.css')) {\n            return 'dir/dir2/manual-chunk'\n          }\n        },\n      },\n    },\n  },\n  esbuild: {\n    logOverride: {\n      'unsupported-css-property': 'silent',\n    },\n  },\n  resolve: {\n    alias: [\n      { find: '=', replacement: dirname },\n      { find: /^=replace\\/(.*)/, replacement: `${dirname}/$1` },\n      { find: 'spacefolder', replacement: dirname + '/folder with space' },\n      { find: '#alias', replacement: dirname + '/aliased/foo.css' },\n      {\n        find: '#alias?inline',\n        replacement: dirname + '/aliased/foo.css?inline',\n      },\n      {\n        find: '#alias-module',\n        replacement: dirname + '/aliased/bar.module.css',\n      },\n    ],\n  },\n  css: {\n    modules: {\n      generateScopedName: '[name]__[local]___[hash:base64:5]',\n\n      // example of how getJSON can be used to generate\n      // typescript typings for css modules class names\n\n      // getJSON(cssFileName, json, _outputFileName) {\n      //   let typings = 'declare const classNames: {\\n'\n      //   for (let className in json) {\n      //     typings += `    \"${className}\": string;\\n`\n      //   }\n      //   typings += '};\\n'\n      //   typings += 'export default classNames;\\n'\n      //   const { join, dirname, basename } = require('path')\n      //   const typingsFile = join(\n      //     dirname(cssFileName),\n      //     basename(cssFileName) + '.d.ts'\n      //   )\n      //   require('fs').writeFileSync(typingsFile, typings)\n      // },\n    },\n    preprocessorOptions: {\n      scss: {\n        additionalData: `$injectedColor: orange;`,\n        importers: [\n          {\n            canonicalize(url) {\n              return url === 'virtual-dep' || url.endsWith('.wxss')\n                ? new URL('custom-importer:virtual-dep')\n                : null\n            },\n            load() {\n              return {\n                contents: ``,\n                syntax: 'scss',\n              }\n            },\n          },\n          {\n            canonicalize(url) {\n              return url === 'virtual-file-absolute'\n                ? new URL('custom-importer:virtual-file-absolute')\n                : null\n            },\n            load() {\n              return {\n                contents: `@use \"${pathToFileURL(path.join(import.meta.dirname, 'file-absolute.scss')).href}\"`,\n                syntax: 'scss',\n              }\n            },\n          },\n        ],\n      },\n      styl: {\n        additionalData: `$injectedColor ?= orange`,\n        imports: [\n          './options/relative-import.styl',\n          path.join(dirname, 'options/absolute-import.styl'),\n        ],\n        define: {\n          $definedColor: new stylus.nodes.RGBA(51, 197, 255, 1),\n          definedFunction: () => new stylus.nodes.RGBA(255, 0, 98, 1),\n        },\n      },\n    },\n    preprocessorMaxWorkers: true,\n  },\n})\n"
  },
  {
    "path": "playground/css/weapp.wxss",
    "content": "this is not css\n"
  },
  {
    "path": "playground/css-codesplit/__tests__/css-codesplit-consistent.spec.ts",
    "content": "import { beforeEach, describe, expect, test } from 'vitest'\nimport { findAssetFile, isBuild, startDefaultServe } from '~utils'\n\nbeforeEach(async () => {\n  await startDefaultServe()\n})\n\nfor (let i = 0; i < 5; i++) {\n  describe.runIf(isBuild)('css-codesplit build', () => {\n    test('should be consistent with same content', () => {\n      expect(findAssetFile(/style-.+\\.css/)).toBeUndefined()\n      expect(findAssetFile(/style2-.+\\.css/)).toMatch('h2{color:#00f}')\n    })\n  })\n}\n"
  },
  {
    "path": "playground/css-codesplit/__tests__/css-codesplit.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport {\n  findAssetFile,\n  getColor,\n  isBuild,\n  listAssets,\n  page,\n  readManifest,\n} from '~utils'\n\ntest('should load all stylesheets', async () => {\n  expect(await getColor('h1')).toBe('red')\n  expect(await getColor('h2')).toBe('blue')\n  expect(await getColor('.dynamic')).toBe('green')\n  expect(await getColor('.async-js')).toBe('blue')\n  expect(await getColor('.chunk')).toBe('magenta')\n})\n\ntest('should load dynamic import with inline', async () => {\n  const css = await page.textContent('.dynamic-inline')\n  expect(css).toMatch('.inline')\n\n  expect(await getColor('.inline')).not.toBe('yellow')\n})\n\ntest('should load dynamic import with module', async () => {\n  const css = await page.textContent('.dynamic-module')\n  expect(css).toMatch('_mod_')\n\n  expect(await getColor('.mod')).toBe('yellow')\n})\n\ntest('style order should be consistent when style tag is inserted by JS', async () => {\n  expect(await getColor('.order-bulk')).toBe('orange')\n  await page.click('.order-bulk-update')\n  await expect.poll(() => getColor('.order-bulk')).toBe('green')\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('should remove empty chunk', async () => {\n    expect(findAssetFile(/style-.*\\.js$/)).toBeUndefined()\n    expect(findAssetFile('main.*.js$')).toMatch(`/* empty css`)\n    expect(findAssetFile('other.*.js$')).toMatch(`/* empty css`)\n    expect(findAssetFile(/async-[-\\w]{8}\\.js$/)).toBeUndefined()\n\n    const assets = listAssets()\n    expect(assets).not.toContainEqual(\n      expect.stringMatching(/async-js-[-\\w]{8}\\.js$/),\n    )\n  })\n\n  test('should remove empty chunk, HTML without JS', async () => {\n    const sharedCSSWithJSChunk = findAssetFile('shared-css-with-js.*.js$')\n    expect(sharedCSSWithJSChunk).toMatch(`/* empty css`)\n    // there are functions and modules in the src code that should be tree-shaken\n    expect(sharedCSSWithJSChunk).not.toMatch('function')\n    expect(sharedCSSWithJSChunk).not.toMatch(/import(?!\\s*\".\\/modulepreload)/)\n  })\n\n  test('should generate correct manifest', async () => {\n    const manifest = readManifest()\n    expect(manifest['index.html'].css.length).toBe(2)\n    expect(manifest['other.js'].css.length).toBe(1)\n  })\n\n  test('should not mark a css chunk with ?url and normal import as pure css chunk', () => {\n    expect(findAssetFile(/chunk-.*\\.js$/)).toBeTruthy()\n  })\n})\n"
  },
  {
    "path": "playground/css-codesplit/async-js.css",
    "content": ".async-js {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-codesplit/async-js.js",
    "content": "// a JS file that becomes an empty file but imports CSS files\nimport './async-js.css'\n"
  },
  {
    "path": "playground/css-codesplit/async.css",
    "content": ".dynamic {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css-codesplit/chunk.css",
    "content": ".chunk {\n  color: magenta;\n}\n"
  },
  {
    "path": "playground/css-codesplit/index.html",
    "content": "<h1>This should be red</h1>\n<h2>This should be blue</h2>\n\n<p class=\"dynamic\">This should be green</p>\n<p class=\"async-js\">This should be blue</p>\n<p class=\"inline\">This should not be yellow</p>\n<p class=\"dynamic-inline\"></p>\n<p class=\"mod\">This should be yellow</p>\n<p class=\"dynamic-module\"></p>\n\n<p class=\"order-bulk\">\n  This should be orange\n  <button class=\"order-bulk-update\">change to green</button>\n</p>\n\n<p class=\"chunk\">This should be magenta</p>\n\n<script type=\"module\" src=\"/main.js\"></script>\n<div id=\"app\"></div>\n"
  },
  {
    "path": "playground/css-codesplit/inline.css",
    "content": ".inline {\n  color: yellow;\n}\n"
  },
  {
    "path": "playground/css-codesplit/main.css",
    "content": "h1 {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-codesplit/main.js",
    "content": "import './style.css'\nimport './main.css'\nimport './order'\n\nimport './chunk.css'\nimport chunkCssUrl from './chunk.css?url'\n\n// use this to not treeshake\nglobalThis.__test_chunkCssUrl = chunkCssUrl\n\nimport('./async.css')\nimport('./async-js')\n\nimport('./inline.css?inline').then((css) => {\n  document.querySelector('.dynamic-inline').textContent = css.default\n})\n\nimport('./mod.module.css').then((css) => {\n  document.querySelector('.dynamic-module').textContent = JSON.stringify(\n    css.default,\n  )\n  document.querySelector('.mod').classList.add(css.default.mod)\n})\n"
  },
  {
    "path": "playground/css-codesplit/mod.module.css",
    "content": ".mod {\n  color: yellow;\n}\n"
  },
  {
    "path": "playground/css-codesplit/order/base.css",
    "content": ".order-bulk {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-codesplit/order/dynamic.css",
    "content": ".order-bulk {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css-codesplit/order/index.js",
    "content": "import './insert' // inserts \"color: orange\"\nimport './base.css' // includes \"color: blue\"\n\ndocument.querySelector('.order-bulk-update').addEventListener('click', () => {\n  import('./dynamic.css') // includes \"color: green\"\n})\n"
  },
  {
    "path": "playground/css-codesplit/order/insert.js",
    "content": "const style = document.createElement('style')\nstyle.textContent = '.order-bulk { color: orange; }'\ndocument.head.appendChild(style)\n"
  },
  {
    "path": "playground/css-codesplit/other.js",
    "content": "import './style.css'\nimport './chunk.css'\nimport chunkCssUrl from './chunk.css?url'\n\n// use this to not treeshake\nglobalThis.__test_chunkCssUrl = chunkCssUrl\n"
  },
  {
    "path": "playground/css-codesplit/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-codesplit\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/css-codesplit/shared-css-empty-1.js",
    "content": "function shouldBeTreeshaken_1() {\n  // This function should be treeshaken, even if { moduleSideEffects: 'no-treeshake' }\n  // was used in the JS corresponding to the HTML entrypoint.\n}\n"
  },
  {
    "path": "playground/css-codesplit/shared-css-empty-2.js",
    "content": "export default function shouldBeTreeshaken_2() {\n  // This function should be treeshaken, even if { moduleSideEffects: 'no-treeshake' }\n  // was used in the JS corresponding to the HTML entrypoint.\n}\n"
  },
  {
    "path": "playground/css-codesplit/shared-css-main.js",
    "content": "import shouldTreeshake from './shared-css-empty-2.js'\ndocument.querySelector('#app').innerHTML = `\n  <div>\n    <h1>Shared CSS, with JS</h1>\n  </div>\n`\nfunction shouldBeTreeshaken_0() {\n  // This function should be treeshaken, even if { moduleSideEffects: 'no-treeshake' }\n  // was used in the JS corresponding to the HTML entrypoint.\n}\n"
  },
  {
    "path": "playground/css-codesplit/shared-css-no-js.html",
    "content": "<link rel=\"stylesheet\" type=\"text/css\" href=\"./shared-css-theme.css\" />\n<body>\n  <h1>Share CSS, no JS</h1>\n</body>\n"
  },
  {
    "path": "playground/css-codesplit/shared-css-theme.css",
    "content": "h1 {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-codesplit/shared-css-with-js.html",
    "content": "<link rel=\"stylesheet\" type=\"text/css\" href=\"./shared-css-theme.css\" />\n<script type=\"module\" src=\"./shared-css-main.js\"></script>\n<script type=\"module\" src=\"./shared-css-empty-1.js\"></script>\n<body>\n  <h1>Replaced by shared-css-main.js</h1>\n</body>\n"
  },
  {
    "path": "playground/css-codesplit/style.css",
    "content": "h2 {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-codesplit/style2.css",
    "content": "h2 {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-codesplit/style2.js",
    "content": "import './style2.css'\n"
  },
  {
    "path": "playground/css-codesplit/vite.config.js",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst dirname = import.meta.dirname\n\nexport default defineConfig({\n  build: {\n    manifest: true,\n    rollupOptions: {\n      input: {\n        main: resolve(dirname, './index.html'),\n        other: resolve(dirname, './other.js'),\n        style2: resolve(dirname, './style2.js'),\n        'shared-css-with-js': resolve(dirname, 'shared-css-with-js.html'),\n        'shared-css-no-js': resolve(dirname, 'shared-css-no-js.html'),\n      },\n      output: {\n        // manualChunks(id) {\n        //   // make `chunk.css` its own chunk for easier testing of pure css chunks\n        //   if (id.includes('chunk.css')) {\n        //     return 'chunk'\n        //   }\n        // },\n        codeSplitting: {\n          groups: [\n            // make `chunk.css` its own chunk for easier testing of pure css chunks\n            {\n              name: 'chunk',\n              test: 'chunk.css',\n            },\n          ],\n        },\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/css-codesplit-cjs/__tests__/css-codesplit-cjs.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { findAssetFile, getColor, isBuild, readManifest } from '~utils'\n\ntest.skip('should load both stylesheets', async () => {\n  expect(await getColor('h1')).toBe('red')\n  expect(await getColor('h2')).toBe('blue')\n})\n\ndescribe.runIf(isBuild).skip('build', () => {\n  test('should remove empty chunk', async () => {\n    expect(findAssetFile(/style.*\\.js$/)).toBeUndefined()\n    expect(findAssetFile('main.*.js$')).toMatch(`/* empty css`)\n    expect(findAssetFile('other.*.js$')).toMatch(`/* empty css`)\n  })\n\n  test('should generate correct manifest', async () => {\n    const manifest = readManifest()\n    expect(manifest['index.html'].css.length).toBe(2)\n    expect(manifest['other.js'].css.length).toBe(1)\n  })\n})\n"
  },
  {
    "path": "playground/css-codesplit-cjs/index.html",
    "content": "<script type=\"module\" src=\"/main.js\"></script>\n<div id=\"app\"></div>\n"
  },
  {
    "path": "playground/css-codesplit-cjs/main.css",
    "content": "h1 {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-codesplit-cjs/main.js",
    "content": "import './style.css'\nimport './main.css'\n\ndocument.getElementById('app').innerHTML =\n  `<h1>This should be red</h1><h2>This should be blue</h2>`\n"
  },
  {
    "path": "playground/css-codesplit-cjs/other.js",
    "content": "import './style.css'\n"
  },
  {
    "path": "playground/css-codesplit-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-codesplit-cjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"commonjs\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/css-codesplit-cjs/style.css",
    "content": "h2 {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-codesplit-cjs/vite.config.js",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    outDir: './dist',\n    manifest: true,\n    rollupOptions: {\n      input: {\n        main: resolve(import.meta.dirname, './index.html'),\n        other: resolve(import.meta.dirname, './other.js'),\n      },\n      treeshake: false,\n      output: {\n        format: 'cjs',\n        // freeze: false,\n        externalLiveBindings: false,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/css-dynamic-import/__tests__/css-dynamic-import.spec.ts",
    "content": "import type { InlineConfig } from 'vite'\nimport { build, createServer, preview } from 'vite'\nimport { expect, test } from 'vitest'\nimport { getColor, isBuild, isServe, page, ports, rootDir } from '~utils'\n\nconst baseOptions = [\n  { base: '', label: 'relative' },\n  { base: '/', label: 'absolute' },\n]\n\nconst getConfig = (base: string): InlineConfig => ({\n  base,\n  root: rootDir,\n  logLevel: 'silent',\n  server: { port: ports['css/dynamic-import'] },\n  preview: { port: ports['css/dynamic-import'] },\n  build: { assetsInlineLimit: 0 },\n})\n\nasync function withBuild(base: string, fn: () => Promise<void>) {\n  const config = getConfig(base)\n  await build(config)\n  const server = await preview(config)\n\n  try {\n    await page.goto(server.resolvedUrls.local[0])\n    await fn()\n  } finally {\n    server.httpServer.close()\n  }\n}\n\nasync function withServe(base: string, fn: () => Promise<void>) {\n  const config = getConfig(base)\n  const server = await createServer(config)\n  await server.listen()\n\n  try {\n    await page.goto(server.resolvedUrls.local[0])\n    await fn()\n  } finally {\n    await page.goto('about:blank') // move to a different page to avoid auto-refresh after server start\n    await server.close()\n  }\n}\n\nasync function getLinks() {\n  const links = await page.$$('link')\n  return await Promise.all(\n    links.map((handle) => {\n      return handle.evaluate((link) => ({\n        pathname: new URL(link.href).pathname,\n        rel: link.rel,\n        as: link.as,\n      }))\n    }),\n  )\n}\n\nbaseOptions.forEach(({ base, label }) => {\n  test.runIf(isBuild)(\n    `doesn't duplicate dynamically imported css files when built with ${label} base`,\n    async () => {\n      await withBuild(base, async () => {\n        await page.waitForSelector('.loaded', { state: 'attached' })\n\n        expect(await getColor('.css-dynamic-import')).toBe('green')\n        const linkUrls = (await getLinks()).map((link) => link.pathname)\n        const uniqueLinkUrls = [...new Set(linkUrls)]\n        expect(linkUrls).toStrictEqual(uniqueLinkUrls)\n      })\n    },\n  )\n\n  test.runIf(isServe)(\n    `doesn't duplicate dynamically imported css files when served with ${label} base`,\n    async () => {\n      await withServe(base, async () => {\n        await page.waitForSelector('.loaded', { state: 'attached' })\n\n        expect(await getColor('.css-dynamic-import')).toBe('green')\n        // in serve there is no preloading\n        expect(await getLinks()).toEqual([\n          {\n            pathname: '/dynamic.css',\n            rel: 'preload',\n            as: 'style',\n          },\n        ])\n      })\n    },\n  )\n})\n"
  },
  {
    "path": "playground/css-dynamic-import/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\n// The server is started in the test, so we need to have a custom serve\n// function or a default server will be created\nexport async function serve() {\n  return {\n    close: () => Promise.resolve(),\n  }\n}\n"
  },
  {
    "path": "playground/css-dynamic-import/dynamic.css",
    "content": ".css-dynamic-import {\n  color: green;\n}\n"
  },
  {
    "path": "playground/css-dynamic-import/dynamic.js",
    "content": "import './dynamic.css'\n\nexport const lazyLoad = async () => {\n  await import('./static.js')\n  document.body.classList.add('loaded')\n}\n"
  },
  {
    "path": "playground/css-dynamic-import/index.html",
    "content": "<p class=\"css-dynamic-import\">This should be green</p>\n\n<script type=\"module\" src=\"./index.js\"></script>\n"
  },
  {
    "path": "playground/css-dynamic-import/index.js",
    "content": "import './static.js'\n\nconst link = document.head.appendChild(document.createElement('link'))\nlink.rel = 'preload'\nlink.as = 'style'\nlink.href = new URL('./dynamic.css', import.meta.url).href\n\nimport('./dynamic.js').then(async ({ lazyLoad }) => {\n  await lazyLoad()\n})\n"
  },
  {
    "path": "playground/css-dynamic-import/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-dynamic-import\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/css-dynamic-import/static.css",
    "content": ".css-dynamic-import {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-dynamic-import/static.js",
    "content": "import './static.css'\n\nexport const foo = 'foo'\n"
  },
  {
    "path": "playground/css-lightningcss/__tests__/css-lightningcss.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport {\n  editFile,\n  findAssetFile,\n  getBg,\n  getColor,\n  isBuild,\n  page,\n  viteTestUrl,\n} from '~utils'\n\n// note: tests should retrieve the element at the beginning of test and reuse it\n// in later assertions to ensure CSS HMR doesn't reload the page\ntest('linked css', async () => {\n  const linked = await page.$('.linked')\n  const atImport = await page.$('.linked-at-import')\n\n  expect(await getColor(linked)).toBe('blue')\n  expect(await getColor(atImport)).toBe('red')\n\n  if (isBuild) return\n  editFile('linked.css', (code) => code.replace('color: blue', 'color: red'))\n  await expect.poll(() => getColor(linked)).toBe('red')\n\n  editFile('linked-at-import.css', (code) =>\n    code.replace('color: red', 'color: blue'),\n  )\n  await expect.poll(() => getColor(atImport)).toBe('blue')\n})\n\ntest('css import from js', async () => {\n  const imported = await page.$('.imported')\n  const atImport = await page.$('.imported-at-import')\n\n  expect(await getColor(imported)).toBe('green')\n  expect(await getColor(atImport)).toBe('purple')\n\n  if (isBuild) return\n  editFile('imported.css', (code) => code.replace('color: green', 'color: red'))\n  await expect.poll(() => getColor(imported)).toBe('red')\n\n  editFile('imported-at-import.css', (code) =>\n    code.replace('color: purple', 'color: blue'),\n  )\n  await expect.poll(() => getColor(atImport)).toBe('blue')\n})\n\ntest('css modules', async () => {\n  const imported = await page.$('.modules')\n  expect(await getColor(imported)).toBe('turquoise')\n\n  expect(await imported.getAttribute('class')).toMatch(/\\w{6}_apply-color/)\n\n  if (isBuild) return\n  editFile('mod.module.css', (code) =>\n    code.replace('color: turquoise', 'color: red'),\n  )\n  await expect.poll(() => getColor(imported)).toBe('red')\n})\n\ntest('inline css modules', async () => {\n  const css = await page.textContent('.modules-inline')\n  expect(css).toMatch(/\\._?\\w{6}_apply-color-inline/)\n})\n\ntest.runIf(isBuild)('minify css', async () => {\n  // should keep the rgba() syntax\n  const cssFile = findAssetFile(/index-[-\\w]+\\.css$/)\n  expect(cssFile).toMatch('rgba(')\n  expect(cssFile).not.toMatch('#ffff00b3')\n})\n\ntest('css with external url', async () => {\n  const css = await page.$('.external')\n  expect(await getBg(css)).toMatch('url(\"https://vite.dev/logo.svg\")')\n})\n\ntest('nested css with relative asset', async () => {\n  const css = await page.$('.nested-css-relative-asset')\n  expect(await getBg(css)).toMatch(\n    isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n  )\n})\n\ntest('aliased asset', async () => {\n  const bg = await getBg('.css-url-aliased')\n  expect(bg).toMatch('data:image/svg+xml,')\n})\n\ntest('preinlined SVG', async () => {\n  expect(await getBg('.css-url-preinlined-svg')).toMatch(\n    /data:image\\/svg\\+xml,.+/,\n  )\n})\n"
  },
  {
    "path": "playground/css-lightningcss/composed.module.css",
    "content": ".apply-color {\n  color: turquoise;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/composes-path-resolving.module.css",
    "content": ".path-resolving-css {\n  composes: apply-color from './composed.module.css';\n}\n"
  },
  {
    "path": "playground/css-lightningcss/css-url.css",
    "content": ".css-url-aliased {\n  background: url('@/fragment.svg');\n  background-size: 10px;\n}\n\n.css-url-preinlined-svg {\n  background: url('data:image/svg+xml,<svg fill=\"black\" width=\"48\" height=\"48\" viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M30.74,15.95c-.01-.1-.04-.2-.09-.28,0-.01,0-.03-.01-.05l-5.57-8.6c-.19-.29-.56-.42-.89-.3C8.21,12.62,3.37,14.48,1.9,15.3c-.27,.04-.5,.21-.59,.46-.05,.09-.05,.17-.05,.26v8.38c0,.41,.34,.75,.75,.75H30c.41,0,.75-.34,.75-.75v-8.38s0-.01,0-.02c0-.02,0-.04-.01-.06Zm-6.61-7.62l4.49,6.94H5.7c4.42-1.73,12.41-4.72,18.43-6.94Zm5.12,15.32H2.75v-6.88H29.25v6.88Z\"/><path d=\"M6.16,21.34c.99,0,1.79-.8,1.79-1.79s-.8-1.79-1.79-1.79-1.79,.8-1.79,1.79,.8,1.79,1.79,1.79Zm0-2.08c.16,0,.29,.13,.29,.29s-.13,.29-.29,.29-.29-.13-.29-.29,.13-.29,.29-.29Z\"/><path d=\"M15.15,23.04c.99,0,1.79-.8,1.79-1.79s-.8-1.79-1.79-1.79-1.79,.8-1.79,1.79,.8,1.79,1.79,1.79Zm0-2.08c.16,0,.29,.13,.29,.29s-.13,.29-.29,.29-.29-.13-.29-.29,.13-.29,.29-.29Z\"/><path d=\"M24.28,20.73c.99,0,1.79-.8,1.79-1.79s-.8-1.79-1.79-1.79-1.79,.8-1.79,1.79,.8,1.79,1.79,1.79Zm0-2.08c.16,0,.29,.13,.29,.29s-.13,.29-.29,.29-.29-.13-.29-.29,.13-.29,.29-.29Z\"/><path d=\"M22.78,10.16c-.99,0-1.79,.8-1.79,1.79s.8,1.79,1.79,1.79,1.79-.8,1.79-1.79-.8-1.79-1.79-1.79Zm0,2.08c-.16,0-.29-.13-.29-.29s.13-.29,.29-.29,.29,.13,.29,.29-.13,.29-.29,.29Z\"/></svg>');\n  background-size: 20px;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/external-url.css",
    "content": ".external {\n  background-image: url('https://vite.dev/logo.svg');\n  background-size: 100%;\n  width: 200px;\n  height: 200px;\n  background-color: #bed;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/imported-at-import.css",
    "content": ".imported-at-import {\n  color: purple;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/imported.css",
    "content": "@import url('./nested/nested.css');\n@import './imported-at-import.css';\n\n.imported {\n  color: green;\n}\n\npre {\n  background-color: #eee;\n  width: 500px;\n  padding: 1em 1.5em;\n  border-radius: 10px;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./linked.css\" />\n\n<div class=\"wrapper\">\n  <h1>Lightning CSS</h1>\n\n  <p class=\"linked\">&lt;link&gt;: This should be blue</p>\n  <p class=\"linked-at-import\">@import in &lt;link&gt;: This should be red</p>\n\n  <p class=\"imported\">import from js: This should be green</p>\n  <p class=\"imported-at-import\">\n    @import in import from js: This should be purple\n  </p>\n\n  <p class=\"modules\">CSS modules: this should be turquoise</p>\n  <p>Imported CSS module:</p>\n  <pre class=\"modules-code\"></pre>\n\n  <p>Imported compose/from CSS module:</p>\n  <p class=\"path-resolved-modules-css\">\n    CSS modules composes path resolving: this should be turquoise\n  </p>\n  <pre class=\"path-resolved-modules-code\"></pre>\n\n  <p>Inline CSS module:</p>\n  <pre class=\"modules-inline\"></pre>\n\n  <p>External URL</p>\n  <div class=\"external\"></div>\n\n  <p>Assets relative to nested CSS</p>\n  <div class=\"nested-css-relative-asset\"></div>\n\n  <div class=\"css-url-aliased\">\n    <span style=\"background: #fff\">CSS background (aliased)</span>\n  </div>\n  <div class=\"css-url-preinlined-svg\">\n    <span style=\"background: #fff\">CSS background (pre inlined SVG)</span>\n  </div>\n</div>\n\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/css-lightningcss/inline.module.css",
    "content": ".apply-color-inline {\n  color: turquoise;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/inlined.css",
    "content": ".inlined {\n  color: green;\n  background: url('./ok.png');\n}\n"
  },
  {
    "path": "playground/css-lightningcss/linked-at-import.css",
    "content": ".linked-at-import {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/linked.css",
    "content": "@import './linked-at-import.css';\n\n/* test nesting */\n.wrapper {\n  .linked {\n    color: blue;\n  }\n}\n"
  },
  {
    "path": "playground/css-lightningcss/main.js",
    "content": "import './minify.css'\nimport './imported.css'\nimport mod from './mod.module.css'\nimport './external-url.css'\nimport './css-url.css'\n\ndocument.querySelector('.modules').classList.add(mod['apply-color'])\ntext('.modules-code', JSON.stringify(mod, null, 2))\n\nimport composesPathResolvingMod from './composes-path-resolving.module.css'\ndocument\n  .querySelector('.path-resolved-modules-css')\n  .classList.add(...composesPathResolvingMod['path-resolving-css'].split(' '))\ntext(\n  '.path-resolved-modules-code',\n  JSON.stringify(composesPathResolvingMod, null, 2),\n)\n\nimport inlineMod from './inline.module.css?inline'\ntext('.modules-inline', inlineMod)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nif (import.meta.hot) {\n  import.meta.hot.accept('./mod.module.css', (newMod) => {\n    const list = document.querySelector('.modules').classList\n    list.remove(mod.applyColor)\n    list.add(newMod.applyColor)\n    text('.modules-code', JSON.stringify(newMod.default, null, 2))\n  })\n}\n"
  },
  {
    "path": "playground/css-lightningcss/minify.css",
    "content": ".test-minify {\n  color: rgba(255, 255, 0, 0.7);\n}\n"
  },
  {
    "path": "playground/css-lightningcss/mod.module.css",
    "content": ".apply-color {\n  color: turquoise;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/nested/nested.css",
    "content": ".nested-css-relative-asset {\n  background-image: url('../ok.png');\n  width: 50px;\n  height: 50px;\n}\n"
  },
  {
    "path": "playground/css-lightningcss/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-lightningcss\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"lightningcss\": \"^1.32.0\"\n  }\n}\n"
  },
  {
    "path": "playground/css-lightningcss/vite.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  css: {\n    transformer: 'lightningcss',\n  },\n  resolve: {\n    alias: {\n      '@': path.resolve(import.meta.dirname, 'nested'),\n    },\n  },\n  build: {\n    cssTarget: ['chrome61'],\n    cssMinify: 'lightningcss',\n  },\n})\n"
  },
  {
    "path": "playground/css-lightningcss-proxy/__tests__/css-lightningcss-proxy.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { port } from './serve'\nimport { getColor, isServe, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ndescribe.runIf(isServe)('injected inline style', () => {\n  test('injected inline style is present', async () => {\n    await page.goto(url)\n    const el = await page.$('.ssr-proxy')\n    expect(await getColor(el)).toBe('coral')\n  })\n})\n"
  },
  {
    "path": "playground/css-lightningcss-proxy/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { hmrPorts, ports, rootDir } from '~utils'\n\nexport const port = ports['css/lightningcss-proxy']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(\n    rootDir,\n    hmrPorts['css/lightningcss-proxy'],\n  )\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/css-lightningcss-proxy/index.html",
    "content": "<!--[inline-css]-->\n<div class=\"wrapper\">\n  <p>Injected inline style with SSR Proxy</p>\n  <p class=\"ssr-proxy\">This should be coral</p>\n</div>\n"
  },
  {
    "path": "playground/css-lightningcss-proxy/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-lightningcss-proxy\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"lightningcss\": \"^1.32.0\",\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/css-lightningcss-proxy/server.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nconst DYNAMIC_STYLES = `\n  <style>\n  .ssr-proxy {\n    color: coral;\n  }\n  </style>\n`\n\nexport async function createServer(root = process.cwd(), hmrPort) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  const vite = await (\n    await import('vite')\n  ).createServer({\n    root,\n    logLevel: isTest ? 'error' : 'info',\n    css: {\n      transformer: 'lightningcss',\n    },\n    server: {\n      middlewareMode: true,\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n      hmr: {\n        port: hmrPort,\n      },\n    },\n    appType: 'custom',\n  })\n  // use vite's connect instance as middleware\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res, next) => {\n    try {\n      let [url] = req.originalUrl.split('?')\n      if (url.endsWith('/')) url += 'index.html'\n\n      if (url.startsWith('/favicon.ico')) {\n        return res.status(404).end('404')\n      }\n\n      const htmlLoc = resolve(`.${url}`)\n      let template = fs.readFileSync(htmlLoc, 'utf-8')\n\n      template = template.replace('<!--[inline-css]-->', DYNAMIC_STYLES)\n\n      // Force calling transformIndexHtml with url === '/', to simulate\n      // usage by ecosystem that was recommended in the SSR documentation\n      // as `const url = req.originalUrl`\n      const html = await vite.transformIndexHtml('/', template)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite && vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/css-lightningcss-root/__tests__/css-lightningcss-root.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getBg, isBuild, page, viteTestUrl } from '~utils'\n\ntest('url dependency', async () => {\n  const css = await page.$('.url-dep')\n  expect(await getBg(css)).toMatch(\n    isBuild ? /ok-[-\\w]+\\.png/ : `${viteTestUrl}/ok.png`,\n  )\n})\n"
  },
  {
    "path": "playground/css-lightningcss-root/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-lightningcss-root\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"lightningcss\": \"^1.32.0\"\n  }\n}\n"
  },
  {
    "path": "playground/css-lightningcss-root/root/index.html",
    "content": "<p>url() dependency</p>\n<div class=\"url-dep\"></div>\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/css-lightningcss-root/root/main.js",
    "content": "import './url-dep.css'\n"
  },
  {
    "path": "playground/css-lightningcss-root/root/url-dep.css",
    "content": ".url-dep {\n  background-image: url('./ok.png');\n  background-size: cover;\n  width: 50px;\n  height: 50px;\n  border: 1px solid black;\n}\n"
  },
  {
    "path": "playground/css-lightningcss-root/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  root: 'root',\n  css: {\n    transformer: 'lightningcss',\n  },\n})\n"
  },
  {
    "path": "playground/css-no-codesplit/__tests__/css-no-codesplit.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { getColor, isBuild, listAssets } from '~utils'\n\ntest('should load all stylesheets', async () => {\n  expect(await getColor('.shared-linked')).toBe('blue')\n  await expect.poll(() => getColor('.async-js')).toBe('blue')\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('should remove empty chunk', async () => {\n    const assets = listAssets()\n    expect(assets).not.toContainEqual(\n      expect.stringMatching(/shared-linked-.*\\.js$/),\n    )\n    expect(assets).not.toContainEqual(expect.stringMatching(/async-js-.*\\.js$/))\n  })\n})\n"
  },
  {
    "path": "playground/css-no-codesplit/async-js.css",
    "content": ".async-js {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-no-codesplit/async-js.js",
    "content": "// a JS file that becomes an empty file but imports CSS files\nimport './async-js.css'\n"
  },
  {
    "path": "playground/css-no-codesplit/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./shared-linked.css\" />\n<script type=\"module\" src=\"./index.js\"></script>\n\n<p class=\"shared-linked\">shared linked: this should be blue</p>\n<p class=\"async-js\">async JS importing CSS: this should be blue</p>\n"
  },
  {
    "path": "playground/css-no-codesplit/index.js",
    "content": "import('./async-js')\n"
  },
  {
    "path": "playground/css-no-codesplit/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-no-codesplit\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/css-no-codesplit/shared-linked.css",
    "content": ".shared-linked {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-no-codesplit/sub.html",
    "content": "<link rel=\"stylesheet\" href=\"./shared-linked.css\" />\n"
  },
  {
    "path": "playground/css-no-codesplit/vite.config.js",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    cssCodeSplit: false,\n    rollupOptions: {\n      input: {\n        index: resolve(import.meta.dirname, './index.html'),\n        sub: resolve(import.meta.dirname, './sub.html'),\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/css-sourcemap/__tests__/css-sourcemap.spec.ts",
    "content": "import { URL } from 'node:url'\nimport { describe, expect, test } from 'vitest'\nimport {\n  extractSourcemap,\n  formatSourcemapForSnapshot,\n  isBuild,\n  isServe,\n  page,\n  serverLogs,\n} from '~utils'\n\ntest.runIf(isBuild)('should not output sourcemap warning (#4939)', () => {\n  serverLogs.forEach((log) => {\n    expect(log).not.toMatch('Sourcemap is likely to be incorrect')\n  })\n})\n\ndescribe.runIf(isServe)('serve', () => {\n  const getStyleTagContentIncluding = async (content: string) => {\n    const styles = await page.$$('style')\n    for (const style of styles) {\n      const text = await style.textContent()\n      if (text.includes(content)) {\n        return text\n      }\n    }\n    throw new Error('Not found')\n  }\n\n  test('linked css', async () => {\n    const res = await page.request.get(\n      new URL('./linked.css', page.url()).href,\n      {\n        headers: {\n          accept: 'text/css',\n        },\n      },\n    )\n    const css = await res.text()\n    expect(css).not.toContain('sourceMappingURL')\n  })\n\n  test('linked css with import', async () => {\n    const res = await page.request.get(\n      new URL('./linked-with-import.css', page.url()).href,\n      {\n        headers: {\n          accept: 'text/css',\n        },\n      },\n    )\n    const css = await res.text()\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ\",\n          \"sources\": [\n            \"be-imported.css\",\n            \"linked-with-import.css\",\n          ],\n          \"sourcesContent\": [\n            \".be-imported {\n        color: red;\n      }\n      \",\n            \"@import '@/be-imported.css';\n\n      .linked-with-import {\n        color: red;\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NzAALmJlLWltcG9ydGVkIHsKICBjb2xvcjogcmVkOwp9CgoubGlua2VkLXdpdGgtaW1wb3J0IHsKICBjb2xvcjogcmVkOwp9CjI1NAB7Im1hcHBpbmdzIjoiQUFBQTtFQUNFLFVBQVU7QUFDWjs7QUNBQTtFQUNFLFVBQVU7QUFDWiIsInNvdXJjZXMiOlsiYmUtaW1wb3J0ZWQuY3NzIiwibGlua2VkLXdpdGgtaW1wb3J0LmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyIuYmUtaW1wb3J0ZWQge1xuICBjb2xvcjogcmVkO1xufVxuIiwiQGltcG9ydCAnQC9iZS1pbXBvcnRlZC5jc3MnO1xuXG4ubGlua2VkLXdpdGgtaW1wb3J0IHtcbiAgY29sb3I6IHJlZDtcbn1cbiJdLCJ2ZXJzaW9uIjozfQ==\"\n      }\n    `)\n  })\n\n  test.runIf(isServe)(\n    'js .css request does not include sourcemap',\n    async () => {\n      const res = await page.request.get(\n        new URL('./linked-with-import.css', page.url()).href,\n      )\n      const content = await res.text()\n      expect(content).not.toMatch('//#s*sourceMappingURL')\n    },\n  )\n\n  test('imported css', async () => {\n    const css = await getStyleTagContentIncluding('.imported ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA,CAAC,QAAQ,CAAC;AACV,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG;AACZ;\",\n          \"sources\": [\n            \"/root/imported.css\",\n          ],\n          \"sourcesContent\": [\n            \".imported {\n        color: red;\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MjgALmltcG9ydGVkIHsKICBjb2xvcjogcmVkOwp9CjE3MwB7InZlcnNpb24iOjMsInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIi5pbXBvcnRlZCB7XG4gIGNvbG9yOiByZWQ7XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBLENBQUMsUUFBUSxDQUFDO0FBQ1YsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUc7QUFDWjsifQ==\"\n      }\n    `)\n  })\n\n  test('imported css with import', async () => {\n    const css = await getStyleTagContentIncluding('.imported-with-import ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ\",\n          \"sources\": [\n            \"/root/be-imported.css\",\n            \"/root/imported-with-import.css\",\n          ],\n          \"sourcesContent\": [\n            \".be-imported {\n        color: red;\n      }\n      \",\n            \"@import '@/be-imported.css';\n\n      .imported-with-import {\n        color: red;\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NzIALmJlLWltcG9ydGVkIHsKICBjb2xvcjogcmVkOwp9CgouaW1wb3J0ZWQtd2l0aC1pbXBvcnQgewogIGNvbG9yOiByZWQ7Cn0KMjcwAHsibWFwcGluZ3MiOiJBQUFBO0VBQ0UsVUFBVTtBQUNaOztBQ0FBO0VBQ0UsVUFBVTtBQUNaIiwic291cmNlcyI6WyIvcm9vdC9iZS1pbXBvcnRlZC5jc3MiLCIvcm9vdC9pbXBvcnRlZC13aXRoLWltcG9ydC5jc3MiXSwic291cmNlc0NvbnRlbnQiOlsiLmJlLWltcG9ydGVkIHtcbiAgY29sb3I6IHJlZDtcbn1cbiIsIkBpbXBvcnQgJ0AvYmUtaW1wb3J0ZWQuY3NzJztcblxuLmltcG9ydGVkLXdpdGgtaW1wb3J0IHtcbiAgY29sb3I6IHJlZDtcbn1cbiJdLCJ2ZXJzaW9uIjozfQ==\"\n      }\n    `)\n  })\n\n  test('imported sass', async () => {\n    const css = await getStyleTagContentIncluding('.imported-sass ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAGE;EACE,OCJM\",\n          \"sourceRoot\": \"\",\n          \"sources\": [\n            \"/root/imported.sass\",\n            \"/root/imported-nested.sass\",\n          ],\n          \"sourcesContent\": [\n            \"@use \"/imported-nested.sass\"\n\n      .imported\n        &-sass\n          color: imported-nested.$primary\n      \",\n            \"$primary: red\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzMALmltcG9ydGVkLXNhc3MgewogIGNvbG9yOiByZWQ7Cn0KMjUyAHsidmVyc2lvbiI6Mywic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQuc2FzcyIsIi9yb290L2ltcG9ydGVkLW5lc3RlZC5zYXNzIl0sIm1hcHBpbmdzIjoiQUFHRTtFQUNFLE9DSk0iLCJzb3VyY2VzQ29udGVudCI6WyJAdXNlIFwiL2ltcG9ydGVkLW5lc3RlZC5zYXNzXCJcblxuLmltcG9ydGVkXG4gICYtc2Fzc1xuICAgIGNvbG9yOiBpbXBvcnRlZC1uZXN0ZWQuJHByaW1hcnlcbiIsIiRwcmltYXJ5OiByZWRcbiJdfQ==\"\n      }\n    `)\n  })\n\n  test('imported sass module', async () => {\n    const css = await getStyleTagContentIncluding('._imported-sass-module_')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AACE;EACE\",\n          \"sources\": [\n            \"/root/imported.module.sass\",\n          ],\n          \"sourcesContent\": [\n            \".imported\n        &-sass-module\n          color: red\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NDkALl9pbXBvcnRlZC1zYXNzLW1vZHVsZV9yMXFjcF8xIHsKICBjb2xvcjogcmVkOwp9CjE1OQB7InZlcnNpb24iOjMsIm1hcHBpbmdzIjoiQUFDRTtFQUNFIiwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQubW9kdWxlLnNhc3MiXSwic291cmNlc0NvbnRlbnQiOlsiLmltcG9ydGVkXG4gICYtc2Fzcy1tb2R1bGVcbiAgICBjb2xvcjogcmVkXG4iXX0=\"\n      }\n    `)\n  })\n\n  test('imported less', async () => {\n    const css = await getStyleTagContentIncluding('.imported-less ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AACE,SAAC;EACC\",\n          \"sources\": [\n            \"/root/imported.less\",\n          ],\n          \"sourcesContent\": [\n            \".imported {\n        &-less {\n          color: @color;\n        }\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzMALmltcG9ydGVkLWxlc3MgewogIGNvbG9yOiByZWQ7Cn0KMTY2AHsidmVyc2lvbiI6MywibWFwcGluZ3MiOiJBQUNFLFNBQUM7RUFDQyIsImlnbm9yZUxpc3QiOltdLCJzb3VyY2VzIjpbIi9yb290L2ltcG9ydGVkLmxlc3MiXSwic291cmNlc0NvbnRlbnQiOlsiLmltcG9ydGVkIHtcbiAgJi1sZXNzIHtcbiAgICBjb2xvcjogQGNvbG9yO1xuICB9XG59XG4iXX0=\"\n      }\n    `)\n  })\n\n  test('imported stylus', async () => {\n    const css = await getStyleTagContentIncluding('.imported-stylus ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AACE;EACE,OAAM,QAAN\",\n          \"sources\": [\n            \"/root/imported.styl\",\n          ],\n          \"sourcesContent\": [\n            \".imported\n        &-stylus\n          color blue-red-mixed\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzkALmltcG9ydGVkLXN0eWx1cyB7CiAgY29sb3I6ICM4MDAwODA7Cn0KMTY3AHsidmVyc2lvbiI6MywibWFwcGluZ3MiOiJBQUNFO0VBQ0UsT0FBTSxRQUFOIiwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQuc3R5bCJdLCJzb3VyY2VzQ29udGVudCI6WyIuaW1wb3J0ZWRcbiAgJi1zdHlsdXNcbiAgICBjb2xvciBibHVlLXJlZC1taXhlZFxuIl19\"\n      }\n    `)\n  })\n\n  test('imported sugarss', async () => {\n    const css = await getStyleTagContentIncluding('.imported-sugarss ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA;EACE;AADe\",\n          \"sources\": [\n            \"/root/imported.sss\",\n          ],\n          \"sourcesContent\": [\n            \".imported-sugarss\n        color: red\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzUALmltcG9ydGVkLXN1Z2Fyc3MgewogIGNvbG9yOiByZWQKfQoxMjkAeyJtYXBwaW5ncyI6IkFBQUE7RUFDRTtBQURlIiwic291cmNlcyI6WyIvcm9vdC9pbXBvcnRlZC5zc3MiXSwic291cmNlc0NvbnRlbnQiOlsiLmltcG9ydGVkLXN1Z2Fyc3NcbiAgY29sb3I6IHJlZFxuIl0sInZlcnNpb24iOjN9\"\n      }\n    `)\n  })\n\n  test('should not output missing source file warning', () => {\n    serverLogs.forEach((log) => {\n      expect(log).not.toMatch(/Sourcemap for .+ points to missing source files/)\n    })\n  })\n})\n"
  },
  {
    "path": "playground/css-sourcemap/__tests__/lib-entry/css-sourcemap-lib-entry.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { findAssetFile, isBuild } from '~utils'\n\ndescribe.runIf(isBuild)('css lib entry', () => {\n  test('remove useless js sourcemap', async () => {\n    expect(findAssetFile('linked.js.map', 'lib-entry', './')).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "playground/css-sourcemap/__tests__/lightningcss/lightningcss.spec.ts",
    "content": "import { URL } from 'node:url'\nimport { describe, expect, test } from 'vitest'\nimport {\n  extractSourcemap,\n  formatSourcemapForSnapshot,\n  isBuild,\n  isServe,\n  page,\n  serverLogs,\n} from '~utils'\n\ntest.runIf(isBuild)('should not output sourcemap warning (#4939)', () => {\n  serverLogs.forEach((log) => {\n    expect(log).not.toMatch('Sourcemap is likely to be incorrect')\n  })\n})\n\ndescribe.runIf(isServe)('serve', () => {\n  const getStyleTagContentIncluding = async (content: string) => {\n    const styles = await page.$$('style')\n    for (const style of styles) {\n      const text = await style.textContent()\n      if (text.includes(content)) {\n        return text\n      }\n    }\n    throw new Error('Not found')\n  }\n\n  test('linked css', async () => {\n    const res = await page.request.get(\n      new URL('./linked.css', page.url()).href,\n      {\n        headers: {\n          accept: 'text/css',\n        },\n      },\n    )\n    const css = await res.text()\n    expect(css).not.toContain('sourceMappingURL')\n  })\n\n  test('linked css with import', async () => {\n    const res = await page.request.get(\n      new URL('./linked-with-import.css', page.url()).href,\n      {\n        headers: {\n          accept: 'text/css',\n        },\n      },\n    )\n    const css = await res.text()\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"ACAA;;;;ADEA\",\n          \"sourceRoot\": null,\n          \"sources\": [\n            \"linked-with-import.css\",\n            \"be-imported.css\",\n          ],\n          \"sourcesContent\": [\n            \"@import '@/be-imported.css';\n\n      .linked-with-import {\n        color: red;\n      }\n      \",\n            \".be-imported {\n        color: red;\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NzAALmJlLWltcG9ydGVkIHsKICBjb2xvcjogcmVkOwp9CgoubGlua2VkLXdpdGgtaW1wb3J0IHsKICBjb2xvcjogcmVkOwp9CjI0NAB7InZlcnNpb24iOjMsInNvdXJjZVJvb3QiOm51bGwsIm1hcHBpbmdzIjoiQUNBQTs7OztBREVBIiwic291cmNlcyI6WyJsaW5rZWQtd2l0aC1pbXBvcnQuY3NzIiwiYmUtaW1wb3J0ZWQuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgJ0AvYmUtaW1wb3J0ZWQuY3NzJztcblxuLmxpbmtlZC13aXRoLWltcG9ydCB7XG4gIGNvbG9yOiByZWQ7XG59XG4iLCIuYmUtaW1wb3J0ZWQge1xuICBjb2xvcjogcmVkO1xufVxuIl19\"\n      }\n    `)\n  })\n\n  test.runIf(isServe)(\n    'js .css request does not include sourcemap',\n    async () => {\n      const res = await page.request.get(\n        new URL('./linked-with-import.css', page.url()).href,\n      )\n      const content = await res.text()\n      expect(content).not.toMatch('//#s*sourceMappingURL')\n    },\n  )\n\n  test('imported css', async () => {\n    const css = await getStyleTagContentIncluding('.imported ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA\",\n          \"sourceRoot\": null,\n          \"sources\": [\n            \"imported.css\",\n          ],\n          \"sourcesContent\": [\n            \".imported {\n        color: red;\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MjgALmltcG9ydGVkIHsKICBjb2xvcjogcmVkOwp9CjEyOQB7InZlcnNpb24iOjMsInNvdXJjZVJvb3QiOm51bGwsIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsiaW1wb3J0ZWQuY3NzIl0sInNvdXJjZXNDb250ZW50IjpbIi5pbXBvcnRlZCB7XG4gIGNvbG9yOiByZWQ7XG59XG4iXX0=\"\n      }\n    `)\n  })\n\n  test('imported css with import', async () => {\n    const css = await getStyleTagContentIncluding('.imported-with-import ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"ACAA;;;;ADEA\",\n          \"sourceRoot\": null,\n          \"sources\": [\n            \"imported-with-import.css\",\n            \"be-imported.css\",\n          ],\n          \"sourcesContent\": [\n            \"@import '@/be-imported.css';\n\n      .imported-with-import {\n        color: red;\n      }\n      \",\n            \".be-imported {\n        color: red;\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NzIALmJlLWltcG9ydGVkIHsKICBjb2xvcjogcmVkOwp9CgouaW1wb3J0ZWQtd2l0aC1pbXBvcnQgewogIGNvbG9yOiByZWQ7Cn0KMjQ4AHsidmVyc2lvbiI6Mywic291cmNlUm9vdCI6bnVsbCwibWFwcGluZ3MiOiJBQ0FBOzs7O0FERUEiLCJzb3VyY2VzIjpbImltcG9ydGVkLXdpdGgtaW1wb3J0LmNzcyIsImJlLWltcG9ydGVkLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJAaW1wb3J0ICdAL2JlLWltcG9ydGVkLmNzcyc7XG5cbi5pbXBvcnRlZC13aXRoLWltcG9ydCB7XG4gIGNvbG9yOiByZWQ7XG59XG4iLCIuYmUtaW1wb3J0ZWQge1xuICBjb2xvcjogcmVkO1xufVxuIl19\"\n      }\n    `)\n  })\n\n  test('imported sass', async () => {\n    const css = await getStyleTagContentIncluding('.imported-sass ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AAGE\",\n          \"sources\": [\n            \"/root/imported.sass\",\n          ],\n          \"sourcesContent\": [\n            \"@use \"/imported-nested.sass\"\n\n      .imported\n        &-sass\n          color: imported-nested.$primary\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzMALmltcG9ydGVkLXNhc3MgewogIGNvbG9yOiByZWQ7Cn0KMTk1AHsidmVyc2lvbiI6MywibWFwcGluZ3MiOiJBQUdFIiwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQuc2FzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJAdXNlIFwiL2ltcG9ydGVkLW5lc3RlZC5zYXNzXCJcblxuLmltcG9ydGVkXG4gICYtc2Fzc1xuICAgIGNvbG9yOiBpbXBvcnRlZC1uZXN0ZWQuJHByaW1hcnlcbiJdfQ==\"\n      }\n    `)\n  })\n\n  test('imported sass module', async () => {\n    const css = await getStyleTagContentIncluding('_imported-sass-module')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AACE\",\n          \"sources\": [\n            \"/root/imported.module.sass\",\n          ],\n          \"sourcesContent\": [\n            \".imported\n        &-sass-module\n          color: red\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NDcALmhvUU10V19pbXBvcnRlZC1zYXNzLW1vZHVsZSB7CiAgY29sb3I6IHJlZDsKfQoxNTQAeyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQ0UiLCJpZ25vcmVMaXN0IjpbXSwic291cmNlcyI6WyIvcm9vdC9pbXBvcnRlZC5tb2R1bGUuc2FzcyJdLCJzb3VyY2VzQ29udGVudCI6WyIuaW1wb3J0ZWRcbiAgJi1zYXNzLW1vZHVsZVxuICAgIGNvbG9yOiByZWRcbiJdfQ==\"\n      }\n    `)\n  })\n\n  test('imported less', async () => {\n    const css = await getStyleTagContentIncluding('.imported-less ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AACE\",\n          \"sources\": [\n            \"/root/imported.less\",\n          ],\n          \"sourcesContent\": [\n            \".imported {\n        &-less {\n          color: @color;\n        }\n      }\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzMALmltcG9ydGVkLWxlc3MgewogIGNvbG9yOiByZWQ7Cn0KMTU2AHsidmVyc2lvbiI6MywibWFwcGluZ3MiOiJBQUNFIiwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQubGVzcyJdLCJzb3VyY2VzQ29udGVudCI6WyIuaW1wb3J0ZWQge1xuICAmLWxlc3Mge1xuICAgIGNvbG9yOiBAY29sb3I7XG4gIH1cbn1cbiJdfQ==\"\n      }\n    `)\n  })\n\n  test('imported stylus', async () => {\n    const css = await getStyleTagContentIncluding('.imported-stylus ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AACE\",\n          \"sources\": [\n            \"/root/imported.styl\",\n          ],\n          \"sourcesContent\": [\n            \".imported\n        &-stylus\n          color blue-red-mixed\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzgALmltcG9ydGVkLXN0eWx1cyB7CiAgY29sb3I6IHB1cnBsZTsKfQoxNTIAeyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBQ0UiLCJpZ25vcmVMaXN0IjpbXSwic291cmNlcyI6WyIvcm9vdC9pbXBvcnRlZC5zdHlsIl0sInNvdXJjZXNDb250ZW50IjpbIi5pbXBvcnRlZFxuICAmLXN0eWx1c1xuICAgIGNvbG9yIGJsdWUtcmVkLW1peGVkXG4iXX0=\"\n      }\n    `)\n  })\n\n  test('imported sugarss', async () => {\n    const css = await getStyleTagContentIncluding('.imported-sugarss ')\n    const map = extractSourcemap(css)\n    expect(formatSourcemapForSnapshot(map, css)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"ignoreList\": [],\n          \"mappings\": \"AAAA\",\n          \"sources\": [\n            \"/root/imported.sss\",\n          ],\n          \"sourcesContent\": [\n            \".imported-sugarss\n        color: red\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MzYALmltcG9ydGVkLXN1Z2Fyc3MgewogIGNvbG9yOiByZWQ7Cn0KMTM1AHsidmVyc2lvbiI6MywibWFwcGluZ3MiOiJBQUFBIiwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiL3Jvb3QvaW1wb3J0ZWQuc3NzIl0sInNvdXJjZXNDb250ZW50IjpbIi5pbXBvcnRlZC1zdWdhcnNzXG4gIGNvbG9yOiByZWRcbiJdfQ==\"\n      }\n    `)\n  })\n\n  test('should not output missing source file warning', () => {\n    serverLogs.forEach((log) => {\n      expect(log).not.toMatch(/Sourcemap for .+ points to missing source files/)\n    })\n  })\n})\n"
  },
  {
    "path": "playground/css-sourcemap/be-imported.css",
    "content": ".be-imported {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-sourcemap/imported-nested.sass",
    "content": "$primary: red\n"
  },
  {
    "path": "playground/css-sourcemap/imported-with-import.css",
    "content": "@import '@/be-imported.css';\n\n.imported-with-import {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-sourcemap/imported.css",
    "content": ".imported {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-sourcemap/imported.less",
    "content": ".imported {\n  &-less {\n    color: @color;\n  }\n}\n"
  },
  {
    "path": "playground/css-sourcemap/imported.module.sass",
    "content": ".imported\n  &-sass-module\n    color: red\n"
  },
  {
    "path": "playground/css-sourcemap/imported.sass",
    "content": "@use \"/imported-nested.sass\"\n\n.imported\n  &-sass\n    color: imported-nested.$primary\n"
  },
  {
    "path": "playground/css-sourcemap/imported.sss",
    "content": ".imported-sugarss\n  color: red\n"
  },
  {
    "path": "playground/css-sourcemap/imported.styl",
    "content": ".imported\n  &-stylus\n    color blue-red-mixed\n"
  },
  {
    "path": "playground/css-sourcemap/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./linked.css\" />\n<link rel=\"stylesheet\" href=\"./linked-with-import.css\" />\n\n<style>\n  .inline {\n    color: red;\n  }\n</style>\n\n<div class=\"wrapper\">\n  <h1>CSS Sourcemap</h1>\n\n  <p class=\"inline\">&lt;inline&gt;</p>\n\n  <p class=\"linked\">&lt;linked&gt;: no import</p>\n  <p class=\"linked-with-import\">&lt;linked&gt;: with import</p>\n\n  <p class=\"imported\">&lt;imported&gt;: no import</p>\n  <p class=\"imported-with-import\">&lt;imported&gt;: with import</p>\n\n  <p class=\"imported-sass\">&lt;imported sass&gt;</p>\n  <p class=\"imported-sass-module\">&lt;imported sass&gt; with module</p>\n\n  <p class=\"imported-less\">&lt;imported less&gt; with string additionalData</p>\n\n  <p class=\"imported-stylus\">&lt;imported stylus&gt;</p>\n\n  <p class=\"imported-sugarss\">&lt;imported sugarss&gt;</p>\n\n  <p class=\"input-map\">&lt;input source-map&gt;</p>\n</div>\n\n<script type=\"module\">\n  import './imported.css'\n  import './imported-with-import.css'\n\n  import './imported.sass'\n  import sassModule from './imported.module.sass'\n\n  document\n    .querySelector('.imported-sass-module')\n    .classList.add(sassModule['imported-sass-module'])\n\n  import './imported.less'\n\n  import './imported.styl'\n\n  import './imported.sss'\n\n  import './input-map.css'\n</script>\n\n<iframe src=\"virtual.html\"></iframe>\n"
  },
  {
    "path": "playground/css-sourcemap/index.js",
    "content": "export default 'hello'\n"
  },
  {
    "path": "playground/css-sourcemap/input-map.css",
    "content": ".input-map {\n  color: #00f;\n}\n/*# sourceMappingURL=input-map.css.map */\n"
  },
  {
    "path": "playground/css-sourcemap/input-map.src.css",
    "content": ".input-map {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/css-sourcemap/linked-with-import.css",
    "content": "@import '@/be-imported.css';\n\n.linked-with-import {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-sourcemap/linked.css",
    "content": ".linked {\n  color: red;\n}\n"
  },
  {
    "path": "playground/css-sourcemap/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-sourcemap\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"less\": \"^4.6.4\",\n    \"lightningcss\": \"^1.32.0\",\n    \"magic-string\": \"^0.30.21\",\n    \"sass\": \"^1.98.0\",\n    \"stylus\": \"^0.64.0\",\n    \"sugarss\": \"^5.0.1\"\n  }\n}\n"
  },
  {
    "path": "playground/css-sourcemap/vite.config-lib-entry.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    cssCodeSplit: true,\n    sourcemap: true,\n    outDir: 'dist/lib-entry',\n    lib: {\n      entry: ['./index.js', './linked.css'],\n      formats: ['es'],\n    },\n  },\n})\n"
  },
  {
    "path": "playground/css-sourcemap/vite.config-lightningcss.js",
    "content": "import { defineConfig, mergeConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nexport default mergeConfig(\n  baseConfig,\n  defineConfig({\n    css: {\n      transformer: 'lightningcss',\n    },\n  }),\n)\n"
  },
  {
    "path": "playground/css-sourcemap/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport MagicString from 'magic-string'\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': import.meta.dirname,\n    },\n  },\n  css: {\n    devSourcemap: true,\n    preprocessorOptions: {\n      less: {\n        additionalData: '@color: red;',\n      },\n      styl: {\n        additionalData: (content, filename) => {\n          const ms = new MagicString(content, { filename })\n\n          const willBeReplaced = 'blue-red-mixed'\n          const start = content.indexOf(willBeReplaced)\n          ms.overwrite(start, start + willBeReplaced.length, 'purple')\n\n          const map = ms.generateMap({ hires: 'boundary' })\n          map.file = filename\n          map.sources = [filename]\n\n          return {\n            content: ms.toString(),\n            map,\n          }\n        },\n      },\n    },\n  },\n  build: {\n    sourcemap: true,\n  },\n  plugins: [\n    {\n      name: 'virtual-html',\n      configureServer(server) {\n        server.middlewares.use(async (req, res, next) => {\n          if (req.url === '/virtual.html') {\n            const t = await server.transformIndexHtml(\n              '/virtual.html',\n              '<style> .foo { color: red; } </style> <p class=\"foo\">virtual html</p>',\n            )\n            res.setHeader('Content-Type', 'text/html')\n            res.statusCode = 200\n            res.end(t)\n            return\n          }\n          next()\n        })\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/data-uri/__tests__/data-uri.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { findAssetFile, isBuild, page } from '~utils'\n\ntest('plain', async () => {\n  expect(await page.textContent('.plain')).toBe('hi')\n})\n\ntest('base64', async () => {\n  expect(await page.textContent('.base64')).toBe('hi')\n})\n\ntest('svg data uri minify', async () => {\n  const sqdqs = await page.getByTestId('sqdqs').boundingBox()\n  const sqsdqs = await page.getByTestId('sqsdqs').boundingBox()\n  const dqsqs = await page.getByTestId('dqsqs').boundingBox()\n  const dqssqs = await page.getByTestId('dqssqs').boundingBox()\n\n  expect(sqdqs.height).toBe(100)\n  expect(sqsdqs.height).toBe(100)\n  expect(dqsqs.height).toBe(100)\n  expect(dqssqs.height).toBe(100)\n})\n\ntest.runIf(isBuild)('should compile away the import for build', async () => {\n  const file = findAssetFile('index')\n  expect(file).not.toMatch('import')\n})\n"
  },
  {
    "path": "playground/data-uri/index.html",
    "content": "<div class=\"plain\"></div>\n<div class=\"base64\"></div>\n<div class=\"comma\"></div>\n\n<script type=\"module\">\n  import msg from \"data:text/javascript, export default 'hi'\"\n  text('.plain', msg)\n\n  import base64Msg from 'data:text/javascript;base64, ZXhwb3J0IGRlZmF1bHQgJ2hpJw=='\n  text('.base64', base64Msg)\n\n  import { comma } from 'comma/foo?number=1,2,3'\n  text('.comma', comma)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n\n<script type=\"module\" src=\"./main.js\"></script>\n\n<div id=\"sqdqs\"></div>\n<div id=\"sqsdqs\"></div>\n<div id=\"dqsqs\"></div>\n<div id=\"dqssqs\"></div>\n"
  },
  {
    "path": "playground/data-uri/main.js",
    "content": "import sqdqs from './single-quote-in-double-quotes.svg'\nimport sqsdqs from './single-quotes-in-double-quotes.svg'\nimport dqsqs from './double-quote-in-single-quotes.svg'\nimport dqssqs from './double-quotes-in-single-quotes.svg'\n\ndocument.querySelector('#sqdqs').innerHTML = `\n  <img data-testid=\"sqdqs\" src=\"${sqdqs}\" class=\"sqdqs\" alt=\"load failed\" />\n`\ndocument.querySelector('#sqsdqs').innerHTML = `\n  <img data-testid=\"sqsdqs\" src=\"${sqsdqs}\" class=\"sqsdqs\" alt=\"load failed\" />\n`\n\ndocument.querySelector('#dqsqs').innerHTML = `\n  <img data-testid=\"dqsqs\" src=\"${dqsqs}\" class=\"dqsqs\" alt=\"load failed\" />\n`\ndocument.querySelector('#dqssqs').innerHTML = `\n  <img data-testid=\"dqssqs\" src=\"${dqssqs}\" class=\"dqssqs\" alt=\"load failed\" />\n`\n"
  },
  {
    "path": "playground/data-uri/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-data-uri\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/data-uri/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'post-plugin',\n      enforce: 'post',\n      resolveId(id) {\n        if (id.replace(/\\?.*$/, '') === 'comma/foo') {\n          return id\n        }\n      },\n      load(id) {\n        if (id.replace(/\\?.*$/, '') === 'comma/foo') {\n          return `export const comma = 'hi'`\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/define/__tests__/define.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport viteConfig from '../vite.config'\nimport { page } from '~utils'\n\nconst defines = viteConfig.define\nconst envDefines = viteConfig.environments.client.define\n\ntest('string', async () => {\n  expect(await page.textContent('.exp')).toBe(\n    String(typeof eval(defines.__EXP__)),\n  )\n  expect(await page.textContent('.string')).toBe(JSON.parse(defines.__STRING__))\n  expect(await page.textContent('.number')).toBe(String(defines.__NUMBER__))\n  expect(await page.textContent('.boolean')).toBe(String(defines.__BOOLEAN__))\n  expect(await page.textContent('.undefined')).toBe('')\n\n  expect(await page.textContent('.object')).toBe(\n    JSON.stringify(defines.__OBJ__, null, 2),\n  )\n  expect(await page.textContent('.process-node-env')).toBe(\n    JSON.parse(defines['process.env.NODE_ENV']),\n  )\n  expect(await page.textContent('.process-env')).toBe(\n    JSON.stringify(defines['process.env'], null, 2),\n  )\n  expect(await page.textContent('.env-var')).toBe(\n    JSON.parse(defines['process.env.SOMEVAR']),\n  )\n  expect(await page.textContent('.process-as-property')).toBe(\n    defines.__OBJ__.process.env.SOMEVAR,\n  )\n  expect(await page.textContent('.spread-object')).toBe(\n    JSON.stringify({ SOMEVAR: defines['process.env.SOMEVAR'] }),\n  )\n  expect(await page.textContent('.spread-array')).toBe(\n    JSON.stringify([...defines.__STRING__]),\n  )\n  expect(await page.textContent('.dollar-identifier')).toBe(\n    String(defines.$DOLLAR),\n  )\n  expect(await page.textContent('.unicode-identifier')).toBe(\n    String(defines.ÖUNICODE_LETTERɵ),\n  )\n  expect(await page.textContent('.no-identifier-substring')).toBe(String(true))\n  expect(await page.textContent('.no-property')).toBe(String(true))\n  // html wouldn't need to define replacement\n  expect(await page.textContent('.exp-define')).toBe('__EXP__')\n  expect(await page.textContent('.import-json')).toBe('__EXP__')\n  expect(await page.textContent('.define-in-dep')).toBe(\n    defines.__STRINGIFIED_OBJ__,\n  )\n  expect(await page.textContent('.define-in-environment')).toBe(\n    envDefines.__DEFINE_IN_ENVIRONMENT__,\n  )\n})\n\ntest('ignores constants in string literals', async () => {\n  expect(\n    await page.textContent('.ignores-string-literals .process-env-dot'),\n  ).toBe('process.env.')\n  expect(\n    await page.textContent('.ignores-string-literals .global-process-env-dot'),\n  ).toBe('global.process.env.')\n  expect(\n    await page.textContent(\n      '.ignores-string-literals .globalThis-process-env-dot',\n    ),\n  ).toBe('globalThis.process.env.')\n  expect(\n    await page.textContent('.ignores-string-literals .process-env-NODE_ENV'),\n  ).toBe('process.env.NODE_ENV')\n  expect(\n    await page.textContent(\n      '.ignores-string-literals .global-process-env-NODE_ENV',\n    ),\n  ).toBe('global.process.env.NODE_ENV')\n  expect(\n    await page.textContent(\n      '.ignores-string-literals .globalThis-process-env-NODE_ENV',\n    ),\n  ).toBe('globalThis.process.env.NODE_ENV')\n  expect(\n    await page.textContent('.ignores-string-literals .import-meta-hot'),\n  ).toBe('import' + '.meta.hot')\n})\n\ntest('replaces constants in template literal expressions', async () => {\n  expect(\n    await page.textContent(\n      '.replaces-constants-in-template-literal-expressions .process-env-dot',\n    ),\n  ).toBe(JSON.parse(defines['process.env.SOMEVAR']))\n  expect(\n    await page.textContent(\n      '.replaces-constants-in-template-literal-expressions .process-env-NODE_ENV',\n    ),\n  ).toBe('dev')\n})\n\ntest('replace constants on import.meta.env when it is a invalid json', async () => {\n  expect(\n    await page.textContent(\n      '.replace-undefined-constants-on-import-meta-env .import-meta-env-UNDEFINED',\n    ),\n  ).toBe('undefined')\n  expect(\n    await page.textContent(\n      '.replace-undefined-constants-on-import-meta-env .import-meta-env-SOME_IDENTIFIER',\n    ),\n  ).toBe('true')\n})\n\ntest('optional values are detected by pattern properly', async () => {\n  expect(await page.textContent('.optional-env')).toBe(\n    JSON.parse(defines['process.env.SOMEVAR']),\n  )\n})\n\ntest('env import with query parameters works correctly', async () => {\n  expect(await page.textContent('.env-with-query')).toBe('success')\n})\n"
  },
  {
    "path": "playground/define/commonjs-dep/index.js",
    "content": "module.exports = {\n  defined: __STRINGIFIED_OBJ__,\n}\n"
  },
  {
    "path": "playground/define/commonjs-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-commonjs-dep\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "playground/define/data.json",
    "content": "{\n  \"foo\": \"__EXP__\"\n}\n"
  },
  {
    "path": "playground/define/index.html",
    "content": "<meta charset=\"utf-8\" />\n\n<h1>Define</h1>\n\n<p>Raw Expression <code class=\"exp\"></code></p>\n<p>String <code class=\"string\"></code></p>\n<p>Number <code class=\"number\"></code></p>\n<p>Boolean <code class=\"boolean\"></code></p>\n<p>Undefined <code class=\"undefined\"></code></p>\n<p>Object <span class=\"pre object\"></span></p>\n<p>Env Var <code class=\"env-var\"></code></p>\n<p>process node env: <code class=\"process-node-env\"></code></p>\n<p>process env: <code class=\"process-env\"></code></p>\n<p>process as property: <code class=\"process-as-property\"></code></p>\n<p>spread object: <code class=\"spread-object\"></code></p>\n<p>spread array: <code class=\"spread-array\"></code></p>\n<p>dollar identifier: <code class=\"dollar-identifier\"></code></p>\n<p>unicode identifier: <code class=\"unicode-identifier\"></code></p>\n<p>no property: <code class=\"no-property\"></code></p>\n<p>no identifier substring: <span class=\"no-identifier-substring\"></span></p>\n<p>define variable in html: <code class=\"exp-define\">__EXP__</code></p>\n<p>import json: <code class=\"import-json\"></code></p>\n<p>define in dep: <code class=\"define-in-dep\"></code></p>\n<p>define in environment: <code class=\"define-in-environment\"></code></p>\n\n<h2>Define ignores string literals</h2>\n<section class=\"ignores-string-literals\">\n  <p>process.env. <code class=\"process-env-dot\"></code></p>\n  <p>global.process.env. <code class=\"global-process-env-dot\"></code></p>\n  <p>\n    globalThis.process.env. <code class=\"globalThis-process-env-dot\"></code>\n  </p>\n  <p>process.env.NODE_ENV <code class=\"process-env-NODE_ENV\"></code></p>\n  <p>\n    global.process.env.NODE_ENV\n    <code class=\"global-process-env-NODE_ENV\"></code>\n  </p>\n  <p>\n    globalThis.process.env.NODE_ENV\n    <code class=\"globalThis-process-env-NODE_ENV\"></code>\n  </p>\n  <p>import.meta.hot <code class=\"import-meta-hot\"></code></p>\n</section>\n\n<h2>Define replaces constants in template literal expressions</h2>\n<section class=\"replaces-constants-in-template-literal-expressions\">\n  <p>process.env. <code class=\"process-env-dot\"></code></p>\n  <p>global.process.env. <code class=\"global-process-env-dot\"></code></p>\n  <p>\n    globalThis.process.env. <code class=\"globalThis-process-env-dot\"></code>\n  </p>\n  <p>process.env.NODE_ENV <code class=\"process-env-NODE_ENV\"></code></p>\n  <p>\n    global.process.env.NODE_ENV\n    <code class=\"global-process-env-NODE_ENV\"></code>\n  </p>\n  <p>\n    globalThis.process.env.NODE_ENV\n    <code class=\"globalThis-process-env-NODE_ENV\"></code>\n  </p>\n  <p>import.meta.hot <code class=\"import-meta-hot\"></code></p>\n</section>\n\n<h2>Define undefined constants on import.meta.env when it's a invalid json</h2>\n<section class=\"replace-undefined-constants-on-import-meta-env\">\n  <p>\n    import.meta.env.UNDEFINED <code class=\"import-meta-env-UNDEFINED\"></code>\n  </p>\n  <p>\n    import.meta.env.SOME_IDENTIFIER\n    <code class=\"import-meta-env-SOME_IDENTIFIER\"></code>\n  </p>\n</section>\n\n<h2>Optional values are detected by pattern properly</h2>\n<p>\n  process?.env?.SOMEVAR\n  <code class=\"optional-env\"></code>\n</p>\n\n<h2>Env import with query parameters works correctly</h2>\n<p>\n  /@vite/env?foo should be transformed\n  <code class=\"env-with-query\"></code>\n</p>\n\n<script>\n  // inject __VITE_SOME_IDENTIFIER__ to test if it's replaced\n  window.__VITE_SOME_IDENTIFIER__ = true\n</script>\n<script type=\"module\">\n  const __VAR_NAME__ = true // ensure define doesn't replace var name\n  text('.exp', typeof __EXP__) // typeof __EXP__ would be `boolean` instead of `string`\n  text('.string', __STRING__)\n  text('.number', __NUMBER__)\n  text('.boolean', __BOOLEAN__)\n  text('.undefined', __UNDEFINED__)\n  text('.object', JSON.stringify(__OBJ__, null, 2))\n  text('.process-node-env', process.env.NODE_ENV)\n  text('.process-env', JSON.stringify(process.env, null, 2))\n  text('.env-var', process.env.SOMEVAR)\n  text('.process-as-property', __OBJ__.process.env.SOMEVAR)\n  text(\n    '.spread-object',\n    JSON.stringify({\n      ...(process.env.SOMEVAR ? { SOMEVAR: `\"${process.env.SOMEVAR}\"` } : {}),\n    }),\n  )\n  text('.spread-array', JSON.stringify([...`\"${__STRING__}\"`]))\n  text('.dollar-identifier', $DOLLAR)\n  text('.unicode-identifier', ÖUNICODE_LETTERɵ)\n\n  // make sure these kinds of use are NOT replaced:\n  const obj = { [`${'_'}_EXP__`]: true }\n  text('.no-property', obj.__EXP__)\n\n  window[`${'_'}_EXP__SUBSTR__`] = true\n  text('.no-identifier-substring', __EXP__SUBSTR__)\n\n  import dataJson from './data.json'\n  text('.import-json', dataJson.foo)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n\n  import { defined } from '@vitejs/test-commonjs-dep'\n  text('.define-in-dep', JSON.stringify(defined))\n\n  text('.define-in-environment', JSON.stringify(__DEFINE_IN_ENVIRONMENT__))\n\n  text('.ignores-string-literals .process-env-dot', 'process.env.')\n  text(\n    '.ignores-string-literals .global-process-env-dot',\n    'global.process.env.',\n  )\n  text(\n    '.ignores-string-literals .globalThis-process-env-dot',\n    'globalThis.process.env.',\n  )\n  text('.ignores-string-literals .process-env-NODE_ENV', 'process.env.NODE_ENV')\n  text(\n    '.ignores-string-literals .global-process-env-NODE_ENV',\n    'global.process.env.NODE_ENV',\n  )\n  text(\n    '.ignores-string-literals .globalThis-process-env-NODE_ENV',\n    'globalThis.process.env.NODE_ENV',\n  )\n  text('.ignores-string-literals .import-meta-hot', 'import.meta.hot')\n\n  text(\n    '.replaces-constants-in-template-literal-expressions .process-env-dot',\n    `${process.env.SOMEVAR}`,\n  )\n  text(\n    '.replaces-constants-in-template-literal-expressions .process-env-NODE_ENV',\n    `${process.env.NODE_ENV}`,\n  )\n\n  text(\n    '.replace-undefined-constants-on-import-meta-env .import-meta-env-UNDEFINED',\n    `${import.meta.env.UNDEFINED}`,\n  )\n  text(\n    '.replace-undefined-constants-on-import-meta-env .import-meta-env-SOME_IDENTIFIER',\n    `${import.meta.env.SOME_IDENTIFIER}`,\n  )\n\n  import optionalEnv from './optional-env.js'\n  text('.optional-env', optionalEnv)\n\n  // replaced by a plugin\n  import(__VITE_ENV_WITH_QUERY__)\n    .then(() => {\n      text('.env-with-query', 'success')\n    })\n    .catch((err) => {\n      text('.env-with-query', `error: ${err.message}`)\n    })\n</script>\n\n<style>\n  .pre {\n    display: block;\n    unicode-bidi: embed;\n    font-family: monospace;\n    white-space: pre;\n  }\n</style>\n"
  },
  {
    "path": "playground/define/optional-env.js",
    "content": "// separate file to test pattern filter\nexport default process?.env?.SOMEVAR\n"
  },
  {
    "path": "playground/define/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-define\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-commonjs-dep\": \"file:./commonjs-dep\"\n  }\n}\n"
  },
  {
    "path": "playground/define/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\n/**\n * Plugin to test that env imports with query parameters work correctly (#20997)\n */\nfunction testEnvQueryParamsPlugin() {\n  let isBuild = true\n  return {\n    name: 'test-env-query-params',\n    configResolved(config) {\n      isBuild = config.command === 'build'\n    },\n    transform(code, id) {\n      if (\n        id.includes('index.html') &&\n        code.includes('__VITE_ENV_WITH_QUERY__')\n      ) {\n        return code.replace(\n          '__VITE_ENV_WITH_QUERY__',\n          JSON.stringify(isBuild ? 'data:text/javascript,' : '/@vite/env?foo'),\n        )\n      }\n    },\n  }\n}\n\nexport default defineConfig({\n  plugins: [testEnvQueryParamsPlugin()],\n  define: {\n    __EXP__: 'false',\n    __STRING__: '\"hello\"',\n    __NUMBER__: 123,\n    __BOOLEAN__: true,\n    __UNDEFINED__: undefined,\n    __OBJ__: {\n      foo: 1,\n      bar: {\n        baz: 2,\n      },\n      process: {\n        env: {\n          SOMEVAR: '\"PROCESS MAY BE PROPERTY\"',\n        },\n      },\n    },\n    'process.env.NODE_ENV': '\"dev\"',\n    'process.env.SOMEVAR': '\"SOMEVAR\"',\n    'process.env': {\n      NODE_ENV: 'dev',\n      SOMEVAR: 'SOMEVAR',\n      OTHER: 'works',\n    },\n    $DOLLAR: 456,\n    ÖUNICODE_LETTERɵ: 789,\n    __VAR_NAME__: false,\n    __STRINGIFIED_OBJ__: JSON.stringify({ foo: true }),\n    'import.meta.env.SOME_IDENTIFIER': '__VITE_SOME_IDENTIFIER__',\n  },\n  environments: {\n    client: {\n      define: {\n        __DEFINE_IN_ENVIRONMENT__: '\"defined only in client\"',\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/devtools/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>DevTools</title>\n  </head>\n\n  <body>\n    <div id=\"app\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/devtools/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-devtools\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.5.30\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"workspace:*\",\n    \"@vitejs/devtools\": \"^0.1.0\"\n  }\n}\n"
  },
  {
    "path": "playground/devtools/src/counter.ts",
    "content": "import { ref } from 'vue'\n\nexport function useCounter() {\n  const count = ref(0)\n\n  function increment() {\n    count.value++\n  }\n\n  function decrement() {\n    count.value--\n  }\n\n  return {\n    count,\n    increment,\n    decrement,\n  }\n}\n"
  },
  {
    "path": "playground/devtools/src/main.ts",
    "content": "import { watchEffect } from 'vue'\nimport { useCounter } from './counter'\n\nconst { count, increment, decrement } = useCounter()\n\nwatchEffect(() => {\n  document.querySelector('#app')!.textContent = `${count.value}`\n})\n\nconst timer = setInterval(() => {\n  if (count.value < 6) {\n    increment()\n  } else {\n    decrement()\n    clearInterval(timer)\n  }\n}, 1000)\n"
  },
  {
    "path": "playground/devtools/vite.config.ts",
    "content": "// no test exists, this should be tested manually\n\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  base: '/',\n  devtools: {\n    enabled: false,\n    port: 5173,\n  },\n})\n"
  },
  {
    "path": "playground/dynamic-import/(app)/main.js",
    "content": "export function hello() {\n  return 'dynamic-import-with-vars-contains-parenthesis'\n}\n"
  },
  {
    "path": "playground/dynamic-import/(app)/nest/index.js",
    "content": "const base = 'main'\nimport(`../${base}.js`).then((mod) => {\n  document.querySelector(\n    '.dynamic-import-with-vars-contains-parenthesis',\n  ).textContent = mod.hello()\n})\n"
  },
  {
    "path": "playground/dynamic-import/__tests__/dynamic-import.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport {\n  browserLogs,\n  findAssetFile,\n  getColor,\n  isBuild,\n  page,\n  serverLogs,\n} from '~utils'\n\ntest('should load literal dynamic import', async () => {\n  await page.click('.baz')\n  await expect.poll(() => page.textContent('.view')).toMatch('Baz view')\n})\n\ntest('should load full dynamic import from public', async () => {\n  await page.click('.qux')\n  await expect.poll(() => page.textContent('.view')).toMatch('Qux view')\n  // No warning should be logged as we are using @vite-ignore\n  expect(\n    serverLogs.some((log) => log.includes('cannot be analyzed by vite')),\n  ).toBe(false)\n})\n\ntest('should load data URL of `blob:`', async () => {\n  await page.click('.issue-2658-1')\n  await expect.poll(() => page.textContent('.view')).toMatch('blob')\n})\n\ntest('should load data URL of `data:`', async () => {\n  await page.click('.issue-2658-2')\n  await expect.poll(() => page.textContent('.view')).toMatch('data')\n})\n\ntest('should have same reference on static and dynamic js import, .mxd', async () => {\n  await page.click('.mxd')\n  await expect.poll(() => page.textContent('.view')).toMatch('true')\n})\n\n// in this case, it is not possible to detect the correct module\ntest('should have same reference on static and dynamic js import, .mxd2', async () => {\n  await page.click('.mxd2')\n  await expect.poll(() => page.textContent('.view')).toMatch('false')\n})\n\ntest('should have same reference on static and dynamic js import, .mxdjson', async () => {\n  await page.click('.mxdjson')\n  await expect.poll(() => page.textContent('.view')).toMatch('true')\n})\n\n// since this test has a timeout, it should be put last so that it\n// does not bleed on the last\ntest('should load dynamic import with vars', async () => {\n  await page.click('.foo')\n  await expect.poll(() => page.textContent('.view')).toMatch('Foo view')\n\n  await page.click('.bar')\n  await expect.poll(() => page.textContent('.view')).toMatch('Bar view')\n})\n\n// dynamic import css\ntest('should load dynamic import with css', async () => {\n  await page.click('.css')\n  await expect.poll(() => getColor('.view')).toBe('red')\n})\n\ntest('should load dynamic import with vars', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars'))\n    .toMatch('hello')\n})\n\ntest('should load dynamic import with vars ignored', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars-ignored'))\n    .toMatch('hello')\n  // No warning should be logged as we are using @vite-ignore\n  expect(\n    serverLogs.some((log) =>\n      log.includes('\"https\" has been externalized for browser compatibility'),\n    ),\n  ).toBe(false)\n})\n\ntest('should load dynamic import with double slash ignored', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-double-slash-ignored'))\n    .toMatch('hello')\n})\n\ntest('should load dynamic import with vars multiline', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars-multiline'))\n    .toMatch('hello')\n})\n\ntest('should load dynamic import with vars alias', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars-alias'))\n    .toMatch('hi')\n})\n\ntest('should load dynamic import with vars raw', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars-raw'))\n    .toMatch('export function hello()')\n})\n\ntest('should load dynamic import with vars url', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars-url'))\n    .toMatch(isBuild ? 'data:text/javascript' : '/alias/url.js')\n})\n\ntest('should load dynamic import with vars worker', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-with-vars-worker'))\n    .toMatch('load worker')\n})\n\ntest('should load dynamic import with css in package', async () => {\n  await page.click('.pkg-css')\n  await expect.poll(() => getColor('.pkg-css')).toBe('blue')\n})\n\ntest('should work with load ../ and itself directory', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-self'))\n    .toMatch('dynamic-import-self-content')\n})\n\ntest('should work with load ../ and contain itself directory', async () => {\n  await expect\n    .poll(() => page.textContent('.dynamic-import-nested-self'))\n    .toMatch('dynamic-import-nested-self-content')\n})\n\ntest('should work a load path that contains parentheses.', async () => {\n  await expect\n    .poll(() =>\n      page.textContent('.dynamic-import-with-vars-contains-parenthesis'),\n    )\n    .toMatch('dynamic-import-with-vars-contains-parenthesis')\n})\n\ntest.runIf(isBuild)(\n  'should rollup warn when static and dynamic import a module in same chunk',\n  // NOTE: this is a warning related to rollup's chunking behavior\n  { skip: true },\n  async () => {\n    const log = serverLogs.join('\\n')\n    expect(log).toContain(\n      'dynamic import will not move module into another chunk',\n    )\n    expect(log).toMatch(\n      /\\(!\\).*\\/dynamic-import\\/files\\/mxd\\.js is dynamically imported by/,\n    )\n    expect(log).toMatch(\n      /\\(!\\).*\\/dynamic-import\\/files\\/mxd\\.json is dynamically imported by/,\n    )\n    expect(log).not.toMatch(\n      /\\(!\\).*\\/dynamic-import\\/nested\\/shared\\.js is dynamically imported by/,\n    )\n  },\n)\n\ntest('dynamic import treeshaken log', async () => {\n  const log = browserLogs.join('\\n')\n  expect(log).toContain('treeshaken foo')\n  expect(log).toContain('treeshaken bar')\n  expect(log).toContain('treeshaken baz1')\n  expect(log).toContain('treeshaken baz2')\n  expect(log).toContain('treeshaken baz3')\n  expect(log).toContain('treeshaken baz4')\n  expect(log).toContain('treeshaken baz5')\n  expect(log).toContain('treeshaken baz6')\n  expect(log).toContain('treeshaken default')\n\n  expect(log).not.toContain('treeshaken removed')\n})\n\ntest('dynamic import syntax parsing', async () => {\n  const log = browserLogs.join('\\n')\n  expect(log).toContain('treeshaken syntax foo')\n  expect(log).toContain('treeshaken syntax default')\n})\n\ntest.runIf(isBuild)('dynamic import treeshaken file', async () => {\n  expect(findAssetFile(/treeshaken.+\\.js$/)).not.toContain('treeshaken removed')\n})\n\ntest.runIf(isBuild)('should not preload for non-analyzable urls', () => {\n  const js = findAssetFile(/index-[-\\w]{8}\\.js$/)\n  // should match e.g. await import(e.jss);o(\".view\",p===i)\n  expect(js).to.match(/\\.jss\\);/)\n})\n"
  },
  {
    "path": "playground/dynamic-import/alias/hello.js",
    "content": "export function hello() {\n  return 'hello'\n}\nconsole.log('hello.js')\n"
  },
  {
    "path": "playground/dynamic-import/alias/hi.js",
    "content": "export function hi() {\n  return 'hi'\n}\nconsole.log('hi.js')\n"
  },
  {
    "path": "playground/dynamic-import/alias/url.js",
    "content": "export const url = 'load url'\n"
  },
  {
    "path": "playground/dynamic-import/alias/worker.js",
    "content": "self.onmessage = (event) => {\n  self.postMessage({\n    msg: 'load worker',\n  })\n}\n"
  },
  {
    "path": "playground/dynamic-import/css/index.css",
    "content": ".css {\n  box-sizing: border-box;\n}\n.view {\n  color: red;\n}\n"
  },
  {
    "path": "playground/dynamic-import/files/mxd.js",
    "content": "export default function () {}\n"
  },
  {
    "path": "playground/dynamic-import/files/mxd.json",
    "content": "{}\n"
  },
  {
    "path": "playground/dynamic-import/index.html",
    "content": "<button class=\"foo\">Foo</button>\n<button class=\"bar\">Bar</button>\n<button class=\"baz\">Baz</button>\n<button class=\"qux\">Qux</button>\n<button class=\"mxd\">Mxd</button>\n<button class=\"mxd2\">Mxd2</button>\n<button class=\"mxdjson\">Mxdjson</button>\n<button class=\"issue-2658-1\">Issue 2658 - 1</button>\n<button class=\"issue-2658-2\">Issue 2658 - 2</button>\n<button class=\"css\">css</button>\n<button class=\"pkg-css\">pkg-css</button>\n\n<p>dynamic-import-with-vars</p>\n<div class=\"dynamic-import-with-vars\">todo</div>\n\n<p>dynamic-import-with-vars-ignored</p>\n<div class=\"dynamic-import-with-vars-ignored\">todo</div>\n\n<p>dynamic-import-with-double-slash-ignored</p>\n<div class=\"dynamic-import-with-double-slash-ignored\">todo</div>\n\n<p>dynamic-import-with-vars-multiline</p>\n<div class=\"dynamic-import-with-vars-multiline\">todo</div>\n\n<p>dynamic-import-with-vars-alias</p>\n<div class=\"dynamic-import-with-vars-alias\">todo</div>\n\n<p>dynamic-import-with-vars-raw</p>\n<div class=\"dynamic-import-with-vars-raw\">todo</div>\n\n<p>dynamic-import-with-vars-url</p>\n<div class=\"dynamic-import-with-vars-url\">todo</div>\n\n<p>dynamic-import-with-vars-worker</p>\n<div class=\"dynamic-import-with-vars-worker\">todo</div>\n\n<p>dynamic-import-with-vars-contains-parenthesis</p>\n<div class=\"dynamic-import-with-vars-contains-parenthesis\">todo</div>\n\n<div class=\"view\"></div>\n\n<div class=\"dynamic-import-self\"></div>\n\n<div class=\"dynamic-import-static\"></div>\n\n<div class=\"dynamic-import-nested-self\"></div>\n\n<script type=\"module\" src=\"./nested/index.js\"></script>\n<script type=\"module\" src=\"./(app)/nest/index.js\"></script>\n<style>\n  p {\n    color: #0088ff;\n  }\n</style>\n"
  },
  {
    "path": "playground/dynamic-import/nested/deps.js",
    "content": "/* don't include dynamic import inside this file */\n\nimport '@vitejs/test-pkg'\n"
  },
  {
    "path": "playground/dynamic-import/nested/hello.js",
    "content": "export function hello() {\n  return 'hello'\n}\n"
  },
  {
    "path": "playground/dynamic-import/nested/index.js",
    "content": "import mxdStatic from '../files/mxd'\nimport mxdStaticJSON from '../files/mxd.json'\n\nasync function setView(view) {\n  const { msg } = await import(`../views/${view}.js`)\n  text('.view', msg)\n}\n\n;['foo', 'bar'].forEach((id) => {\n  document.querySelector(`.${id}`).addEventListener('click', () => setView(id))\n})\n\n// literal dynamic\ndocument.querySelector('.baz').addEventListener('click', async () => {\n  const { msg } = await import('../views/baz.js')\n  text('.view', msg)\n})\n\n// full dynamic\nconst arr = ['qux.js']\nconst view = `/views/${arr[0]}`\ndocument.querySelector('.qux').addEventListener('click', async () => {\n  const { msg } = await import(/*@vite-ignore*/ view)\n  text('.view', msg)\n})\n\n// mixed static and dynamic\ndocument.querySelector('.mxd').addEventListener('click', async () => {\n  const view = 'mxd'\n  const { default: mxdDynamic } = await import(`../files/${view}.js`)\n  text('.view', mxdStatic === mxdDynamic)\n})\n\ndocument.querySelector('.mxd2').addEventListener('click', async () => {\n  const test = { jss: '../files/mxd.js' }\n  const ttest = test\n  const view = 'mxd'\n  const { default: mxdDynamic } = await import(/*@vite-ignore*/ test.jss)\n  text('.view', mxdStatic === mxdDynamic)\n})\n\ndocument.querySelector('.mxdjson').addEventListener('click', async () => {\n  const view = 'mxd'\n  const { default: mxdDynamicJSON } = await import(`../files/${view}.json`)\n  text('.view', mxdStaticJSON === mxdDynamicJSON)\n})\n\n// data URLs (`blob:`)\nconst code1 = 'export const msg = \"blob\"'\nconst blob = new Blob([code1], { type: 'text/javascript;charset=UTF-8' })\nconst blobURL = URL.createObjectURL(blob)\ndocument.querySelector('.issue-2658-1').addEventListener('click', async () => {\n  const { msg } = await import(/*@vite-ignore*/ blobURL)\n  text('.view', msg)\n})\n\n// data URLs (`data:`)\nconst code2 = 'export const msg = \"data\";'\nconst dataURL = `data:text/javascript;charset=utf-8,${encodeURIComponent(\n  code2,\n)}`\ndocument.querySelector('.issue-2658-2').addEventListener('click', async () => {\n  const { msg } = await import(/*@vite-ignore*/ dataURL)\n  text('.view', msg)\n})\n\ndocument.querySelector('.css').addEventListener('click', async () => {\n  await import('../css/index.css')\n  text('.view', 'dynamic import css')\n})\n\ndocument.querySelector('.pkg-css').addEventListener('click', async () => {\n  await import('./deps')\n  text('.view', 'dynamic import css in package')\n})\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nlet base = 'hello'\n\nimport(`../alias/${base}.js`).then((mod) => {\n  text('.dynamic-import-with-vars', mod.hello())\n})\n\nimport(/*@vite-ignore*/ `https://localhost`).catch((mod) => {\n  console.log(mod)\n  text('.dynamic-import-with-vars-ignored', 'hello')\n})\n\nimport(/*@vite-ignore*/ `https://localhost//${'test'}`).catch((mod) => {\n  console.log(mod)\n  text('.dynamic-import-with-double-slash-ignored', 'hello')\n})\n\n// prettier-ignore\nimport(\n  /* this messes with */\n  `../alias/${base}.js`\n  /* es-module-lexer */\n).then((mod) => {\n  text('.dynamic-import-with-vars-multiline', mod.hello())\n})\n\nimport(`../alias/${base}.js?raw`).then((mod) => {\n  text('.dynamic-import-with-vars-raw', JSON.stringify(mod))\n})\n\nbase = 'url'\nimport(`../alias/${base}.js?url`).then((mod) => {\n  text('.dynamic-import-with-vars-url', JSON.stringify(mod))\n})\n\nbase = 'worker'\nimport(`../alias/${base}.js?worker`).then((workerMod) => {\n  const worker = new workerMod.default()\n  worker.postMessage('1')\n  worker.addEventListener('message', (ev) => {\n    console.log(ev)\n    text('.dynamic-import-with-vars-worker', JSON.stringify(ev.data))\n  })\n})\n\nbase = 'hi'\nimport(`@/${base}.js`).then((mod) => {\n  text('.dynamic-import-with-vars-alias', mod.hi())\n})\n\nbase = 'self'\nimport(`../nested/${base}.js`).then((mod) => {\n  text('.dynamic-import-self', mod.self)\n})\n\nimport(`../nested/nested/${base}.js`).then((mod) => {\n  text('.dynamic-import-nested-self', mod.self)\n})\n;(async function () {\n  const { foo } = await import('./treeshaken/treeshaken.js')\n  const { bar, default: tree } = await import('./treeshaken/treeshaken.js')\n  const default2 = (await import('./treeshaken/treeshaken.js')).default\n  const baz1 = (await import('./treeshaken/treeshaken.js')).baz1\n  const baz2 = (await import('./treeshaken/treeshaken.js')).baz2.log\n  const baz3 = (await import('./treeshaken/treeshaken.js')).baz3?.log\n  const baz4 = await import('./treeshaken/treeshaken.js').then(\n    ({ baz4 }) => baz4,\n  )\n  const baz5 = await import('./treeshaken/treeshaken.js').then(function ({\n      baz5,\n    }) {\n      return baz5\n    }),\n    { baz6 } = await import('./treeshaken/treeshaken.js')\n  foo()\n  bar()\n  tree()\n  ;(await import('./treeshaken/treeshaken.js')).default()\n  default2()\n  baz1()\n  baz2()\n  baz3()\n  baz4()\n  baz5()\n  baz6()\n})()\n// Test syntax parsing only\n;(async function () {\n  const default1 = await import('./treeshaken/syntax.js').then(\n    (mod) => mod.default,\n  )\n  const default2 = (await import('./treeshaken/syntax.js')).default,\n    other = () => {}\n  const foo = await import('./treeshaken/syntax.js').then((mod) => mod.foo)\n  const foo2 = await import('./treeshaken/syntax.js').then(\n    ({ foo = {} }) => foo,\n  )\n  const foo3 = await import('./treeshaken/syntax.js').then((m) => m.foo)\n  const e = ('' + window.doesntExist)[3] // to disallow minifier to constant fold\n  const foo4 = await import('./treeshaken/syntax.js')[`th${e}n`]((m) => m.foo)\n  await import('./treeshaken/syntax.js').then((mod) => mod.foo({ foo }))\n  const obj = [\n    '',\n    {\n      async lazy() {\n        const { foo } = await import('./treeshaken/treeshaken.js')\n        return { foo: aaa(foo) }\n      },\n    },\n  ]\n  default1()\n  default2()\n  other()\n  foo()\n  foo2()\n  foo3()\n  foo4()\n  obj[1].lazy()\n})()\n\nimport(`../nested/static.js`).then((mod) => {\n  text('.dynamic-import-static', mod.self)\n})\n\nconsole.log('index.js')\n"
  },
  {
    "path": "playground/dynamic-import/nested/nested/self.js",
    "content": "export const self = 'dynamic-import-nested-self-content'\n"
  },
  {
    "path": "playground/dynamic-import/nested/self.js",
    "content": "export const self = 'dynamic-import-self-content'\n"
  },
  {
    "path": "playground/dynamic-import/nested/shared.js",
    "content": "export const n = 1\n"
  },
  {
    "path": "playground/dynamic-import/nested/static.js",
    "content": "export const self = 'dynamic-import-static'\n"
  },
  {
    "path": "playground/dynamic-import/nested/treeshaken/syntax.js",
    "content": "export const foo = () => {\n  console.log('treeshaken syntax foo')\n}\nexport default () => {\n  console.log('treeshaken syntax default')\n}\n"
  },
  {
    "path": "playground/dynamic-import/nested/treeshaken/treeshaken.js",
    "content": "export const foo = () => {\n  console.log('treeshaken foo')\n}\nexport const bar = () => {\n  console.log('treeshaken bar')\n}\nexport const baz1 = () => {\n  console.log('treeshaken baz1')\n}\nexport const baz2 = {\n  log: () => {\n    console.log('treeshaken baz2')\n  },\n}\nexport const baz3 = {\n  log: () => {\n    console.log('treeshaken baz3')\n  },\n}\nexport const baz4 = () => {\n  console.log('treeshaken baz4')\n}\nexport const baz5 = () => {\n  console.log('treeshaken baz5')\n}\nexport const baz6 = () => {\n  console.log('treeshaken baz6')\n}\nexport const removed = () => {\n  console.log('treeshaken removed')\n}\nexport default () => {\n  console.log('treeshaken default')\n}\n"
  },
  {
    "path": "playground/dynamic-import/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dynamic-import\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-pkg\": \"file:./pkg\"\n  }\n}\n"
  },
  {
    "path": "playground/dynamic-import/pkg/index.js",
    "content": "import('./pkg.css')\n"
  },
  {
    "path": "playground/dynamic-import/pkg/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-pkg\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/dynamic-import/pkg/pkg.css",
    "content": ".pkg-css {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/dynamic-import/views/bar.js",
    "content": "export const msg = 'Bar view'\n"
  },
  {
    "path": "playground/dynamic-import/views/baz.js",
    "content": "import { n } from '../nested/shared'\nconsole.log('baz' + n)\n\nexport const msg = 'Baz view'\n"
  },
  {
    "path": "playground/dynamic-import/views/foo.js",
    "content": "import { n } from '../nested/shared'\nconsole.log('foo' + n)\n\nexport const msg = 'Foo view'\n"
  },
  {
    "path": "playground/dynamic-import/views/qux.js",
    "content": "export const msg = 'Qux view'\n"
  },
  {
    "path": "playground/dynamic-import/vite.config.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst dirname = import.meta.dirname\n\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'copy',\n      writeBundle() {\n        fs.mkdirSync(path.resolve(dirname, 'dist/views'))\n        fs.mkdirSync(path.resolve(dirname, 'dist/files'))\n        fs.copyFileSync(\n          path.resolve(dirname, 'views/qux.js'),\n          path.resolve(dirname, 'dist/views/qux.js'),\n        )\n        fs.copyFileSync(\n          path.resolve(dirname, 'files/mxd.js'),\n          path.resolve(dirname, 'dist/files/mxd.js'),\n        )\n        fs.copyFileSync(\n          path.resolve(dirname, 'files/mxd.json'),\n          path.resolve(dirname, 'dist/files/mxd.json'),\n        )\n      },\n    },\n  ],\n  resolve: {\n    alias: {\n      '@': path.resolve(dirname, 'alias'),\n    },\n  },\n  build: {\n    sourcemap: true,\n  },\n})\n"
  },
  {
    "path": "playground/dynamic-import-inline/__tests__/dynamic-import-inline.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, serverLogs } from '~utils'\n\ntest.runIf(isBuild)(\n  \"don't warn when codeSplitting is set to false\",\n  async () => {\n    const log = serverLogs.join('\\n')\n    expect(log).not.toContain(\n      'dynamic import will not move module into another chunk',\n    )\n  },\n)\n"
  },
  {
    "path": "playground/dynamic-import-inline/index.html",
    "content": "<script type=\"module\" src=\"./src/index.js\"></script>\n"
  },
  {
    "path": "playground/dynamic-import-inline/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dynamic-import-inline\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/dynamic-import-inline/src/foo.js",
    "content": "export default function foo() {\n  return 'foo'\n}\n"
  },
  {
    "path": "playground/dynamic-import-inline/src/index.js",
    "content": "import foo from './foo'\n\nconst asyncImport = async () => {\n  const { foo } = await import('./foo.js')\n  foo()\n}\n\nfoo()\nasyncImport()\n"
  },
  {
    "path": "playground/dynamic-import-inline/vite.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '@': path.resolve(import.meta.dirname, 'alias'),\n    },\n  },\n  build: {\n    sourcemap: true,\n    rollupOptions: {\n      output: {\n        codeSplitting: false,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/env/__tests__/env.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page } from '~utils'\n\nconst mode = isBuild ? `production` : `development`\n\ntest('base', async () => {\n  expect(await page.textContent('.base')).toBe('/env/')\n})\n\ntest('mode', async () => {\n  expect(await page.textContent('.mode')).toBe(mode)\n})\n\ntest('dev', async () => {\n  expect(await page.textContent('.dev')).toBe(String(!isBuild))\n})\n\ntest('prod', async () => {\n  expect(await page.textContent('.prod')).toBe(String(isBuild))\n})\n\ntest('custom', async () => {\n  expect(await page.textContent('.custom')).toBe('1')\n})\n\ntest('custom in template literal expression', async () => {\n  expect(await page.textContent('.custom-template-literal-exp')).toBe('1')\n})\n\ntest('custom-prefix', async () => {\n  expect(await page.textContent('.custom-prefix')).toBe('1')\n})\n\ntest('mode file override', async () => {\n  expect(await page.textContent('.mode-file')).toBe(`.env.${mode}`)\n})\n\ntest('inline variables', async () => {\n  expect(await page.textContent('.inline')).toBe(\n    isBuild ? `inline-build` : `inline-serve`,\n  )\n})\n\ntest('define', async () => {\n  expect(await page.textContent('.bool')).toBe('boolean')\n  expect(await page.textContent('.number')).toBe('number')\n  expect(await page.textContent('.string')).toBe('string')\n  expect(await page.textContent('.stringify-object')).toBe('object')\n})\n\ntest('NODE_ENV', async () => {\n  expect(await page.textContent('.node-env')).toBe(process.env.NODE_ENV)\n  expect(await page.textContent('.global-node-env')).toBe(process.env.NODE_ENV)\n  expect(await page.textContent('.global-this-node-env')).toBe(\n    process.env.NODE_ENV,\n  )\n})\n\ntest('expand', async () => {\n  expect(await page.textContent('.expand-a')).toBe('expand')\n  expect(await page.textContent('.expand-b')).toBe('depend')\n})\n\ntest('ssr', async () => {\n  expect(await page.textContent('.ssr')).toBe('false')\n})\n\ntest('env object', async () => {\n  const env = JSON.parse(await page.textContent('.env-object'))\n  expect(env).not.toHaveProperty([\n    'DEPEND_ENV',\n    'IRRELEVANT_ENV',\n    'IRRELEVANT_ESCAPE_ENV',\n  ])\n  expect(env).toMatchObject({\n    VITE_EFFECTIVE_MODE_FILE_NAME: `.env.${mode}`,\n    CUSTOM_PREFIX_ENV_VARIABLE: '1',\n    VITE_CUSTOM_ENV_VARIABLE: '1',\n    VITE_EXPAND_A: 'expand',\n    VITE_EXPAND_B: 'depend',\n    VITE_ESCAPE_A: 'escape$',\n    VITE_ESCAPE_B: 'escape$',\n    BASE_URL: '/env/',\n    VITE_BOOL: true,\n    SSR: false,\n    MODE: mode,\n    DEV: !isBuild,\n    PROD: isBuild,\n    VITE_NUMBER: 123,\n    VITE_STRING: '{\"123\",}',\n    VITE_STRINGIFY_OBJECT: {\n      a: '1',\n      b: '2',\n    },\n  })\n})\n\ntest('env object in template literal expression', async () => {\n  const envText = await page.textContent('.env-object-in-template-literal-exp')\n  expect(JSON.parse(envText)).toMatchObject({\n    VITE_EFFECTIVE_MODE_FILE_NAME: `.env.${mode}`,\n    CUSTOM_PREFIX_ENV_VARIABLE: '1',\n    VITE_CUSTOM_ENV_VARIABLE: '1',\n    BASE_URL: '/env/',\n    MODE: mode,\n    DEV: !isBuild,\n    PROD: isBuild,\n  })\n})\n\nif (!isBuild) {\n  test('relative url import script return import.meta.url', async () => {\n    expect(await page.textContent('.url')).toMatch('/env/index.js')\n  })\n}\n\ntest('ignores import' + '.meta.env in string literals', async () => {\n  expect(await page.textContent('.ignores-literal-import-meta-env-dot')).toBe(\n    'import' + '.meta.env.',\n  )\n  expect(await page.textContent('.ignores-literal-import-meta-env')).toBe(\n    'import' + '.meta.env',\n  )\n})\n"
  },
  {
    "path": "playground/env/index.html",
    "content": "<h1>Environment Variables</h1>\n<p>import.meta.env.BASE_URL: <code class=\"base\"></code></p>\n<p>import.meta.env.MODE: <code class=\"mode\"></code></p>\n<p>import.meta.env.DEV: <code class=\"dev\"></code></p>\n<p>import.meta.env.PROD: <code class=\"prod\"></code></p>\n<p>import.meta.env.VITE_CUSTOM_ENV_VARIABLE: <code class=\"custom\"></code></p>\n<p>\n  ${import.meta.env.VITE_CUSTOM_ENV_VARIABLE}:\n  <code class=\"custom-template-literal-exp\"></code>\n</p>\n<p>\n  import.meta.env.CUSTOM_PREFIX_ENV_VARIABLE:\n  <code class=\"custom-prefix\"></code>\n</p>\n<p>\n  import.meta.env.VITE_EFFECTIVE_MODE_FILE_NAME: <code class=\"mode-file\"></code>\n</p>\n<p>import.meta.env.VITE_INLINE: <code class=\"inline\"></code></p>\n<p>typeof import.meta.env.VITE_BOOL: <code class=\"bool\"></code></p>\n<p>typeof import.meta.env.VITE_NUMBER: <code class=\"number\"></code></p>\n<p>typeof import.meta.env.VITE_STRING: <code class=\"string\"></code></p>\n<p>\n  typeof import.meta.env.VITE_STRINGIFY_OBJECT:\n  <code class=\"stringify-object\"></code>\n</p>\n<p>process.env.NODE_ENV: <code class=\"node-env\"></code></p>\n<p>global.process.env.NODE_ENV: <code class=\"global-node-env\"></code></p>\n<p>\n  globalThis.process.env.NODE_ENV: <code class=\"global-this-node-env\"></code>\n</p>\n<p>import.meta.env.VITE_EXPAND_A: <code class=\"expand-a\"></code></p>\n<p>import.meta.env.VITE_EXPAND_B: <code class=\"expand-b\"></code></p>\n<p>import.meta.env.SSR: <code class=\"ssr\"></code></p>\n<p>import.meta.env: <span class=\"pre env-object\"></span></p>\n<p>\n  ${import.meta.env}:\n  <span class=\"pre env-object-in-template-literal-exp\"></span>\n</p>\n<p>import.meta.url: <span class=\"pre url\"></span></p>\n<p>\n  import.meta.env. <code class=\"ignores-literal-import-meta-env-dot\"></code>\n</p>\n<p>import.meta.env <code class=\"ignores-literal-import-meta-env\"></code></p>\n\n<script type=\"module\">\n  text('.base', import.meta.env.BASE_URL)\n  text('.mode', import.meta.env.MODE)\n  text('.dev', import.meta.env.DEV)\n  text('.prod', import.meta.env.PROD)\n  text('.custom', import.meta.env.VITE_CUSTOM_ENV_VARIABLE)\n  text(\n    '.custom-template-literal-exp',\n    `${import.meta.env.VITE_CUSTOM_ENV_VARIABLE}`,\n  )\n  text('.custom-prefix', import.meta.env.CUSTOM_PREFIX_ENV_VARIABLE)\n  text('.mode-file', import.meta.env.VITE_EFFECTIVE_MODE_FILE_NAME)\n  text('.inline', import.meta.env.VITE_INLINE)\n  text('.bool', typeof import.meta.env.VITE_BOOL)\n  text('.number', typeof import.meta.env.VITE_NUMBER)\n  text('.string', typeof import.meta.env.VITE_STRING)\n  text('.stringify-object', typeof import.meta.env.VITE_STRINGIFY_OBJECT)\n  text('.ssr', import.meta.env.SSR)\n  text('.node-env', process.env.NODE_ENV)\n  text('.global-node-env', global.process.env.NODE_ENV)\n  text('.global-this-node-env', globalThis.process.env.NODE_ENV)\n  text('.env-object', JSON.stringify(import.meta.env, null, 2))\n  text(\n    '.env-object-in-template-literal-exp',\n    `${JSON.stringify(import.meta.env, null, 2)}`,\n  )\n  text('.ignores-literal-import-meta-env-dot', 'import' + '.meta.env.')\n  text('.ignores-literal-import-meta-env', 'import' + '.meta.env')\n  text('.expand-a', import.meta.env.VITE_EXPAND_A)\n  text('.expand-b', import.meta.env.VITE_EXPAND_B)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n<script type=\"module\" src=\"./index.js\"></script>\n\n<style>\n  .pre {\n    display: block;\n    unicode-bidi: embed;\n    font-family: monospace;\n    white-space: pre;\n  }\n</style>\n"
  },
  {
    "path": "playground/env/index.js",
    "content": "text('.url', import.meta.url)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n"
  },
  {
    "path": "playground/env/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-env\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"VITE_INLINE=inline-serve vite\",\n    \"build\": \"VITE_INLINE=inline-build vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/env/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nprocess.env.EXPAND = 'expand'\n\nexport default defineConfig({\n  base: '/env/',\n  envPrefix: ['VITE_', 'CUSTOM_PREFIX_'],\n  build: {\n    outDir: 'dist/env',\n  },\n  define: {\n    'import.meta.env.VITE_BOOL': true,\n    'import.meta.env.VITE_NUMBER': '123',\n    'import.meta.env.VITE_STRING': JSON.stringify('{\"123\",}'),\n    'import.meta.env.VITE_STRINGIFY_OBJECT': JSON.stringify({ a: '1', b: '2' }),\n  },\n})\n"
  },
  {
    "path": "playground/env-nested/__tests__/env-nested.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page } from '~utils'\n\nconst mode = isBuild ? `production` : `development`\n\ntest('mode', async () => {\n  expect(await page.textContent('.mode')).toBe(mode)\n})\n\ntest('mode file override', async () => {\n  expect(await page.textContent('.mode-file')).toBe(`.env.${mode}`)\n})\n\ntest('should not load parent .env file', async () => {\n  expect(await page.textContent('.parent-env')).not.toBe('dont_load_me')\n})\n"
  },
  {
    "path": "playground/env-nested/index.html",
    "content": "<h1>Nested Environment Variables</h1>\n<p>import.meta.env.MODE: <code class=\"mode\"></code></p>\n<p>\n  import.meta.env.VITE_EFFECTIVE_MODE_FILE_NAME: <code class=\"mode-file\"></code>\n</p>\n<p>Empty import.meta.env.VITE_PARENT_ENV: <code class=\"parent-env\"></code></p>\n\n<script type=\"module\">\n  text('.mode', import.meta.env.MODE)\n  text('.mode-file', import.meta.env.VITE_EFFECTIVE_MODE_FILE_NAME)\n  text('.parent-env', import.meta.env.VITE_PARENT_ENV)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/env-nested/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-env-nested\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/env-nested/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  envDir: './envs',\n})\n"
  },
  {
    "path": "playground/environment-react-ssr/__tests__/environment-react-ssr.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { stripVTControlCharacters } from 'node:util'\nimport { describe, expect, onTestFinished, test } from 'vitest'\nimport {\n  isBuild,\n  page,\n  readDepOptimizationMetadata,\n  readFile,\n  serverLogs,\n  testDir,\n} from '~utils'\n\ntest('basic', async () => {\n  await page.getByText('hydrated: true').isVisible()\n  await page.getByText('Count: 0').isVisible()\n  await page.getByRole('button', { name: '+' }).click()\n  await page.getByText('Count: 1').isVisible()\n})\n\ndescribe.runIf(!isBuild)('pre-bundling', () => {\n  test('client', async () => {\n    const metaJson = readDepOptimizationMetadata()\n\n    expect(metaJson.optimized['react']).toBeTruthy()\n    expect(metaJson.optimized['react-dom/client']).toBeTruthy()\n    expect(metaJson.optimized['react/jsx-dev-runtime']).toBeTruthy()\n\n    expect(metaJson.optimized['react-dom/server']).toBeFalsy()\n  })\n\n  test('ssr', async () => {\n    const metaJson = readDepOptimizationMetadata('ssr')\n\n    expect(metaJson.optimized['react']).toBeTruthy()\n    expect(metaJson.optimized['react-dom/server']).toBeTruthy()\n    expect(metaJson.optimized['react/jsx-dev-runtime']).toBeTruthy()\n\n    expect(metaJson.optimized['react-dom/client']).toBeFalsy()\n\n    // process.env.NODE_ENV should be kept as keepProcessEnv is true\n    const depsFiles = fs\n      .readdirSync(path.resolve(testDir, 'node_modules/.vite/deps_ssr'), {\n        withFileTypes: true,\n      })\n      .filter((file) => file.isFile() && file.name.endsWith('.js'))\n      .map((file) => path.join(file.parentPath, file.name))\n    const depsFilesWithProcessEnvNodeEnv = depsFiles.filter((file) =>\n      fs.readFileSync(file, 'utf-8').includes('process.env.NODE_ENV'),\n    )\n\n    expect(depsFilesWithProcessEnvNodeEnv.length).toBeGreaterThan(0)\n  })\n\n  test('deps reload', async () => {\n    const envs = ['client', 'server'] as const\n\n    const clientMeta = readDepOptimizationMetadata('client')\n    const ssrMeta = readDepOptimizationMetadata('ssr')\n    expect(clientMeta.optimized['react-fake-client']).toBeFalsy()\n    expect(clientMeta.optimized['react-fake-server']).toBeFalsy()\n    expect(ssrMeta.optimized['react-fake-server']).toBeFalsy()\n    expect(ssrMeta.optimized['react-fake-client']).toBeFalsy()\n\n    envs.forEach((env) => {\n      const filePath = path.resolve(testDir, `src/entry-${env}.tsx`)\n      const originalContent = readFile(filePath)\n      fs.writeFileSync(\n        filePath,\n        `import 'react-fake-${env}'\\n${originalContent}`,\n        'utf-8',\n      )\n      onTestFinished(() => {\n        fs.writeFileSync(filePath, originalContent, 'utf-8')\n      })\n    })\n\n    await expect\n      .poll(() =>\n        serverLogs\n          .map(\n            (log) =>\n              stripVTControlCharacters(log).match(\n                /new dependencies optimized: (react-fake-.*)/,\n              )?.[1],\n          )\n          .filter(Boolean),\n      )\n      .toStrictEqual(['react-fake-server', 'react-fake-client'])\n\n    const clientMetaNew = readDepOptimizationMetadata('client')\n    const ssrMetaNew = readDepOptimizationMetadata('ssr')\n    expect(clientMetaNew.optimized['react-fake-client']).toBeTruthy()\n    expect(clientMetaNew.optimized['react-fake-server']).toBeFalsy()\n    expect(ssrMetaNew.optimized['react-fake-server']).toBeTruthy()\n    expect(ssrMetaNew.optimized['react-fake-client']).toBeFalsy()\n  })\n})\n"
  },
  {
    "path": "playground/environment-react-ssr/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>environment-react-ssr</title>\n    <meta\n      name=\"viewport\"\n      content=\"width=device-width, height=device-height, initial-scale=1.0\"\n    />\n  </head>\n  <body>\n    <script src=\"/src/entry-client\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/environment-react-ssr/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-environment-react-ssr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build --app\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.14\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"react\": \"^19.2.4\",\n    \"react-fake-client\": \"npm:react@^19.2.4\",\n    \"react-fake-server\": \"npm:react@^19.2.4\",\n    \"react-dom\": \"^19.2.4\"\n  }\n}\n"
  },
  {
    "path": "playground/environment-react-ssr/src/entry-client.tsx",
    "content": "import ReactDomClient from 'react-dom/client'\nimport React from 'react'\nimport Root from './root'\n\nasync function main() {\n  const el = document.getElementById('root')\n  React.startTransition(() => {\n    ReactDomClient.hydrateRoot(el!, <Root />)\n  })\n}\n\nmain()\n"
  },
  {
    "path": "playground/environment-react-ssr/src/entry-server.tsx",
    "content": "import ReactDomServer from 'react-dom/server'\nimport type { Connect, ViteDevServer } from 'vite'\nimport Root from './root'\n\nconst handler: Connect.NextHandleFunction = async (_req, res) => {\n  const ssrHtml = ReactDomServer.renderToString(<Root />)\n  let html = await importHtml()\n  html = html.replace(/<body>/, `<body><div id=\"root\">${ssrHtml}</div>`)\n  res.setHeader('content-type', 'text/html').end(html)\n}\n\nexport default handler\n\ndeclare let __globalServer: ViteDevServer\n\nasync function importHtml() {\n  if (import.meta.env.DEV) {\n    const mod = await import('/index.html?raw')\n    return __globalServer.transformIndexHtml('/', mod.default)\n  } else {\n    const mod = await import('/dist/client/index.html?raw')\n    return mod.default\n  }\n}\n"
  },
  {
    "path": "playground/environment-react-ssr/src/root.tsx",
    "content": "import React from 'react'\n\nexport default function Root() {\n  const [count, setCount] = React.useState(0)\n\n  const [hydrated, setHydrated] = React.useState(false)\n  React.useEffect(() => {\n    setHydrated(true)\n  }, [])\n\n  return (\n    <div>\n      <div>hydrated: {String(hydrated)}</div>\n      <div>Count: {count}</div>\n      <button onClick={() => setCount((v) => v - 1)}>-1</button>\n      <button onClick={() => setCount((v) => v + 1)}>+1</button>\n    </div>\n  )\n}\n"
  },
  {
    "path": "playground/environment-react-ssr/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"include\": [\"src\"],\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\"\n  }\n}\n"
  },
  {
    "path": "playground/environment-react-ssr/vite.config.ts",
    "content": "import {\n  type Connect,\n  type Plugin,\n  type PluginOption,\n  createServerModuleRunner,\n  defineConfig,\n} from 'vite'\n\nexport default defineConfig((env) => ({\n  clearScreen: false,\n  appType: 'custom',\n  plugins: [\n    vitePluginSsrMiddleware({\n      entry: '/src/entry-server',\n      preview: new URL('./dist/server/index.js', import.meta.url).toString(),\n    }),\n    {\n      name: 'global-server',\n      configureServer(server) {\n        Object.assign(globalThis, { __globalServer: server })\n      },\n    },\n    {\n      name: 'build-client',\n      async buildApp(builder) {\n        await builder.build(builder.environments.client)\n      },\n    },\n  ],\n  resolve: {\n    noExternal: true,\n  },\n  environments: {\n    client: {\n      build: {\n        minify: false,\n        sourcemap: true,\n        outDir: 'dist/client',\n      },\n      optimizeDeps: {\n        rolldownOptions: {\n          // manual test for https://github.com/vitejs/rolldown-vite/issues/416\n          transform: {},\n        },\n      },\n    },\n    ssr: {\n      optimizeDeps: {\n        noDiscovery: false,\n      },\n      build: {\n        outDir: 'dist/server',\n        rollupOptions: {\n          input: {\n            index: '/src/entry-server',\n          },\n        },\n      },\n    },\n  },\n\n  builder: {\n    async buildApp(builder) {\n      if (!builder.environments.client.isBuilt) {\n        throw new Error('Client environment should be built first')\n      }\n      await builder.build(builder.environments.ssr)\n    },\n  },\n}))\n\n// vavite-style ssr middleware plugin\nexport function vitePluginSsrMiddleware({\n  entry,\n  preview,\n}: {\n  entry: string\n  preview?: string\n}): PluginOption {\n  const plugin: Plugin = {\n    name: vitePluginSsrMiddleware.name,\n\n    configureServer(server) {\n      const runner = createServerModuleRunner(server.environments.ssr, {\n        hmr: { logger: false },\n      })\n      const importWithRetry = async () => {\n        try {\n          return await runner.import(entry)\n        } catch (e) {\n          if (\n            e instanceof Error &&\n            (e as any).code === 'ERR_OUTDATED_OPTIMIZED_DEP'\n          ) {\n            runner.clearCache()\n            return await importWithRetry()\n          }\n          throw e\n        }\n      }\n      const handler: Connect.NextHandleFunction = async (req, res, next) => {\n        try {\n          const mod = await importWithRetry()\n          await mod['default'](req, res, next)\n        } catch (e) {\n          next(e)\n        }\n      }\n      return () => server.middlewares.use(handler)\n    },\n\n    async configurePreviewServer(server) {\n      if (preview) {\n        const mod = await import(preview)\n        return () => server.middlewares.use(mod.default)\n      }\n      return\n    },\n  }\n  return [plugin]\n}\n"
  },
  {
    "path": "playground/extensions/__tests__/extensions.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { browserLogs, page } from '~utils'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ntest('not contain `.mjs`', async () => {\n  const appHtml = await page.content()\n  expect(appHtml).toMatch('Hello Vite!')\n})\n"
  },
  {
    "path": "playground/extensions/index.html",
    "content": "<div id=\"app\">Hello Vite!</div>\n\n<script type=\"module\">\n  import { createApp } from 'vue'\n  createApp({ template: 'Hello Vite!' }).mount('#app')\n</script>\n"
  },
  {
    "path": "playground/extensions/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-extensions\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"vue\": \"^3.5.30\"\n  }\n}\n"
  },
  {
    "path": "playground/extensions/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  resolve: {\n    alias: [{ find: 'vue', replacement: 'vue/dist/vue.esm-bundler.js' }],\n    extensions: ['.js'],\n  },\n})\n"
  },
  {
    "path": "playground/external/__tests__/external.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { browserLogs, isBuild, page } from '~utils'\n\ntest('importmap', () => {\n  expect(browserLogs).not.toContain(\n    'An import map is added after module script load was triggered.',\n  )\n})\n\ntest('should have default exports', async () => {\n  expect(await page.textContent('#imported-slash5-exists')).toBe('true')\n  expect(await page.textContent('#imported-slash3-exists')).toBe('true')\n  expect(await page.textContent('#required-slash3-exists')).toBe('true')\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('should externalize imported packages', async () => {\n    // If `vue` is successfully externalized, the page should use the version from the import map\n    expect(await page.textContent('#imported-vue-version')).toBe('3.4.38')\n  })\n\n  test('should externalize required packages', async () => {\n    // If `vue` is successfully externalized, the page should use the version from the import map\n    expect(await page.textContent('#required-vue-version')).toBe('3.4.38')\n  })\n})\n"
  },
  {
    "path": "playground/external/dep-that-imports/index.js",
    "content": "import { version } from 'vue'\nimport slash5 from 'slash5'\nimport slash3 from 'slash3'\n\ndocument.querySelector('#imported-vue-version').textContent = version\ndocument.querySelector('#imported-slash5-exists').textContent =\n  !!slash5('foo/bar')\ndocument.querySelector('#imported-slash3-exists').textContent =\n  !!slash3('foo/bar')\n"
  },
  {
    "path": "playground/external/dep-that-imports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-that-imports\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"slash3\": \"npm:slash@^3.0.0\",\n    \"slash5\": \"npm:slash@^5.1.0\",\n    \"vue\": \"^3.5.30\"\n  }\n}\n"
  },
  {
    "path": "playground/external/dep-that-requires/index.js",
    "content": "const { version } = require('vue')\n// require('slash5') // cannot require ESM\nconst slash3 = require('slash3')\n\ndocument.querySelector('#required-vue-version').textContent = version\ndocument.querySelector('#required-slash3-exists').textContent =\n  !!slash3('foo/bar')\n"
  },
  {
    "path": "playground/external/dep-that-requires/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-that-requires\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"slash3\": \"npm:slash@^3.0.0\",\n    \"slash5\": \"npm:slash@^5.1.0\",\n    \"vue\": \"^3.5.30\"\n  }\n}\n"
  },
  {
    "path": "playground/external/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite App</title>\n    <script type=\"importmap\">\n      {\n        \"imports\": {\n          \"vue\": \"/vue@3.4.38.js\",\n          \"slash5\": \"/slash@5.js\",\n          \"slash3\": \"/slash@3.0.0.js\"\n        }\n      }\n    </script>\n  </head>\n  <body>\n    <p>Imported Vue version: <span id=\"imported-vue-version\"></span></p>\n    <p>Required Vue version: <span id=\"required-vue-version\"></span></p>\n    <p>Imported slash5 exists: <span id=\"imported-slash5-exists\"></span></p>\n    <p>Imported slash3 exists: <span id=\"imported-slash3-exists\"></span></p>\n    <p>Required slash3 exists: <span id=\"required-slash3-exists\"></span></p>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-dep-that-imports\": \"file:./dep-that-imports\",\n    \"@vitejs/test-dep-that-requires\": \"file:./dep-that-requires\"\n  },\n  \"devDependencies\": {\n    \"slash3\": \"npm:slash@^3.0.0\",\n    \"slash5\": \"npm:slash@^5.1.0\",\n    \"vite\": \"workspace:*\",\n    \"vue\": \"^3.5.30\",\n    \"vue34\": \"npm:vue@~3.4.38\"\n  }\n}\n"
  },
  {
    "path": "playground/external/public/slash@3.0.0.js",
    "content": "/* eslint-disable */\n// copied from https://esm.sh/v133/slash@3.0.0/es2022/slash.mjs to reduce network issues in CI\n\n/* esm.sh - esbuild bundle(slash@3.0.0) es2022 production */\nvar a=Object.create;var d=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var A=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),E=(e,t)=>{for(var r in t)d(e,r,{get:t[r],enumerable:!0})},u=(e,t,r,i)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let n of x(t))!p.call(e,n)&&n!==r&&d(e,n,{get:()=>t[n],enumerable:!(i=m(t,n))||i.enumerable});return e},o=(e,t,r)=>(u(e,t,\"default\"),r&&u(r,t,\"default\")),c=(e,t,r)=>(r=e!=null?a(g(e)):{},u(t||!e||!e.__esModule?d(r,\"default\",{value:e,enumerable:!0}):r,e));var f=A((h,_)=>{\"use strict\";_.exports=e=>{let t=/^\\\\\\\\\\?\\\\/.test(e),r=/[^\\u0000-\\u0080]+/.test(e);return t||r?e:e.replace(/\\\\/g,\"/\")}});var s={};E(s,{default:()=>P});var L=c(f());o(s,c(f()));var{default:l,...N}=L,P=l!==void 0?l:N;export{P as default};\n"
  },
  {
    "path": "playground/external/src/main.js",
    "content": "import './require-polyfill'\nimport '@vitejs/test-dep-that-imports'\nimport '@vitejs/test-dep-that-requires'\n"
  },
  {
    "path": "playground/external/src/require-polyfill.js",
    "content": "import * as vue from 'vue'\nimport slash3 from 'slash3'\n\nexport default (id) => {\n  if (id === 'vue') return vue\n  if (id === 'slash3') return slash3\n  throw new Error(`Cannot require \"${id}\"`)\n}\n"
  },
  {
    "path": "playground/external/vite.config.js",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst npmDirectServeConfig = {\n  '/vue@3.4.38.js': 'vue34/dist/vue.runtime.esm-browser.js',\n  '/slash@5.js': 'slash5/index.js',\n}\n/** @type {import('vite').Connect.NextHandleFunction} */\nconst serveNpmCodeDirectlyMiddleware = async (req, res, next) => {\n  for (const [url, file] of Object.entries(npmDirectServeConfig)) {\n    if (req.originalUrl === url) {\n      const code = await fs.readFile(\n        new URL(`./node_modules/${file}`, import.meta.url),\n      )\n      res.setHeader('Content-Type', 'text/javascript')\n      res.end(code)\n      return\n    }\n  }\n  next()\n}\n\nexport default defineConfig({\n  optimizeDeps: {\n    include: ['dep-that-imports', 'dep-that-requires'],\n    exclude: ['vue', 'slash5'],\n  },\n  build: {\n    minify: false,\n    rollupOptions: {\n      external: ['vue', 'slash3', 'slash5'],\n      transform: {\n        inject: {\n          require: path.resolve(import.meta.dirname, 'src/require-polyfill.js'),\n        },\n      },\n    },\n    commonjsOptions: {\n      esmExternals: ['vue', 'slash5'],\n      dynamicRequireTargets: ['test-no-op-fdir-glob'],\n    },\n  },\n  plugins: [\n    {\n      name: 'serve-npm-code-directly',\n      configureServer({ middlewares }) {\n        middlewares.use(serveNpmCodeDirectlyMiddleware)\n      },\n      configurePreviewServer({ middlewares }) {\n        middlewares.use(serveNpmCodeDirectlyMiddleware)\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/forward-console/__test__/forward-console.spec.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\nimport { expect, test } from 'vitest'\nimport { isServe, page, serverLogs } from '~utils'\n\nfunction normalizeLogs(logs: string[]) {\n  return (\n    logs\n      .map((log) => stripVTControlCharacters(log))\n      .join('\\n')\n      // normalize .pnpm path\n      .replaceAll(\n        /node_modules\\/\\.pnpm\\/[^/\\n]+\\/node_modules\\//g,\n        'node_modules/.pnpm/<normalized>/node_modules/',\n      )\n      // strip trailing spaces of code frame\n      .replaceAll(/ +\\n/g, '\\n')\n  )\n}\n\ntest.runIf(isServe)('unhandled error', async () => {\n  await page.click('#test-error')\n  await expect.poll(() => normalizeLogs(serverLogs)).toContain(`\\\n[Unhandled error] Error: this is test error\n > testError src/main.ts:30:8\n    28 |\n    29 |  function testError() {\n    30 |    throw new Error('this is test error')\n       |          ^\n    31 |  }\n    32 |\n > HTMLButtonElement.<anonymous> src/main.ts:8:2\n`)\n})\n\ntest.runIf(isServe)('unhandled rejection', async () => {\n  const logIndex = serverLogs.length\n  await page.click('#test-unhandledrejection')\n  await expect.poll(() => normalizeLogs(serverLogs.slice(logIndex)))\n    .toContain(`\\\n[Unhandled rejection] Error: this is test unhandledrejection\n > testUnhandledRejection src/main.ts:34:17\n    32 |\n    33 |  function testUnhandledRejection() {\n    34 |    Promise.reject(new Error('this is test unhandledrejection'))\n       |                   ^\n    35 |  }\n    36 |\n > HTMLButtonElement.<anonymous> src/main.ts:14:4\n`)\n})\n\ntest.runIf(isServe)('console.error', async () => {\n  const logIndex = serverLogs.length\n  await page.click('#test-console-error')\n  await expect\n    .poll(() => normalizeLogs(serverLogs.slice(logIndex)))\n    .toContain(\n      `[console.error] format: string=hello number=12.9 int=42 float=3.5 json={\"id\":1} object={\"enabled\":true} object2={\"nested\":{\"deep\":1}} style= literal=% trailing done`,\n    )\n})\n\ntest.runIf(isServe)('dependency stack uses source map path', async () => {\n  const logIndex = serverLogs.length\n  await page.click('#test-dep-error')\n  await expect.poll(() => normalizeLogs(serverLogs.slice(logIndex)))\n    .toContain(`\\\n[Unhandled error] Error: this is test dependency error\n > throwDepError ../../node_modules/.pnpm/<normalized>/node_modules/@vitejs/test-forward-console-throw-dep/index.js:2:8\n > testDepError src/main.ts:38:2\n    36 |\n    37 |  function testDepError() {\n    38 |    throwDepError()\n       |    ^\n    39 |  }\n    40 |\n > HTMLButtonElement.<anonymous> src/main.ts:22:2\n`)\n})\n"
  },
  {
    "path": "playground/forward-console/fixtures/throw-dep/index.js",
    "content": "export function throwDepError() {\n  throw new Error('this is test dependency error')\n}\n"
  },
  {
    "path": "playground/forward-console/fixtures/throw-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-forward-console-throw-dep\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./index.js\"\n  }\n}\n"
  },
  {
    "path": "playground/forward-console/index.html",
    "content": "<button id=\"test-error\">Test error</button>\n<button id=\"test-unhandledrejection\">Test unhandledrejection</button>\n<button id=\"test-console-error\">Test console.error</button>\n<button id=\"test-dep-error\">Test dependency error</button>\n<script type=\"module\" src=\"/src/main.ts\"></script>\n"
  },
  {
    "path": "playground/forward-console/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-forward-console\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-forward-console-throw-dep\": \"file:./fixtures/throw-dep\"\n  },\n  \"devDependencies\": {}\n}\n"
  },
  {
    "path": "playground/forward-console/src/main.ts",
    "content": "import { throwDepError } from '@vitejs/test-forward-console-throw-dep'\n\nexport type SomePadding = {\n  here: boolean\n}\n\ndocument.getElementById('test-error').addEventListener('click', () => {\n  testError()\n})\n\ndocument\n  .getElementById('test-unhandledrejection')\n  .addEventListener('click', () => {\n    testUnhandledRejection()\n  })\n\ndocument.getElementById('test-console-error').addEventListener('click', () => {\n  testConsoleError()\n})\n\ndocument.getElementById('test-dep-error').addEventListener('click', () => {\n  testDepError()\n})\n\nexport type AnotherPadding = {\n  there: boolean\n}\n\nfunction testError() {\n  throw new Error('this is test error')\n}\n\nfunction testUnhandledRejection() {\n  Promise.reject(new Error('this is test unhandledrejection'))\n}\n\nfunction testDepError() {\n  throwDepError()\n}\n\nfunction testConsoleError() {\n  console.error(\n    'format: string=%s number=%d int=%i float=%f json=%j object=%o object2=%O style=%c literal=%% trailing',\n    'hello',\n    12.9,\n    '42px',\n    '3.5',\n    { id: 1 },\n    { enabled: true },\n    { nested: { deep: 1 } },\n    'color:red',\n    'done',\n  )\n}\n"
  },
  {
    "path": "playground/forward-console/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  server: {\n    forwardConsole: true,\n  },\n})\n"
  },
  {
    "path": "playground/fs-serve/__tests__/base/fs-serve-base.spec.ts",
    "content": "import '../commonTests'\n"
  },
  {
    "path": "playground/fs-serve/__tests__/commonTests.ts",
    "content": "import http from 'node:http'\nimport {\n  afterEach,\n  beforeAll,\n  beforeEach,\n  describe,\n  expect,\n  test,\n} from 'vitest'\nimport type { Page } from 'playwright-chromium'\nimport WebSocket from 'ws'\nimport testJSON from '../safe.json'\nimport { browser, isServe, page, viteServer, viteTestUrl } from '~utils'\n\nconst getViteTestIndexHtmlUrl = () => {\n  const srcPrefix = viteTestUrl.endsWith('/') ? '' : '/'\n  // NOTE: viteTestUrl is set lazily\n  return viteTestUrl + srcPrefix + 'src/'\n}\n\nconst stringified = JSON.stringify(testJSON)\n\ndescribe.runIf(isServe)('main', () => {\n  beforeAll(async () => {\n    await page.goto(getViteTestIndexHtmlUrl())\n  })\n\n  test('default import', async () => {\n    await expect.poll(() => page.textContent('.full')).toBe(stringified)\n  })\n\n  test('named import', async () => {\n    await expect.poll(() => page.textContent('.named')).toBe(testJSON.msg)\n  })\n\n  test('virtual svg module', async () => {\n    await expect.poll(() => page.textContent('.virtual-svg')).toMatch('<svg')\n  })\n\n  test('safe fetch', async () => {\n    await expect.poll(() => page.textContent('.safe-fetch')).toMatch('KEY=safe')\n    await expect.poll(() => page.textContent('.safe-fetch-status')).toBe('200')\n  })\n\n  test('safe fetch with query', async () => {\n    await expect\n      .poll(() => page.textContent('.safe-fetch-query'))\n      .toMatch('KEY=safe')\n    await expect\n      .poll(() => page.textContent('.safe-fetch-query-status'))\n      .toBe('200')\n  })\n\n  test('safe fetch with special characters', async () => {\n    await expect\n      .poll(() => page.textContent('.safe-fetch-subdir-special-characters'))\n      .toMatch('KEY=safe')\n    await expect\n      .poll(() =>\n        page.textContent('.safe-fetch-subdir-special-characters-status'),\n      )\n      .toBe('200')\n  })\n\n  test('unsafe fetch', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch'))\n      .toMatch('403 Restricted')\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-status'))\n      .toBe('403')\n  })\n\n  test('unsafe HTML fetch', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-html'))\n      .toMatch('403 Restricted')\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-html-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fetch with special characters (#8498)', async () => {\n    await expect.poll(() => page.textContent('.unsafe-fetch-8498')).toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-8498-status'))\n      .toBe('404')\n  })\n\n  test('unsafe fetch with special characters 2 (#8498)', async () => {\n    await expect.poll(() => page.textContent('.unsafe-fetch-8498-2')).toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-8498-2-status'))\n      .toBe('404')\n  })\n\n  test('unsafe fetch import inline', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-import-inline-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fetch raw query import', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-raw-query-import-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fetch ?.svg?import', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-query-dot-svg-import-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fetch .svg?import', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-svg-status'))\n      .toBe('403')\n  })\n\n  test('safe fs fetch', async () => {\n    await expect\n      .poll(() => page.textContent('.safe-fs-fetch'))\n      .toBe(stringified)\n    await expect\n      .poll(() => page.textContent('.safe-fs-fetch-status'))\n      .toBe('200')\n  })\n\n  test('safe fs fetch', async () => {\n    await expect\n      .poll(() => page.textContent('.safe-fs-fetch-query'))\n      .toBe(stringified)\n    await expect\n      .poll(() => page.textContent('.safe-fs-fetch-query-status'))\n      .toBe('200')\n  })\n\n  test('safe fs fetch with special characters', async () => {\n    await expect\n      .poll(() => page.textContent('.safe-fs-fetch-special-characters'))\n      .toBe(stringified)\n    await expect\n      .poll(() => page.textContent('.safe-fs-fetch-special-characters-status'))\n      .toBe('200')\n  })\n\n  test('unsafe fs fetch', async () => {\n    await expect.poll(() => page.textContent('.unsafe-fs-fetch')).toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fs fetch', async () => {\n    await expect.poll(() => page.textContent('.unsafe-fs-fetch-raw')).toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-raw-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fs fetch query 1', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-raw-query1'))\n      .toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-raw-query1-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fs fetch query 2', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-raw-query2'))\n      .toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-raw-query2-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fs fetch with special characters (#8498)', async () => {\n    await expect.poll(() => page.textContent('.unsafe-fs-fetch-8498')).toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-8498-status'))\n      .toBe('404')\n  })\n\n  test('unsafe fs fetch with special characters 2 (#8498)', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-8498-2'))\n      .toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-8498-2-status'))\n      .toBe('404')\n  })\n\n  test('unsafe fs fetch import inline', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-fs-fetch-import-inline-status'))\n      .toBe('403')\n  })\n\n  test('unsafe fs fetch import inline wasm init', async () => {\n    await expect\n      .poll(() =>\n        page.textContent('.unsafe-fs-fetch-import-inline-wasm-init-status'),\n      )\n      .toBe('403')\n  })\n\n  test('unsafe fs fetch with relative path after query status', async () => {\n    await expect\n      .poll(() =>\n        page.textContent('.unsafe-fs-fetch-relative-path-after-query-status'),\n      )\n      .toBe('404')\n  })\n\n  test('nested entry', async () => {\n    await expect.poll(() => page.textContent('.nested-entry')).toBe('foobar')\n  })\n\n  test('denied', async () => {\n    await expect.poll(() => page.textContent('.unsafe-dotenv')).toBe('403')\n  })\n\n  test('denied EnV casing', async () => {\n    // It is 403 in case insensitive system, 404 in others\n    await expect\n      .poll(() => page.textContent('.unsafe-dotEnV-casing'))\n      .toStrictEqual(expect.toBeOneOf(['403', '404']))\n  })\n\n  test('denied env with ?.svg?.wasm?init', async () => {\n    await expect\n      .poll(() => page.textContent('.unsafe-dotenv-query-dot-svg-wasm-init'))\n      .toBe('403')\n  })\n})\n\ndescribe('fetch', () => {\n  test('serve with configured headers', async () => {\n    const res = await fetch(viteTestUrl + '/src/')\n    expect(res.headers.get('x-served-by')).toBe('vite')\n  })\n})\n\ndescribe('cross origin', () => {\n  const fetchStatusFromPage = async (page: Page, url: string) => {\n    return await page.evaluate(async (url: string) => {\n      try {\n        const res = await globalThis.fetch(url)\n        return res.status\n      } catch {\n        return -1\n      }\n    }, url)\n  }\n\n  const connectWebSocketFromPage = async (page: Page, url: string) => {\n    return await page.evaluate(async (url: string) => {\n      try {\n        const ws = new globalThis.WebSocket(url, ['vite-hmr'])\n        await new Promise<void>((resolve, reject) => {\n          ws.addEventListener('open', () => {\n            resolve()\n            ws.close()\n          })\n          ws.addEventListener('error', () => {\n            reject()\n          })\n        })\n        return true\n      } catch {\n        return false\n      }\n    }, url)\n  }\n\n  const connectWebSocketFromServer = async (\n    url: string,\n    host: string,\n    origin: string | undefined,\n  ) => {\n    try {\n      const ws = new WebSocket(url, ['vite-hmr'], {\n        headers: {\n          Host: host,\n          ...(origin ? { Origin: origin } : undefined),\n        },\n      })\n      await new Promise<void>((resolve, reject) => {\n        ws.addEventListener('open', () => {\n          resolve()\n          ws.close()\n        })\n        ws.addEventListener('error', () => {\n          reject()\n        })\n      })\n      return true\n    } catch {\n      return false\n    }\n  }\n\n  describe('allowed for same origin', () => {\n    beforeEach(async () => {\n      await page.goto(getViteTestIndexHtmlUrl())\n    })\n\n    test('fetch HTML file', async () => {\n      const status = await fetchStatusFromPage(page, viteTestUrl + '/src/')\n      expect(status).toBe(200)\n    })\n\n    test.runIf(isServe)('fetch JS file', async () => {\n      const status = await fetchStatusFromPage(\n        page,\n        viteTestUrl + '/src/code.js',\n      )\n      expect(status).toBe(200)\n    })\n\n    test.runIf(isServe)('connect WebSocket with valid token', async () => {\n      const token = viteServer.config.webSocketToken\n      const result = await connectWebSocketFromPage(\n        page,\n        `${viteTestUrl}?token=${token}`,\n      )\n      expect(result).toBe(true)\n    })\n\n    test('fetch with allowed hosts', async () => {\n      const viteTestUrlUrl = new URL(viteTestUrl)\n      const res = await fetch(viteTestUrl + '/src/index.html', {\n        headers: { Host: viteTestUrlUrl.host },\n      })\n      expect(res.status).toBe(200)\n    })\n\n    test.runIf(isServe)(\n      'connect WebSocket with valid token with allowed hosts',\n      async () => {\n        const viteTestUrlUrl = new URL(viteTestUrl)\n        const token = viteServer.config.webSocketToken\n        const result = await connectWebSocketFromServer(\n          `${viteTestUrl}?token=${token}`,\n          viteTestUrlUrl.host,\n          viteTestUrlUrl.origin,\n        )\n        expect(result).toBe(true)\n      },\n    )\n\n    test.runIf(isServe)(\n      'connect WebSocket without a token without the origin header',\n      async () => {\n        const viteTestUrlUrl = new URL(viteTestUrl)\n        const result = await connectWebSocketFromServer(\n          viteTestUrl,\n          viteTestUrlUrl.host,\n          undefined,\n        )\n        expect(result).toBe(true)\n      },\n    )\n  })\n\n  describe('denied for different origin', async () => {\n    let page2: Page\n    beforeEach(async () => {\n      page2 = await browser.newPage()\n      await page2.goto('http://vite.dev/404')\n    })\n    afterEach(async () => {\n      await page2.close()\n    })\n\n    test('fetch HTML file', async () => {\n      const status = await fetchStatusFromPage(page2, viteTestUrl + '/src/')\n      expect(status).not.toBe(200)\n    })\n\n    test.runIf(isServe)('fetch JS file', async () => {\n      const status = await fetchStatusFromPage(\n        page2,\n        viteTestUrl + '/src/code.js',\n      )\n      expect(status).not.toBe(200)\n    })\n\n    test.runIf(isServe)('connect WebSocket without token', async () => {\n      const result = await connectWebSocketFromPage(page, viteTestUrl)\n      expect(result).toBe(false)\n\n      const result2 = await connectWebSocketFromPage(\n        page,\n        `${viteTestUrl}?token=`,\n      )\n      expect(result2).toBe(false)\n    })\n\n    test.runIf(isServe)('connect WebSocket with invalid token', async () => {\n      const token = viteServer.config.webSocketToken\n      const result = await connectWebSocketFromPage(\n        page,\n        `${viteTestUrl}?token=${'t'.repeat(token.length)}`,\n      )\n      expect(result).toBe(false)\n\n      const result2 = await connectWebSocketFromPage(\n        page,\n        `${viteTestUrl}?token=${'t'.repeat(token.length)}t`, // different length\n      )\n      expect(result2).toBe(false)\n    })\n\n    test('fetch with non-allowed hosts', async () => {\n      // NOTE: fetch cannot be used here as `fetch` sets the correct `Host` header\n      const res = await new Promise<http.IncomingMessage>((resolve, reject) => {\n        http\n          .get(\n            viteTestUrl + '/src/index.html',\n            {\n              headers: {\n                Host: 'vite.dev',\n              },\n            },\n            (res) => {\n              resolve(res)\n            },\n          )\n          .on('error', (e) => {\n            reject(e)\n          })\n      })\n      expect(res.statusCode).toBe(403)\n    })\n\n    test.runIf(isServe)(\n      'connect WebSocket with valid token with non-allowed hosts',\n      async () => {\n        const token = viteServer.config.webSocketToken\n        const result = await connectWebSocketFromServer(\n          `${viteTestUrl}?token=${token}`,\n          'vite.dev',\n          'http://vite.dev',\n        )\n        expect(result).toBe(false)\n\n        const result2 = await connectWebSocketFromServer(\n          `${viteTestUrl}?token=${token}`,\n          'vite.dev',\n          undefined,\n        )\n        expect(result2).toBe(false)\n      },\n    )\n  })\n})\n\ndescribe.runIf(!isServe)('preview HTML', () => {\n  test('unsafe HTML fetch', async () => {\n    await expect.poll(() => page.textContent('.unsafe-fetch-html')).toBe('')\n    await expect\n      .poll(() => page.textContent('.unsafe-fetch-html-status'))\n      .toBe('404')\n  })\n})\n\ntest.runIf(isServe)(\n  'load script with no-cors mode from a different origin',\n  async () => {\n    const viteTestUrlUrl = new URL(viteTestUrl)\n\n    // NOTE: fetch cannot be used here as `fetch` sets some headers automatically\n    const res = await new Promise<http.IncomingMessage>((resolve, reject) => {\n      http\n        .get(\n          viteTestUrl + '/src/code.js',\n          {\n            headers: {\n              'Sec-Fetch-Dest': 'script',\n              'Sec-Fetch-Mode': 'no-cors',\n              'Sec-Fetch-Site': 'same-site',\n              Origin: 'http://vite.dev',\n              Host: viteTestUrlUrl.host,\n            },\n          },\n          (res) => {\n            resolve(res)\n          },\n        )\n        .on('error', (e) => {\n          reject(e)\n        })\n    })\n    expect(res.statusCode).toBe(200)\n    const body = Buffer.concat(await ArrayFromAsync(res)).toString()\n    expect(body).toContain(\n      'Cross-origin requests for classic scripts must be made with CORS mode enabled.',\n    )\n  },\n)\n\ntest.runIf(isServe)(\n  'load image with no-cors mode from a different origin should be allowed',\n  async () => {\n    const viteTestUrlUrl = new URL(viteTestUrl)\n\n    // NOTE: fetch cannot be used here as `fetch` sets some headers automatically\n    const res = await new Promise<http.IncomingMessage>((resolve, reject) => {\n      http\n        .get(\n          viteTestUrl + '/src/code.js',\n          {\n            headers: {\n              'Sec-Fetch-Dest': 'image',\n              'Sec-Fetch-Mode': 'no-cors',\n              'Sec-Fetch-Site': 'same-site',\n              Origin: 'http://vite.dev',\n              Host: viteTestUrlUrl.host,\n            },\n          },\n          (res) => {\n            resolve(res)\n          },\n        )\n        .on('error', (e) => {\n          reject(e)\n        })\n    })\n    expect(res.statusCode).not.toBe(403)\n    const body = Buffer.concat(await ArrayFromAsync(res)).toString()\n    expect(body).not.toContain(\n      'Cross-origin requests for classic scripts must be made with CORS mode enabled.',\n    )\n  },\n)\n\n// Note: Array.fromAsync is only supported in Node.js 22+\nasync function ArrayFromAsync<T>(\n  asyncIterable: AsyncIterable<T>,\n): Promise<T[]> {\n  const chunks = []\n  for await (const chunk of asyncIterable) {\n    chunks.push(chunk)\n  }\n  return chunks\n}\n"
  },
  {
    "path": "playground/fs-serve/__tests__/deny/fs-serve-deny.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { isServe, page, viteTestUrl } from '~utils'\n\ndescribe.runIf(isServe)('main', () => {\n  test('**/deny/** should deny src/deny/deny.txt', async () => {\n    const res = await page.request.fetch(\n      new URL('/src/deny/deny.txt', viteTestUrl).href,\n    )\n    expect(res.status()).toBe(403)\n  })\n  test('**/deny/** should deny src/deny/.deny', async () => {\n    const res = await page.request.fetch(\n      new URL('/src/deny/.deny', viteTestUrl).href,\n    )\n    expect(res.status()).toBe(403)\n  })\n})\n"
  },
  {
    "path": "playground/fs-serve/__tests__/fs-serve.spec.ts",
    "content": "import net from 'node:net'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { isServe, isWindows, viteTestUrl } from '~utils'\nimport './commonTests'\n\ndescribe.runIf(isServe)('invalid request', () => {\n  const sendRawRequest = async (baseUrl: string, requestTarget: string) => {\n    return new Promise<string>((resolve, reject) => {\n      const parsedUrl = new URL(baseUrl)\n\n      const buf: Buffer[] = []\n      const client = net.createConnection(\n        { port: +parsedUrl.port, host: parsedUrl.hostname },\n        () => {\n          client.write(\n            [\n              `GET ${encodeURI(requestTarget)} HTTP/1.1`,\n              `Host: ${parsedUrl.host}`,\n              'Connection: Close',\n              '\\r\\n',\n            ].join('\\r\\n'),\n          )\n        },\n      )\n      client.on('data', (data) => {\n        buf.push(data)\n      })\n      client.on('end', (hadError) => {\n        if (!hadError) {\n          resolve(Buffer.concat(buf).toString())\n        }\n      })\n      client.on('error', (err) => {\n        reject(err)\n      })\n    })\n  }\n\n  const root = path\n    .resolve(import.meta.dirname.replace('playground', 'playground-temp'), '..')\n    .replace(/\\\\/g, '/')\n\n  test('request with sendRawRequest should work', async () => {\n    const response = await sendRawRequest(viteTestUrl, '/src/safe.txt')\n    expect(response).toContain('HTTP/1.1 200 OK')\n    expect(response).toContain('KEY=safe')\n  })\n\n  test('request with sendRawRequest should work with /@fs/', async () => {\n    const response = await sendRawRequest(\n      viteTestUrl,\n      path.posix.join('/@fs/', root, 'root/src/safe.txt'),\n    )\n    expect(response).toContain('HTTP/1.1 200 OK')\n    expect(response).toContain('KEY=safe')\n  })\n\n  test('should reject request that has # in request-target', async () => {\n    const response = await sendRawRequest(\n      viteTestUrl,\n      '/src/safe.txt#/../../unsafe.txt',\n    )\n    expect(response).toContain('HTTP/1.1 400 Bad Request')\n  })\n\n  test('should reject request that has # in request-target with /@fs/', async () => {\n    const response = await sendRawRequest(\n      viteTestUrl,\n      path.posix.join('/@fs/', root, 'root/src/safe.txt') +\n        '#/../../unsafe.txt',\n    )\n    expect(response).toContain('HTTP/1.1 400 Bad Request')\n  })\n\n  test('should deny request to denied file when a request has /.', async () => {\n    const response = await sendRawRequest(viteTestUrl, '/src/dummy.crt/.')\n    expect(response).toContain('HTTP/1.1 403 Forbidden')\n  })\n\n  test('should deny request to denied file when a request ends with \\\\', async () => {\n    const response = await sendRawRequest(viteTestUrl, '/src/.env\\\\')\n    expect(response).toContain(\n      isWindows ? 'HTTP/1.1 403 Forbidden' : 'HTTP/1.1 404 Not Found',\n    )\n  })\n\n  test('should deny request to denied file when a request ends with \\\\ with /@fs/', async () => {\n    const response = await sendRawRequest(\n      viteTestUrl,\n      path.posix.join('/@fs/', root, 'root/src/.env') + '\\\\',\n    )\n    expect(response).toContain(\n      isWindows ? 'HTTP/1.1 403 Forbidden' : 'HTTP/1.1 404 Not Found',\n    )\n  })\n\n  test('should deny request with /@fs/ to denied file when a request has /.', async () => {\n    const response = await sendRawRequest(\n      viteTestUrl,\n      path.posix.join('/@fs/', root, 'root/src/dummy.crt/') + '.',\n    )\n    expect(response).toContain('HTTP/1.1 403 Forbidden')\n  })\n\n  test('should deny request to HTML file outside root by default with relative path', async () => {\n    const response = await sendRawRequest(viteTestUrl, '/../unsafe.html')\n    expect(response).toContain('HTTP/1.1 403 Forbidden')\n  })\n})\n"
  },
  {
    "path": "playground/fs-serve/entry.js",
    "content": "import { msg } from './nested/foo'\n\nexport const fullmsg = msg + 'bar'\n\ndocument.querySelector('.nested-entry').textContent = fullmsg\n"
  },
  {
    "path": "playground/fs-serve/nested/foo.js",
    "content": "export const msg = 'foo'\n"
  },
  {
    "path": "playground/fs-serve/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-fs-serve\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite root\",\n    \"build\": \"vite build root\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview root\",\n    \"dev:base\": \"vite root --config ./root/vite.config-base.js\",\n    \"build:base\": \"vite build root --config ./root/vite.config-base.js\",\n    \"preview:base\": \"vite preview root --config ./root/vite.config-base.js\",\n    \"dev:deny\": \"vite root --config ./root/vite.config-deny.js\",\n    \"build:deny\": \"vite build root --config ./root/vite.config-deny.js\",\n    \"preview:deny\": \"vite preview root --config ./root/vite.config-deny.js\"\n  },\n  \"devDependencies\": {\n    \"ws\": \"^8.19.0\"\n  }\n}\n"
  },
  {
    "path": "playground/fs-serve/root/src/code.js",
    "content": "// code.js\n"
  },
  {
    "path": "playground/fs-serve/root/src/deny/.deny",
    "content": ".deny\n"
  },
  {
    "path": "playground/fs-serve/root/src/deny/deny.txt",
    "content": "deny\n"
  },
  {
    "path": "playground/fs-serve/root/src/dummy.crt",
    "content": "secret\n"
  },
  {
    "path": "playground/fs-serve/root/src/index.html",
    "content": "<link rel=\"icon\" href=\"/src/favicon.ico\" />\n\n<h2>Normal Import</h2>\n<pre class=\"full\"></pre>\n<pre class=\"named\"></pre>\n\n<h2>Safe Fetch</h2>\n<pre class=\"safe-fetch-status\"></pre>\n<pre class=\"safe-fetch\"></pre>\n<pre class=\"safe-fetch-query-status\"></pre>\n<pre class=\"safe-fetch-query\"></pre>\n\n<h2>Safe Fetch Subdirectory</h2>\n<pre class=\"safe-fetch-subdir-status\"></pre>\n<pre class=\"safe-fetch-subdir\"></pre>\n<pre class=\"safe-fetch-subdir-special-characters-status\"></pre>\n<pre class=\"safe-fetch-subdir-special-characters\"></pre>\n\n<h2>Unsafe Fetch</h2>\n<pre class=\"unsafe-fetch-status\"></pre>\n<pre class=\"unsafe-fetch\"></pre>\n<pre class=\"unsafe-fetch-html-status\"></pre>\n<pre class=\"unsafe-fetch-html\"></pre>\n<pre class=\"unsafe-fetch-8498-status\"></pre>\n<pre class=\"unsafe-fetch-8498\"></pre>\n<pre class=\"unsafe-fetch-8498-2-status\"></pre>\n<pre class=\"unsafe-fetch-8498-2\"></pre>\n<pre class=\"unsafe-fetch-import-inline-status\"></pre>\n<pre class=\"unsafe-fetch-raw-query-import-status\"></pre>\n<pre class=\"unsafe-fetch-query-dot-svg-import-status\"></pre>\n<pre class=\"unsafe-fetch-svg-status\"></pre>\n\n<h2>Safe /@fs/ Fetch</h2>\n<pre class=\"safe-fs-fetch-status\"></pre>\n<pre class=\"safe-fs-fetch\"></pre>\n<pre class=\"safe-fs-fetch-query-status\"></pre>\n<pre class=\"safe-fs-fetch-query\"></pre>\n<pre class=\"safe-fs-fetch-special-characters-status\"></pre>\n<pre class=\"safe-fs-fetch-special-characters\"></pre>\n\n<h2>Unsafe /@fs/ Fetch</h2>\n<pre class=\"unsafe-fs-fetch-status\"></pre>\n<pre class=\"unsafe-fs-fetch\"></pre>\n<pre class=\"unsafe-fs-fetch-html-status\"></pre>\n<pre class=\"unsafe-fs-fetch-html\"></pre>\n<pre class=\"unsafe-fs-fetch-raw-status\"></pre>\n<pre class=\"unsafe-fs-fetch-raw\"></pre>\n<pre class=\"unsafe-fs-fetch-raw-query1-status\"></pre>\n<pre class=\"unsafe-fs-fetch-raw-query1\"></pre>\n<pre class=\"unsafe-fs-fetch-raw-query2-status\"></pre>\n<pre class=\"unsafe-fs-fetch-raw-query2\"></pre>\n<pre class=\"unsafe-fs-fetch-8498-status\"></pre>\n<pre class=\"unsafe-fs-fetch-8498\"></pre>\n<pre class=\"unsafe-fs-fetch-8498-2-status\"></pre>\n<pre class=\"unsafe-fs-fetch-8498-2\"></pre>\n<pre class=\"unsafe-fs-fetch-import-inline-status\"></pre>\n<pre class=\"unsafe-fs-fetch-import-inline-wasm-init-status\"></pre>\n<pre class=\"unsafe-fs-fetch-relative-path-after-query-status\"></pre>\n\n<h2>Nested Entry</h2>\n<pre class=\"nested-entry\"></pre>\n\n<h2>Denied</h2>\n<pre class=\"unsafe-dotenv\"></pre>\n<pre class=\"unsafe-dotEnV-casing\"></pre>\n<pre class=\"unsafe-dotenv-query-dot-svg-wasm-init\"></pre>\n\n<d2>Virtual SVG module</d2>\n<pre class=\"virtual-svg\"></pre>\n\n<script type=\"module\">\n  import '../../entry'\n  import json, { msg } from '../../safe.json'\n  import './code.js'\n\n  // Check virtual svg module still works\n  import fooSvg from 'virtual:foo.svg'\n\n  function joinUrlSegments(a, b) {\n    if (!a || !b) {\n      return a || b || ''\n    }\n    if (a.endsWith('/')) {\n      a = a.substring(0, a.length - 1)\n    }\n    if (b[0] !== '/') {\n      b = '/' + b\n    }\n    return a + b\n  }\n\n  text('.full', JSON.stringify(json))\n  text('.named', msg)\n  text('.virtual-svg', fooSvg)\n\n  const base = typeof BASE !== 'undefined' ? BASE : ''\n\n  // inside allowed dir, safe fetch\n  fetch(joinUrlSegments(base, '/src/safe.txt'))\n    .then((r) => {\n      text('.safe-fetch-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.safe-fetch', JSON.stringify(data))\n    })\n\n  // inside allowed dir with query, safe fetch\n  fetch(joinUrlSegments(base, '/src/safe.txt?query'))\n    .then((r) => {\n      text('.safe-fetch-query-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.safe-fetch-query', JSON.stringify(data))\n    })\n\n  // inside allowed dir, safe fetch\n  fetch(joinUrlSegments(base, '/src/subdir/safe.txt'))\n    .then((r) => {\n      text('.safe-fetch-subdir-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.safe-fetch-subdir', JSON.stringify(data))\n    })\n\n  // inside allowed dir, with special characters, safe fetch\n  fetch(\n    joinUrlSegments(\n      base,\n      '/src/special%20characters%20%C3%A5%C3%A4%C3%B6/safe.txt',\n    ),\n  )\n    .then((r) => {\n      text('.safe-fetch-subdir-special-characters-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.safe-fetch-subdir-special-characters', JSON.stringify(data))\n    })\n\n  // outside of allowed dir, treated as unsafe\n  fetch(joinUrlSegments(base, '/unsafe.txt'))\n    .then((r) => {\n      text('.unsafe-fetch-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.unsafe-fetch', data)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of allowed dir, treated as unsafe\n  fetch(joinUrlSegments(base, '/unsafe.html'))\n    .then((r) => {\n      text('.unsafe-fetch-html-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.unsafe-fetch-html', data)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of allowed dir with special characters #8498\n  fetch(joinUrlSegments(base, '/src/%2e%2e%2funsafe%2etxt'))\n    .then((r) => {\n      text('.unsafe-fetch-8498-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.unsafe-fetch-8498', data)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of allowed dir with special characters 2 #8498\n  fetch(joinUrlSegments(base, '/src/%252e%252e%252funsafe%252etxt'))\n    .then((r) => {\n      text('.unsafe-fetch-8498-2-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.unsafe-fetch-8498-2', data)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of allowed dir with import inline\n  fetch(joinUrlSegments(base, '/unsafe.txt?import&inline'))\n    .then((r) => {\n      text('.unsafe-fetch-import-inline-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of allowed dir with raw query import\n  fetch(joinUrlSegments(base, '/unsafe.txt?raw?import'))\n    .then((r) => {\n      text('.unsafe-fetch-raw-query-import-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of allowed dir with .svg query import\n  fetch(joinUrlSegments(base, '/unsafe.txt?.svg?import'))\n    .then((r) => {\n      text('.unsafe-fetch-query-dot-svg-import-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // svg outside of allowed dir, treated as unsafe\n  fetch(joinUrlSegments(base, '/unsafe.svg?import'))\n    .then((r) => {\n      text('.unsafe-fetch-svg-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // imported before, should be treated as safe\n  fetch(joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/safe.json'))\n    .then((r) => {\n      text('.safe-fs-fetch-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.safe-fs-fetch', JSON.stringify(data))\n    })\n\n  // imported before with query, should be treated as safe\n  fetch(\n    joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/safe.json?query'),\n  )\n    .then((r) => {\n      text('.safe-fs-fetch-query-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.safe-fs-fetch-query', JSON.stringify(data))\n    })\n\n  // not imported before, outside of root, treated as unsafe\n  fetch(joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/unsafe.json'))\n    .then((r) => {\n      text('.unsafe-fs-fetch-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch', JSON.stringify(data))\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // not imported before, outside of root, treated as unsafe\n  fetch(joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/unsafe.html'))\n    .then((r) => {\n      text('.unsafe-fs-fetch-html-status', r.status)\n      return r.text()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch-html', data)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // not imported before, outside of root, treated as unsafe\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-raw-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch-raw', JSON.stringify(data))\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw??',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-raw-query1-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch-raw-query1', JSON.stringify(data))\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) + '/unsafe.json?import&raw?&',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-raw-query2-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch-raw-query2', JSON.stringify(data))\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of root inline\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) + '/root/unsafe.txt?import&inline',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-import-inline-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of root inline, faux wasm?init\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) +\n        '/root/unsafe.txt?import&?inline=1.wasm?init',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-import-inline-wasm-init-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside of root with relative path after query\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) +\n        '/root/src/?/../../unsafe.txt?import&raw',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-relative-path-after-query-status', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // outside root with special characters #8498\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) +\n        '/root/src/%2e%2e%2f%2e%2e%2funsafe%2ejson',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-8498-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch-8498', JSON.stringify(data))\n    })\n\n  // outside root with special characters 2 #8498\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) +\n        '/root/src/%252e%252e%252f%252e%252e%252funsafe%252ejson',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-fs-fetch-8498-2-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.unsafe-fs-fetch-8498-2', JSON.stringify(data))\n    })\n\n  // not imported before, inside root with special characters, treated as safe\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) +\n        '/root/src/special%20characters%20%C3%A5%C3%A4%C3%B6/safe.json',\n    ),\n  )\n    .then((r) => {\n      text('.safe-fs-fetch-special-characters-status', r.status)\n      return r.json()\n    })\n    .then((data) => {\n      text('.safe-fs-fetch-special-characters', JSON.stringify(data))\n    })\n\n  // .env, denied by default\n  fetch(\n    joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/root/src/.env'),\n  )\n    .then((r) => {\n      text('.unsafe-dotenv', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // .env, for case insensitive file systems\n  fetch(\n    joinUrlSegments(base, joinUrlSegments('/@fs/', ROOT) + '/root/src/.EnV'),\n  )\n    .then((r) => {\n      text('.unsafe-dotEnV-casing', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  // .env with .svg?.wasm?init\n  fetch(\n    joinUrlSegments(\n      base,\n      joinUrlSegments('/@fs/', ROOT) + '/root/src/.env?.svg?.wasm?init',\n    ),\n  )\n    .then((r) => {\n      text('.unsafe-dotenv-query-dot-svg-wasm-init', r.status)\n    })\n    .catch((e) => {\n      console.error(e)\n    })\n\n  function text(sel, text) {\n    document.querySelector(sel).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/fs-serve/root/src/safe.txt",
    "content": "KEY=safe\n"
  },
  {
    "path": "playground/fs-serve/root/src/special characters åäö/safe.json",
    "content": "{\n  \"msg\": \"safe\"\n}\n"
  },
  {
    "path": "playground/fs-serve/root/src/special characters åäö/safe.txt",
    "content": "KEY=safe\n"
  },
  {
    "path": "playground/fs-serve/root/src/subdir/safe.txt",
    "content": "KEY=safe\n"
  },
  {
    "path": "playground/fs-serve/root/svgVirtualModulePlugin.ts",
    "content": "import type { Plugin } from 'vite'\nconst svgVirtualModuleId = 'virtual:foo.svg'\nconst resolvedSvgVirtualModuleId = '\\0' + svgVirtualModuleId\n\nexport default function svgVirtualModulePlugin(): Plugin {\n  return {\n    name: 'svg-virtual-module',\n    resolveId(id) {\n      if (id === svgVirtualModuleId) {\n        return resolvedSvgVirtualModuleId\n      }\n    },\n    async load(id, _options) {\n      if (id === resolvedSvgVirtualModuleId) {\n        return `export default '<svg><rect width=\"100\" height=\"100\"></svg>'`\n      }\n    },\n    enforce: 'pre',\n  }\n}\n"
  },
  {
    "path": "playground/fs-serve/root/unsafe.html",
    "content": "<p>unsafe</p>\n"
  },
  {
    "path": "playground/fs-serve/root/unsafe.txt",
    "content": "KEY=unsafe\n"
  },
  {
    "path": "playground/fs-serve/root/vite.config-base.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\nimport svgVirtualModulePlugin from './svgVirtualModulePlugin'\n\nconst BASE = '/base/'\n\nexport default defineConfig({\n  base: BASE,\n  build: {\n    rollupOptions: {\n      input: {\n        main: path.resolve(import.meta.dirname, 'src/index.html'),\n      },\n    },\n  },\n  server: {\n    fs: {\n      strict: true,\n      allow: [path.resolve(import.meta.dirname, 'src')],\n    },\n    hmr: {\n      overlay: false,\n    },\n    headers: {\n      'x-served-by': 'vite',\n    },\n  },\n  preview: {\n    headers: {\n      'x-served-by': 'vite',\n    },\n  },\n  define: {\n    ROOT: JSON.stringify(path.dirname(import.meta.dirname).replace(/\\\\/g, '/')),\n    BASE: JSON.stringify(BASE),\n  },\n  plugins: [svgVirtualModulePlugin()],\n})\n"
  },
  {
    "path": "playground/fs-serve/root/vite.config-deny.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\nimport svgVirtualModulePlugin from './svgVirtualModulePlugin'\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      input: {\n        main: path.resolve(import.meta.dirname, 'src/index.html'),\n      },\n    },\n  },\n  server: {\n    fs: {\n      strict: true,\n      allow: [path.resolve(import.meta.dirname, 'src')],\n      deny: ['**/deny/**'],\n    },\n  },\n  define: {\n    ROOT: JSON.stringify(path.dirname(import.meta.dirname).replace(/\\\\/g, '/')),\n  },\n  plugins: [svgVirtualModulePlugin()],\n})\n"
  },
  {
    "path": "playground/fs-serve/root/vite.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\nimport svgVirtualModulePlugin from './svgVirtualModulePlugin'\n\nexport default defineConfig({\n  build: {\n    rollupOptions: {\n      input: {\n        main: path.resolve(import.meta.dirname, 'src/index.html'),\n      },\n    },\n  },\n  server: {\n    fs: {\n      strict: true,\n      allow: [path.resolve(import.meta.dirname, 'src')],\n    },\n    hmr: {\n      overlay: false,\n    },\n    headers: {\n      'x-served-by': 'vite',\n    },\n  },\n  preview: {\n    headers: {\n      'x-served-by': 'vite',\n    },\n  },\n  define: {\n    ROOT: JSON.stringify(path.dirname(import.meta.dirname).replace(/\\\\/g, '/')),\n  },\n  plugins: [svgVirtualModulePlugin()],\n})\n"
  },
  {
    "path": "playground/fs-serve/safe.json",
    "content": "{\n  \"msg\": \"safe\"\n}\n"
  },
  {
    "path": "playground/fs-serve/unsafe.html",
    "content": "<p>unsafe outside root</p>\n"
  },
  {
    "path": "playground/fs-serve/unsafe.json",
    "content": "{\n  \"msg\": \"unsafe\"\n}\n"
  },
  {
    "path": "playground/glob-import/__tests__/glob-import.spec.ts",
    "content": "import path from 'node:path'\nimport { readdir } from 'node:fs/promises'\nimport { expect, test } from 'vitest'\nimport {\n  addFile,\n  editFile,\n  findAssetFile,\n  isBuild,\n  page,\n  removeFile,\n} from '~utils'\n\nconst filteredResult = {\n  './alias.js': {\n    default: 'hi',\n  },\n  './foo.js': {\n    msg: 'foo',\n  },\n  \"./quote'.js\": {\n    msg: 'single-quote',\n  },\n}\n\nconst json = {\n  msg: 'baz',\n  default: {\n    msg: 'baz',\n  },\n}\n\nconst globWithAlias = {\n  '/dir/alias.js': {\n    default: 'hi',\n  },\n}\n\nconst allResult = {\n  // JSON file should be properly transformed\n  '/dir/alias.js': {\n    default: 'hi',\n  },\n  '/dir/baz.json': json,\n  '/dir/foo.css': {},\n  '/dir/foo.js': {\n    msg: 'foo',\n  },\n  '/dir/index.js': isBuild\n    ? {\n        modules: filteredResult,\n        globWithAlias,\n      }\n    : {\n        globWithAlias,\n        modules: filteredResult,\n      },\n  '/dir/nested/bar.js': {\n    modules: {\n      '../baz.json': json,\n    },\n    msg: 'bar',\n  },\n  \"/dir/quote'.js\": {\n    msg: 'single-quote',\n  },\n}\n\nconst nodeModulesResult = {\n  '/dir/node_modules/hoge.js': { msg: 'hoge' },\n}\n\nconst rawResult = {\n  '/dir/baz.json': {\n    msg: 'baz',\n  },\n}\n\nconst relativeRawResult = {\n  './dir/baz.json': {\n    msg: 'baz',\n  },\n}\n\nconst baseRawResult = {\n  './baz.json': {\n    msg: 'baz',\n  },\n}\n\ntest('should work', async () => {\n  await expect\n    .poll(async () => JSON.parse(await page.textContent('.result')))\n    .toStrictEqual(allResult)\n  await expect\n    .poll(async () => JSON.parse(await page.textContent('.result-eager')))\n    .toStrictEqual(allResult)\n  await expect\n    .poll(async () =>\n      JSON.parse(await page.textContent('.result-node_modules')),\n    )\n    .toStrictEqual(nodeModulesResult)\n})\n\ntest('import glob raw', async () => {\n  expect(await page.textContent('.globraw')).toBe(\n    JSON.stringify(rawResult, null, 2),\n  )\n})\n\ntest('import property access', async () => {\n  expect(await page.textContent('.property-access')).toBe(\n    JSON.stringify(rawResult['/dir/baz.json'], null, 2),\n  )\n})\n\ntest('import relative glob raw', async () => {\n  expect(await page.textContent('.relative-glob-raw')).toBe(\n    JSON.stringify(relativeRawResult, null, 2),\n  )\n})\n\ntest('unassigned import processes', async () => {\n  expect(await page.textContent('.side-effect-result')).toBe(\n    'Hello from side effect',\n  )\n})\n\ntest('import glob in package', async () => {\n  expect(await page.textContent('.in-package')).toBe(\n    JSON.stringify(['/pkg-pages/foo.js']),\n  )\n})\n\nif (!isBuild) {\n  test('hmr for adding/removing files', async () => {\n    const resultElement = page.locator('.result')\n\n    addFile('dir/a.js', '')\n    await expect\n      .poll(async () => {\n        const actualAdd = await resultElement.textContent()\n        return JSON.parse(actualAdd)\n      })\n      .toStrictEqual({\n        '/dir/a.js': {},\n        ...allResult,\n        '/dir/index.js': {\n          ...allResult['/dir/index.js'],\n          modules: {\n            './a.js': {},\n            ...allResult['/dir/index.js'].modules,\n          },\n        },\n      })\n\n    // edit the added file\n    editFile('dir/a.js', () => 'export const msg =\"a\"')\n    await expect\n      .poll(async () => {\n        const actualEdit = await resultElement.textContent()\n        return JSON.parse(actualEdit)\n      })\n      .toStrictEqual({\n        '/dir/a.js': {\n          msg: 'a',\n        },\n        ...allResult,\n        '/dir/index.js': {\n          ...allResult['/dir/index.js'],\n          modules: {\n            './a.js': {\n              msg: 'a',\n            },\n            ...allResult['/dir/index.js'].modules,\n          },\n        },\n      })\n\n    removeFile('dir/a.js')\n    await expect\n      .poll(async () => {\n        const actualRemove = await resultElement.textContent()\n        return JSON.parse(actualRemove)\n      })\n      .toStrictEqual(allResult)\n  })\n\n  test('no hmr for adding/removing files', async () => {\n    let request = page.waitForResponse(/dir\\/index\\.js$/, { timeout: 200 })\n    addFile('nohmr.js', '')\n    let response = await request.catch(() => ({ status: () => -1 }))\n    expect(response.status()).toBe(-1)\n\n    request = page.waitForResponse(/dir\\/index\\.js$/, { timeout: 200 })\n    removeFile('nohmr.js')\n    response = await request.catch(() => ({ status: () => -1 }))\n    expect(response.status()).toBe(-1)\n  })\n\n  test('hmr for adding/removing files in package', async () => {\n    const resultElement = page.locator('.in-package')\n\n    addFile('pkg-pages/bar.js', '// empty')\n    await expect\n      .poll(async () => JSON.parse(await resultElement.textContent()))\n      .toStrictEqual(['/pkg-pages/foo.js', '/pkg-pages/bar.js'].sort())\n\n    removeFile('pkg-pages/bar.js')\n    await expect\n      .poll(async () => JSON.parse(await resultElement.textContent()))\n      .toStrictEqual(['/pkg-pages/foo.js'])\n  })\n\n  test('hmr for adding/removing files with array patterns and exclusions', async () => {\n    const resultElement = page.locator('.array-result')\n    await expect\n      .poll(async () => JSON.parse(await resultElement.textContent()))\n      .toStrictEqual({\n        './array-test-dir/included.js': 'included',\n      })\n\n    addFile('array-test-dir/new-file.js', 'export default \"new\"')\n    await expect\n      .poll(async () => JSON.parse(await resultElement.textContent()))\n      .toStrictEqual({\n        './array-test-dir/included.js': 'included',\n        './array-test-dir/new-file.js': 'new',\n      })\n\n    removeFile('array-test-dir/new-file.js')\n    await expect\n      .poll(async () => JSON.parse(await resultElement.textContent()))\n      .toStrictEqual({\n        './array-test-dir/included.js': 'included',\n      })\n  })\n}\n\ntest('array pattern with exclusions', async () => {\n  await expect\n    .poll(async () => JSON.parse(await page.textContent('.array-result')))\n    .toStrictEqual({\n      './array-test-dir/included.js': 'included',\n    })\n})\n\ntest('tree-shake eager css', async () => {\n  expect(await page.textContent('.no-tree-shake-eager-css-result')).toMatch(\n    '.no-tree-shake-eager-css',\n  )\n\n  if (isBuild) {\n    const content = findAssetFile(/index-[-\\w]+\\.js/)\n    expect(content).not.toMatch('.tree-shake-eager-css')\n  }\n})\n\ntest('escapes special chars in globs without mangling user supplied glob suffix', async () => {\n  // the escape dir contains subdirectories where each has a name that needs escaping for glob safety\n  // inside each of them is a glob.js that exports the result of a relative glob `./**/*.js`\n  // and an alias glob `@escape_<dirname>_mod/**/*.js`. The matching aliases are generated in vite.config.ts\n  // index.html has a script that loads all these glob.js files and prints the globs that returned the expected result\n  // this test finally compares the printed output of index.js with the list of directories with special chars,\n  // expecting that they all work\n  const files = await readdir(path.join(import.meta.dirname, '..', 'escape'), {\n    withFileTypes: true,\n  })\n  const expectedNames = files\n    .filter((f) => f.isDirectory())\n    .map((f) => `/escape/${f.name}/glob.js`)\n    .sort()\n  await expect\n    .poll(async () => {\n      const text = await page.textContent('.escape-relative')\n      return text.split('\\n').sort()\n    })\n    .toEqual(expectedNames)\n  await expect\n    .poll(async () => {\n      const text = await page.textContent('.escape-alias')\n      return text.split('\\n').sort()\n    })\n    .toEqual(expectedNames)\n})\n\ntest('subpath imports', async () => {\n  await expect\n    .poll(async () => await page.textContent('.subpath-imports'))\n    .toMatch('bar foo')\n})\n\ntest('#alias imports', async () => {\n  await expect\n    .poll(async () => await page.textContent('.hash-alias-imports'))\n    .toMatch('bar foo')\n})\n\ntest('import base glob raw', async () => {\n  await expect\n    .poll(async () => await page.textContent('.result-base'))\n    .toBe(JSON.stringify(baseRawResult, null, 2))\n})\n\ntest('import.meta.glob and dynamic import vars transformations should be visible to post transform plugins', async () => {\n  await expect\n    .poll(async () => await page.textContent('.transform-visibility'))\n    .toBe(\n      JSON.stringify({ globTransformed: true, dynamicImportTransformed: true }),\n    )\n})\n"
  },
  {
    "path": "playground/glob-import/array-test-dir/excluded.js",
    "content": "export default 'excluded'\n"
  },
  {
    "path": "playground/glob-import/array-test-dir/included.js",
    "content": "export default 'included'\n"
  },
  {
    "path": "playground/glob-import/dir/alias.js",
    "content": "export default 'hi'\n"
  },
  {
    "path": "playground/glob-import/dir/baz.json",
    "content": "{\n  \"msg\": \"baz\"\n}\n"
  },
  {
    "path": "playground/glob-import/dir/foo.css",
    "content": ".foo {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/glob-import/dir/foo.js",
    "content": "export const msg = 'foo'\n"
  },
  {
    "path": "playground/glob-import/dir/index.js",
    "content": "const modules = import.meta.glob('./*.{js,ts}', { eager: true })\nconst globWithAlias = import.meta.glob('@dir/al*.js', { eager: true })\n\n// test negative glob\nimport.meta.glob(['@dir/*.js', '!@dir/x.js'])\nimport.meta.glob(['!@dir/x.js', '@dir/*.js'])\n\n// test for sourcemap\nconsole.log('hello')\n\nexport { modules, globWithAlias }\n"
  },
  {
    "path": "playground/glob-import/dir/nested/bar.js",
    "content": "const modules = import.meta.glob('../*.json', { eager: true })\n\nexport const msg = 'bar'\nexport { modules }\n"
  },
  {
    "path": "playground/glob-import/dir/quote'.js",
    "content": "export const msg = 'single-quote'\n"
  },
  {
    "path": "playground/glob-import/escape/(parenthesis)/glob.js",
    "content": "const relative = import.meta.glob('./**/*.js', { eager: true })\nconst alias = import.meta.glob('@escape_(parenthesis)_mod/**/*.js', {\n  eager: true,\n})\nexport { relative, alias }\n"
  },
  {
    "path": "playground/glob-import/escape/(parenthesis)/mod/index.js",
    "content": "export const msg = 'foo'\n"
  },
  {
    "path": "playground/glob-import/escape/[brackets]/glob.js",
    "content": "const relative = import.meta.glob('./**/*.js', { eager: true })\nconst alias = import.meta.glob('@escape_[brackets]_mod/**/*.js', {\n  eager: true,\n})\nexport { relative, alias }\n"
  },
  {
    "path": "playground/glob-import/escape/[brackets]/mod/index.js",
    "content": "export const msg = 'foo'\n"
  },
  {
    "path": "playground/glob-import/escape/{curlies}/glob.js",
    "content": "const relative = import.meta.glob('./**/*.js', { eager: true })\nconst alias = import.meta.glob('@escape_{curlies}_mod/**/*.js', { eager: true })\nexport { relative, alias }\n"
  },
  {
    "path": "playground/glob-import/escape/{curlies}/mod/index.js",
    "content": "export const msg = 'foo'\n"
  },
  {
    "path": "playground/glob-import/import-meta-glob-pkg/index.js",
    "content": "export const g = import.meta.glob('/pkg-pages/*.js')\ndocument.querySelector('.in-package').textContent = JSON.stringify(\n  Object.keys(g).sort(),\n)\n"
  },
  {
    "path": "playground/glob-import/import-meta-glob-pkg/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-import-meta-glob-pkg\",\n  \"type\": \"module\",\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "playground/glob-import/imports-path/bar.js",
    "content": "export default 'bar'\n"
  },
  {
    "path": "playground/glob-import/imports-path/foo.js",
    "content": "export default 'foo'\n"
  },
  {
    "path": "playground/glob-import/index.html",
    "content": "<h1>Glob import</h1>\n<h2>Normal</h2>\n<pre class=\"result\"></pre>\n<h2>Eager</h2>\n<pre class=\"result-eager\"></pre>\n<h2>node_modules</h2>\n<pre class=\"result-node_modules\"></pre>\n<h2>Raw</h2>\n<pre class=\"globraw\"></pre>\n<h2>Property access</h2>\n<pre class=\"property-access\"></pre>\n<h2>Relative raw</h2>\n<pre class=\"relative-glob-raw\"></pre>\n<h2>Side effect</h2>\n<pre class=\"side-effect-result\"></pre>\n<h2>Tree shake Eager CSS</h2>\n<p class=\"tree-shake-eager-css\">Should be orange</p>\n<p class=\"no-tree-shake-eager-css\">Should be orange</p>\n<pre class=\"no-tree-shake-eager-css-result\"></pre>\n<h2>Escape relative glob</h2>\n<pre class=\"escape-relative\"></pre>\n<h2>Escape alias glob</h2>\n<pre class=\"escape-alias\"></pre>\n<h2>Subpath imports</h2>\n<pre class=\"subpath-imports\"></pre>\n<h2>#alias imports</h2>\n<pre class=\"hash-alias-imports\"></pre>\n<h2>In package</h2>\n<pre class=\"in-package\"></pre>\n<h2>Base</h2>\n<pre class=\"result-base\"></pre>\n\n<script type=\"module\" src=\"./dir/index.js\"></script>\n<script type=\"module\">\n  function useImports(modules, selector) {\n    const keys = Object.keys(modules)\n    Promise.all(keys.map((key) => modules[key]())).then((mods) => {\n      const res = {}\n      mods.forEach((m, i) => {\n        res[keys[i]] = m\n      })\n      document.querySelector(selector).textContent = JSON.stringify(\n        res,\n        null,\n        2,\n      )\n    })\n  }\n\n  const modules = import.meta.glob(\n    '/dir/**',\n    // for test: annotation contain \")\"\n    /*\n     * for test: annotation contain \")\"\n     * */\n  )\n  useImports(modules, '.result')\n  const eagerModules = import.meta.glob('/dir/**', { eager: true })\n  document.querySelector('.result-eager').textContent = JSON.stringify(\n    eagerModules,\n    null,\n    2,\n  )\n\n  const nodeModules = import.meta.glob('/dir/node_modules/**')\n  useImports(nodeModules, '.result-node_modules')\n</script>\n\n<script type=\"module\">\n  const rawModules = import.meta.glob('/dir/*.json', {\n    query: '?raw',\n    eager: true,\n    import: 'default',\n  })\n  const globraw = {}\n  Object.keys(rawModules).forEach((key) => {\n    globraw[key] = JSON.parse(rawModules[key])\n  })\n  document.querySelector('.globraw').textContent = JSON.stringify(\n    globraw,\n    null,\n    2,\n  )\n</script>\n\n<script type=\"module\">\n  const bazJson = import.meta.glob('/dir/*.json', {\n    query: '?raw',\n    eager: true,\n    import: 'default',\n  })['/dir/baz.json']\n  document.querySelector('.property-access').textContent = JSON.stringify(\n    JSON.parse(bazJson),\n    null,\n    2,\n  )\n</script>\n\n<script type=\"module\">\n  const relativeRawModules = import.meta.glob('../glob-import/dir/*.json', {\n    query: '?raw',\n    eager: true,\n    import: 'default',\n  })\n  const relativeGlobRaw = {}\n  Object.keys(relativeRawModules).forEach((key) => {\n    relativeGlobRaw[key] = JSON.parse(relativeRawModules[key])\n  })\n  document.querySelector('.relative-glob-raw').textContent = JSON.stringify(\n    relativeGlobRaw,\n    null,\n    2,\n  )\n</script>\n\n<script type=\"module\">\n  const neverInvoke = () =>\n    (document.querySelector('.side-effect-result').textContent =\n      \"Syntax generated from 'import.meta.glob' must do ASI.\")\n  const notInvocation = neverInvoke\n  import.meta.glob('/side-effect/**', { eager: true })\n</script>\n\n<script type=\"module\">\n  import.meta.glob('/tree-shake.css', { eager: true, query: { inline: true } })\n  const results = import.meta.glob('/no-tree-shake.css', {\n    eager: true,\n    query: { inline: true },\n  })\n  document.querySelector('.no-tree-shake-eager-css-result').textContent =\n    results['/no-tree-shake.css'].default\n</script>\n\n<script type=\"module\">\n  const globs = import.meta.glob('/escape/**/glob.js', {\n    eager: true,\n  })\n  globalThis.globs = globs\n  const relative = Object.entries(globs)\n    .filter(([_, mod]) => Object.keys(mod?.relative ?? {}).length === 1)\n    .map(([glob]) => glob)\n  document.querySelector('.escape-relative').textContent = relative\n    .sort()\n    .join('\\n')\n  const alias = Object.entries(globs)\n    .filter(([_, mod]) => Object.keys(mod?.alias ?? {}).length === 1)\n    .map(([glob]) => glob)\n  document.querySelector('.escape-alias').textContent = alias.sort().join('\\n')\n</script>\n\n<script type=\"module\">\n  const subpathImports = import.meta.glob('#imports/*', { eager: true })\n  document.querySelector('.subpath-imports').textContent = Object.values(\n    subpathImports,\n  )\n    .map((mod) => mod.default)\n    .join(' ')\n</script>\n\n<script type=\"module\">\n  const hashAliasImports = import.meta.glob('#alias/*', { eager: true })\n  document.querySelector('.hash-alias-imports').textContent = Object.values(\n    hashAliasImports,\n  )\n    .map((mod) => mod.default)\n    .join(' ')\n</script>\n\n<script type=\"module\">\n  import '@vitejs/test-import-meta-glob-pkg'\n</script>\n\n<script type=\"module\">\n  const baseModules = import.meta.glob('./*.json', {\n    query: '?raw',\n    eager: true,\n    import: 'default',\n    base: './dir',\n  })\n  const globBase = {}\n  Object.keys(baseModules).forEach((key) => {\n    globBase[key] = JSON.parse(baseModules[key])\n  })\n  document.querySelector('.result-base').textContent = JSON.stringify(\n    globBase,\n    null,\n    2,\n  )\n</script>\n\n<h2>Array Pattern with Exclusions</h2>\n<pre class=\"array-result\"></pre>\n\n<script type=\"module\">\n  const arrayModules = import.meta.glob(\n    ['./array-test-dir/*.js', '!./array-test-dir/excluded.js'],\n    {\n      eager: true,\n      import: 'default',\n    },\n  )\n  document.querySelector('.array-result').textContent = JSON.stringify(\n    arrayModules,\n    null,\n    2,\n  )\n</script>\n\n<h2>Transform visibility</h2>\n<pre class=\"transform-visibility\"></pre>\n\n<script type=\"module\">\n  import result from './transform-visibility.js'\n  document.querySelector('.transform-visibility').textContent =\n    JSON.stringify(result)\n</script>\n"
  },
  {
    "path": "playground/glob-import/no-tree-shake.css",
    "content": ".no-tree-shake-eager-css {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/glob-import/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-import-context\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"imports\": {\n    \"#imports/*\": \"./imports-path/*\"\n  },\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-import-meta-glob-pkg\": \"file:./import-meta-glob-pkg\"\n  }\n}\n"
  },
  {
    "path": "playground/glob-import/pkg-pages/foo.js",
    "content": "// empty\n"
  },
  {
    "path": "playground/glob-import/side-effect/writedom.js",
    "content": "/* global document */\ndocument &&\n  (document.querySelector('.side-effect-result').textContent =\n    'Hello from side effect')\n"
  },
  {
    "path": "playground/glob-import/side-effect/writetodom.js",
    "content": "/* global document */\ndocument &&\n  (document.querySelector('.side-effect-result').textContent =\n    'Hello from side effect')\n"
  },
  {
    "path": "playground/glob-import/transform-visibility.js",
    "content": "const name = 'foo'\nexport const globResult = import.meta.glob('./dir/*.js')\nexport const dynamicResult = import(`./dir/${name}.js`)\n"
  },
  {
    "path": "playground/glob-import/tree-shake.css",
    "content": ".tree-shake-eager-css {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/glob-import/vite.config.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst escapeAliases = fs\n  .readdirSync(path.join(import.meta.dirname, 'escape'), {\n    withFileTypes: true,\n  })\n  .filter((f) => f.isDirectory())\n  .map((f) => f.name)\n  .reduce((aliases: Record<string, string>, dir) => {\n    aliases[`@escape_${dir}_mod`] = path.resolve(\n      import.meta.dirname,\n      `./escape/${dir}/mod`,\n    )\n    return aliases\n  }, {})\n\nconst transformVisibilityPlugin = {\n  name: 'test:transform-visibility',\n  enforce: 'post',\n  transform(code: string, id: string) {\n    if (id.endsWith('transform-visibility.js')) {\n      const globTransformed = !code.includes('import.meta.glob')\n      const dynamicImportTransformed = code.includes(\n        '__variableDynamicImportRuntimeHelper',\n      )\n      return `export default ${JSON.stringify({ globTransformed, dynamicImportTransformed })}`\n    }\n  },\n}\n\nexport default defineConfig({\n  plugins: [transformVisibilityPlugin],\n  resolve: {\n    alias: {\n      ...escapeAliases,\n      '@dir': path.resolve(import.meta.dirname, './dir/'),\n      '#alias': path.resolve(import.meta.dirname, './imports-path/'),\n    },\n  },\n  build: {\n    sourcemap: true,\n    rollupOptions: {\n      output: {\n        // manualChunks(id) {\n        //   if (id.includes('foo.css')) {\n        //     return 'foo_css'\n        //   }\n        // },\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/hmr/__tests__/hmr.spec.ts",
    "content": "import { stripVTControlCharacters } from 'node:util'\nimport { beforeAll, describe, expect, it, test } from 'vitest'\nimport type { Page } from 'playwright-chromium'\nimport {\n  addFile,\n  browser,\n  browserLogs,\n  editFile,\n  getBg,\n  getColor,\n  isBuild,\n  page,\n  readFile,\n  removeFile,\n  serverLogs,\n  untilBrowserLogAfter,\n  viteTestUrl,\n} from '~utils'\n\ntest('should render', async () => {\n  expect(await page.textContent('.app')).toBe('1')\n  expect(await page.textContent('.dep')).toBe('1')\n  expect(await page.textContent('.nested')).toBe('1')\n})\n\nif (!isBuild) {\n  test('should connect', async () => {\n    expect(browserLogs.length).toBe(5)\n    expect(browserLogs.some((msg) => msg.includes('connected'))).toBe(true)\n    browserLogs.length = 0\n  })\n\n  const fetchHotEvents = async (): Promise<{\n    connectCount: number\n    disconnectCount: number\n  }> => {\n    const res = await fetch(viteTestUrl + '/hot-events-counts')\n    return res.json()\n  }\n  test('hot events', async () => {\n    expect(await fetchHotEvents()).toStrictEqual({\n      connectCount: 1,\n      disconnectCount: 0,\n    })\n    await untilBrowserLogAfter(() => page.reload(), [/connected/])\n    expect(await fetchHotEvents()).toStrictEqual({\n      connectCount: 2,\n      disconnectCount: 1,\n    })\n  })\n\n  test('self accept', async () => {\n    const el = await page.$('.app')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('hmr.ts', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        'foo was: 1',\n        '(self-accepting 1) foo is now: 2',\n        '(self-accepting 2) foo is now: 2',\n        '[vite] hot updated: /hmr.ts',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('2')\n\n    await untilBrowserLogAfter(\n      () =>\n        editFile('hmr.ts', (code) =>\n          code.replace('const foo = 2', 'const foo = 3'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        'foo was: 2',\n        '(self-accepting 1) foo is now: 3',\n        '(self-accepting 2) foo is now: 3',\n        '[vite] hot updated: /hmr.ts',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('3')\n  })\n\n  test('accept dep', async () => {\n    const el = await page.$('.dep')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('hmrDep.js', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 1',\n        '(dep) foo from dispose: 1',\n        '(single dep) foo is now: 2',\n        '(single dep) nested foo is now: 1',\n        '(multi deps) foo is now: 2',\n        '(multi deps) nested foo is now: 1',\n        '[vite] hot updated: /hmrDep.js via /hmr.ts',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('2')\n\n    await untilBrowserLogAfter(\n      () =>\n        editFile('hmrDep.js', (code) =>\n          code.replace('const foo = 2', 'const foo = 3'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 2',\n        '(dep) foo from dispose: 2',\n        '(single dep) foo is now: 3',\n        '(single dep) nested foo is now: 1',\n        '(multi deps) foo is now: 3',\n        '(multi deps) nested foo is now: 1',\n        '[vite] hot updated: /hmrDep.js via /hmr.ts',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('3')\n  })\n\n  test('nested dep propagation', async () => {\n    const el = await page.$('.nested')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('hmrNestedDep.js', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 3',\n        '(dep) foo from dispose: 3',\n        '(single dep) foo is now: 3',\n        '(single dep) nested foo is now: 2',\n        '(multi deps) foo is now: 3',\n        '(multi deps) nested foo is now: 2',\n        '[vite] hot updated: /hmrDep.js via /hmr.ts',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('2')\n\n    await untilBrowserLogAfter(\n      () =>\n        editFile('hmrNestedDep.js', (code) =>\n          code.replace('const foo = 2', 'const foo = 3'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 3',\n        '(dep) foo from dispose: 3',\n        '(single dep) foo is now: 3',\n        '(single dep) nested foo is now: 3',\n        '(multi deps) foo is now: 3',\n        '(multi deps) nested foo is now: 3',\n        '[vite] hot updated: /hmrDep.js via /hmr.ts',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('3')\n  })\n\n  test('invalidate', async () => {\n    const el = await page.$('.invalidation-parent')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('invalidation/child.js', (code) =>\n          code.replace('child', 'child updated'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '>>> vite:invalidate -- /invalidation/child.js',\n        '[vite] invalidate /invalidation/child.js',\n        '[vite] hot updated: /invalidation/child.js',\n        '>>> vite:afterUpdate -- update',\n        '>>> vite:beforeUpdate -- update',\n        '(invalidation) parent is executing',\n        '[vite] hot updated: /invalidation/parent.js',\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el.textContent()).toMatch('child updated')\n  })\n\n  test('invalidate works with multiple tabs', async () => {\n    let page2: Page\n    try {\n      page2 = await browser.newPage()\n      await page2.goto(viteTestUrl)\n\n      const el = await page.$('.invalidation-parent')\n      await untilBrowserLogAfter(\n        () =>\n          editFile('invalidation/child.js', (code) =>\n            code.replace('child', 'child updated'),\n          ),\n        [\n          '>>> vite:beforeUpdate -- update',\n          '>>> vite:invalidate -- /invalidation/child.js',\n          '[vite] invalidate /invalidation/child.js',\n          '[vite] hot updated: /invalidation/child.js',\n          '>>> vite:afterUpdate -- update',\n          // if invalidate dedupe doesn't work correctly, this beforeUpdate will be called twice\n          '>>> vite:beforeUpdate -- update',\n          '(invalidation) parent is executing',\n          '[vite] hot updated: /invalidation/parent.js',\n          '>>> vite:afterUpdate -- update',\n        ],\n        true,\n      )\n      await expect.poll(() => el.textContent()).toMatch('child updated')\n    } finally {\n      await page2.close()\n    }\n  })\n\n  test('invalidate on root triggers page reload', async () => {\n    editFile('invalidation/root.js', (code) => code.replace('Init', 'Updated'))\n    await page.waitForEvent('load')\n    await expect\n      .poll(async () => (await page.$('.invalidation-root')).textContent())\n      .toMatch('Updated')\n  })\n\n  test('soft invalidate', async () => {\n    const el = await page.$('.soft-invalidation')\n    expect(await el.textContent()).toBe(\n      'soft-invalidation/index.js is transformed 1 times. child is bar',\n    )\n    editFile('soft-invalidation/child.js', (code) =>\n      code.replace('bar', 'updated'),\n    )\n    await expect\n      .poll(() => el.textContent())\n      .toBe(\n        'soft-invalidation/index.js is transformed 1 times. child is updated',\n      )\n\n    editFile('soft-invalidation/index.js', (code) =>\n      code.replace('child is', 'child is now'),\n    )\n    editFile('soft-invalidation/child.js', (code) =>\n      code.replace('updated', 'updated?'),\n    )\n    await expect\n      .poll(() => el.textContent())\n      .toBe(\n        'soft-invalidation/index.js is transformed 2 times. child is now updated?',\n      )\n  })\n\n  test('invalidate in circular dep should not trigger infinite HMR', async () => {\n    const el = await page.$('.invalidation-circular-deps')\n    await expect.poll(() => el.textContent()).toMatch('child')\n    editFile(\n      'invalidation-circular-deps/circular-invalidate/child.js',\n      (code) => code.replace('child', 'child updated'),\n    )\n    await page.waitForEvent('load')\n    await expect\n      .poll(() => page.textContent('.invalidation-circular-deps'))\n      .toMatch('child updated')\n  })\n\n  test('invalidate in circular dep should be hot updated if possible', async () => {\n    const el = await page.$('.invalidation-circular-deps-handled')\n    await expect.poll(() => el.textContent()).toMatch('child')\n    editFile(\n      'invalidation-circular-deps/invalidate-handled-in-circle/child.js',\n      (code) => code.replace('child', 'child updated'),\n    )\n    await expect.poll(() => el.textContent()).toMatch('child updated')\n  })\n\n  test('plugin hmr handler + custom event', async () => {\n    const el = await page.$('.custom')\n    editFile('customFile.js', (code) => code.replace('custom', 'edited'))\n    await expect.poll(() => el.textContent()).toMatch('edited')\n  })\n\n  test('plugin hmr remove custom events', async () => {\n    const el = await page.$('.toRemove')\n    editFile('customFile.js', (code) => code.replace('custom', 'edited'))\n    await expect.poll(() => el.textContent()).toMatch('edited')\n    editFile('customFile.js', (code) => code.replace('edited', 'custom'))\n    await expect.poll(() => el.textContent()).toMatch('edited')\n  })\n\n  test('plugin client-server communication', async () => {\n    const el = await page.$('.custom-communication')\n    await expect.poll(() => el.textContent()).toMatch('3')\n  })\n\n  test('full-reload encodeURI path', async () => {\n    await page.goto(\n      viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html',\n    )\n    const el = await page.$('#app')\n    expect(await el.textContent()).toBe('title')\n    editFile('unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html', (code) =>\n      code.replace('title', 'title2'),\n    )\n    await page.waitForEvent('load')\n    await expect\n      .poll(async () => (await page.$('#app')).textContent())\n      .toBe('title2')\n  })\n\n  test('CSS update preserves query params', async () => {\n    await page.goto(viteTestUrl)\n\n    editFile('global.css', (code) => code.replace('white', 'tomato'))\n\n    const elprev = await page.$('.css-prev')\n    const elpost = await page.$('.css-post')\n    await expect.poll(() => elprev.textContent()).toMatch('param=required')\n    await expect.poll(() => elpost.textContent()).toMatch('param=required')\n    const textprev = await elprev.textContent()\n    const textpost = await elpost.textContent()\n    expect(textprev).not.toBe(textpost)\n    expect(textprev).not.toMatch('direct')\n    expect(textpost).not.toMatch('direct')\n  })\n\n  test('it swaps out link tags', async () => {\n    await page.goto(viteTestUrl)\n\n    editFile('global.css', (code) => code.replace('white', 'tomato'))\n\n    let el = await page.$('.link-tag-added')\n    await expect.poll(() => el.textContent()).toMatch('yes')\n\n    el = await page.$('.link-tag-removed')\n    await expect.poll(() => el.textContent()).toMatch('yes')\n\n    expect((await page.$$('link')).length).toBe(1)\n  })\n\n  test('not loaded dynamic import', async () => {\n    await page.goto(viteTestUrl + '/counter/index.html', { waitUntil: 'load' })\n\n    let btn = await page.$('button')\n    expect(await btn.textContent()).toBe('Counter 0')\n    await btn.click()\n    expect(await btn.textContent()).toBe('Counter 1')\n\n    // Modifying `index.ts` triggers a page reload, as expected\n    const indexTsLoadPromise = page.waitForEvent('load')\n    editFile('counter/index.ts', (code) => code)\n    await indexTsLoadPromise\n    btn = await page.$('button')\n    expect(await btn.textContent()).toBe('Counter 0')\n\n    await btn.click()\n    expect(await btn.textContent()).toBe('Counter 1')\n\n    // #7561\n    // `dep.ts` defines `import.module.hot.accept` and has not been loaded.\n    // Therefore, modifying it has no effect (doesn't trigger a page reload).\n    // (Note that, a dynamic import that is never loaded and that does not\n    // define `accept.module.hot.accept` may wrongfully trigger a full page\n    // reload, see discussion at #7561.)\n    const depTsLoadPromise = page.waitForEvent('load', { timeout: 1000 })\n    editFile('counter/dep.ts', (code) => code)\n    await expect(depTsLoadPromise).rejects.toThrow(\n      /page\\.waitForEvent: Timeout \\d+ms exceeded while waiting for event \"load\"/,\n    )\n\n    btn = await page.$('button')\n    expect(await btn.textContent()).toBe('Counter 1')\n  })\n\n  // #2255\n  test('importing reloaded', async () => {\n    await page.goto(viteTestUrl)\n    const outputEle = await page.$('.importing-reloaded')\n    const getOutput = () => {\n      return outputEle.innerHTML()\n    }\n\n    await expect\n      .poll(getOutput)\n      .toMatch(['a.js: a0', 'b.js: b0,a0'].join('<br>'))\n\n    editFile('importing-updated/a.js', (code) => code.replace(\"'a0'\", \"'a1'\"))\n    await expect\n      .poll(getOutput)\n      .toMatch(['a.js: a0', 'b.js: b0,a0', 'a.js: a1'].join('<br>'))\n\n    editFile('importing-updated/b.js', (code) =>\n      code.replace('`b0,${a}`', '`b1,${a}`'),\n    )\n    // note that \"a.js: a1\" should not happen twice after \"b.js: b0,a0'\"\n    await expect\n      .poll(getOutput)\n      .toMatch(\n        ['a.js: a0', 'b.js: b0,a0', 'a.js: a1', 'b.js: b1,a1'].join('<br>'),\n      )\n  })\n\n  describe('acceptExports', () => {\n    const HOT_UPDATED = /hot updated/\n    const CONNECTED = /connected/\n\n    const baseDir = 'accept-exports'\n\n    describe('when all used exports are accepted', () => {\n      const testDir = baseDir + '/main-accepted'\n\n      const fileName = 'target.ts'\n      const file = `${testDir}/${fileName}`\n      const url = '/' + file\n\n      let dep = 'dep0'\n\n      beforeAll(async () => {\n        await untilBrowserLogAfter(\n          () => page.goto(`${viteTestUrl}/${testDir}/`),\n          [CONNECTED, />>>>>>/],\n          (logs) => {\n            expect(logs).toContain(`<<<<<< A0 B0 D0 ; ${dep}`)\n            expect(logs).toContain('>>>>>> A0 D0')\n          },\n        )\n      })\n\n      it('the callback is called with the new version the module', async () => {\n        const callbackFile = `${testDir}/callback.ts`\n        const callbackUrl = '/' + callbackFile\n\n        await untilBrowserLogAfter(\n          () => {\n            editFile(callbackFile, (code) =>\n              code\n                .replace(\"x = 'X'\", \"x = 'Y'\")\n                .replace('reloaded >>>', 'reloaded (2) >>>'),\n            )\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual([\n              'reloaded >>> Y',\n              `[vite] hot updated: ${callbackUrl}`,\n            ])\n          },\n        )\n\n        await untilBrowserLogAfter(\n          () => {\n            editFile(callbackFile, (code) => code.replace(\"x = 'Y'\", \"x = 'Z'\"))\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual([\n              'reloaded (2) >>> Z',\n              `[vite] hot updated: ${callbackUrl}`,\n            ])\n          },\n        )\n      })\n\n      it('stops HMR bubble on dependency change', async () => {\n        const depFileName = 'dep.ts'\n        const depFile = `${testDir}/${depFileName}`\n\n        await untilBrowserLogAfter(\n          () => {\n            editFile(depFile, (code) => code.replace('dep0', (dep = 'dep1')))\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual([\n              `<<<<<< A0 B0 D0 ; ${dep}`,\n              `[vite] hot updated: ${url}`,\n            ])\n          },\n        )\n      })\n\n      it('accepts itself and refreshes on change', async () => {\n        await untilBrowserLogAfter(\n          () => {\n            editFile(file, (code) => code.replace(/(\\b[A-Z])0/g, '$11'))\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual([\n              `<<<<<< A1 B1 D1 ; ${dep}`,\n              `[vite] hot updated: ${url}`,\n            ])\n          },\n        )\n      })\n\n      it('accepts itself and refreshes on 2nd change', async () => {\n        await untilBrowserLogAfter(\n          () => {\n            editFile(file, (code) =>\n              code\n                .replace(/(\\b[A-Z])1/g, '$12')\n                .replace(\n                  \"acceptExports(['a', 'default']\",\n                  \"acceptExports(['b', 'default']\",\n                ),\n            )\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual([\n              `<<<<<< A2 B2 D2 ; ${dep}`,\n              `[vite] hot updated: ${url}`,\n            ])\n          },\n        )\n      })\n\n      it('does not accept itself anymore after acceptedExports change', async () => {\n        await untilBrowserLogAfter(\n          async () => {\n            editFile(file, (code) => code.replace(/(\\b[A-Z])2/g, '$13'))\n            await page.waitForEvent('load')\n          },\n          [CONNECTED, />>>>>>/],\n          (logs) => {\n            expect(logs).toContain(`<<<<<< A3 B3 D3 ; ${dep}`)\n            expect(logs).toContain('>>>>>> A3 D3')\n          },\n        )\n      })\n    })\n\n    describe('when some used exports are not accepted', () => {\n      const testDir = baseDir + '/main-non-accepted'\n\n      const namedFileName = 'named.ts'\n      const namedFile = `${testDir}/${namedFileName}`\n      const defaultFileName = 'default.ts'\n      const defaultFile = `${testDir}/${defaultFileName}`\n      const depFileName = 'dep.ts'\n      const depFile = `${testDir}/${depFileName}`\n\n      const a = 'A0'\n      let dep = 'dep0'\n\n      beforeAll(async () => {\n        await untilBrowserLogAfter(\n          () => page.goto(`${viteTestUrl}/${testDir}/`),\n          [CONNECTED, />>>>>>/],\n          (logs) => {\n            expect(logs).toContain(`<<< named: ${a} ; ${dep}`)\n            expect(logs).toContain(`<<< default: def0`)\n            expect(logs).toContain(`>>>>>> ${a} def0`)\n          },\n        )\n      })\n\n      it('does not stop the HMR bubble on change to dep', async () => {\n        await untilBrowserLogAfter(\n          async () => {\n            editFile(depFile, (code) => code.replace('dep0', (dep = 'dep1')))\n            await page.waitForEvent('load')\n          },\n          [CONNECTED, />>>>>>/],\n          (logs) => {\n            expect(logs).toContain(`<<< named: ${a} ; ${dep}`)\n          },\n        )\n      })\n\n      describe('does not stop the HMR bubble on change to self', () => {\n        it('with named exports', async () => {\n          await untilBrowserLogAfter(\n            async () => {\n              editFile(namedFile, (code) => code.replace(a, 'A1'))\n              await page.waitForEvent('load')\n            },\n            [CONNECTED, />>>>>>/],\n            (logs) => {\n              expect(logs).toContain(`<<< named: A1 ; ${dep}`)\n            },\n          )\n        })\n\n        it('with default export', async () => {\n          await untilBrowserLogAfter(\n            async () => {\n              editFile(defaultFile, (code) => code.replace('def0', 'def1'))\n              await page.waitForEvent('load')\n            },\n            [CONNECTED, />>>>>>/],\n            (logs) => {\n              expect(logs).toContain(`<<< default: def1`)\n            },\n          )\n        })\n      })\n    })\n\n    test('accepts itself when imported for side effects only (no bindings imported)', async () => {\n      const testDir = baseDir + '/side-effects'\n      const file = 'side-effects.ts'\n\n      await untilBrowserLogAfter(\n        () => page.goto(`${viteTestUrl}/${testDir}/`),\n        [CONNECTED, />>>/],\n        (logs) => {\n          expect(logs).toContain('>>> side FX')\n        },\n      )\n\n      await untilBrowserLogAfter(\n        () => {\n          editFile(`${testDir}/${file}`, (code) =>\n            code.replace('>>> side FX', '>>> side FX !!'),\n          )\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual([\n            '>>> side FX !!',\n            `[vite] hot updated: /${testDir}/${file}`,\n          ])\n        },\n      )\n    })\n\n    describe('acceptExports([])', () => {\n      const testDir = baseDir + '/unused-exports'\n\n      test('accepts itself if no exports are imported', async () => {\n        const fileName = 'unused.ts'\n        const file = `${testDir}/${fileName}`\n        const url = '/' + file\n\n        await untilBrowserLogAfter(\n          () => page.goto(`${viteTestUrl}/${testDir}/`),\n          [CONNECTED, '-- unused --'],\n          (logs) => {\n            expect(logs).toContain('-- unused --')\n          },\n        )\n\n        await untilBrowserLogAfter(\n          () => {\n            editFile(file, (code) =>\n              code.replace('-- unused --', '-> unused <-'),\n            )\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual(['-> unused <-', `[vite] hot updated: ${url}`])\n          },\n        )\n      })\n\n      test(\"doesn't accept itself if any of its exports is imported\", async () => {\n        const fileName = 'used.ts'\n        const file = `${testDir}/${fileName}`\n\n        await untilBrowserLogAfter(\n          () => page.goto(`${viteTestUrl}/${testDir}/`),\n          [CONNECTED, '-- used --'],\n          (logs) => {\n            expect(logs).toContain('-- used --')\n            expect(logs).toContain('used:foo0')\n          },\n        )\n\n        await untilBrowserLogAfter(\n          async () => {\n            editFile(file, (code) =>\n              code.replace('foo0', 'foo1').replace('-- used --', '-> used <-'),\n            )\n            await page.waitForEvent('load')\n          },\n          [CONNECTED, /used:foo/],\n          (logs) => {\n            expect(logs).toContain('-> used <-')\n            expect(logs).toContain('used:foo1')\n          },\n        )\n      })\n    })\n\n    describe('indiscriminate imports: import *', () => {\n      const testStarExports = (testDirName: string) => {\n        const testDir = `${baseDir}/${testDirName}`\n\n        it('accepts itself if all its exports are accepted', async () => {\n          const fileName = 'deps-all-accepted.ts'\n          const file = `${testDir}/${fileName}`\n          const url = '/' + file\n\n          await untilBrowserLogAfter(\n            () => page.goto(`${viteTestUrl}/${testDir}/`),\n            [CONNECTED, '>>> ready <<<'],\n            (logs) => {\n              expect(logs).toContain('loaded:all:a0b0c0default0')\n              expect(logs).toContain('all >>>>>> a0, b0, c0')\n            },\n          )\n\n          await untilBrowserLogAfter(\n            () => {\n              editFile(file, (code) => code.replace(/([abc])0/g, '$11'))\n            },\n            HOT_UPDATED,\n            (logs) => {\n              expect(logs).toEqual([\n                'all >>>>>> a1, b1, c1',\n                `[vite] hot updated: ${url}`,\n              ])\n            },\n          )\n\n          await untilBrowserLogAfter(\n            () => {\n              editFile(file, (code) => code.replace(/([abc])1/g, '$12'))\n            },\n            HOT_UPDATED,\n            (logs) => {\n              expect(logs).toEqual([\n                'all >>>>>> a2, b2, c2',\n                `[vite] hot updated: ${url}`,\n              ])\n            },\n          )\n        })\n\n        it(\"doesn't accept itself if one export is not accepted\", async () => {\n          const fileName = 'deps-some-accepted.ts'\n          const file = `${testDir}/${fileName}`\n\n          await untilBrowserLogAfter(\n            () => page.goto(`${viteTestUrl}/${testDir}/`),\n            [CONNECTED, '>>> ready <<<'],\n            (logs) => {\n              expect(logs).toContain('loaded:some:a0b0c0default0')\n              expect(logs).toContain('some >>>>>> a0, b0, c0')\n            },\n          )\n\n          await untilBrowserLogAfter(\n            async () => {\n              const loadPromise = page.waitForEvent('load')\n              editFile(file, (code) => code.replace(/([abc])0/g, '$11'))\n              await loadPromise\n            },\n            [CONNECTED, '>>> ready <<<'],\n            (logs) => {\n              expect(logs).toContain('loaded:some:a1b1c1default0')\n              expect(logs).toContain('some >>>>>> a1, b1, c1')\n            },\n          )\n        })\n      }\n\n      describe('import * from ...', () => testStarExports('star-imports'))\n\n      describe('dynamic import(...)', () => testStarExports('dynamic-imports'))\n    })\n  })\n\n  test('css in html hmr', async () => {\n    await page.goto(viteTestUrl)\n    expect(await getBg('.import-image')).toMatch('icon')\n    await page.goto(viteTestUrl + '/foo/', { waitUntil: 'load' })\n    expect(await getBg('.import-image')).toMatch('icon')\n\n    const loadPromise = page.waitForEvent('load')\n    editFile('index.html', (code) => code.replace('url(\"./icon.png\")', ''))\n    await loadPromise\n    expect(await getBg('.import-image')).toMatch('')\n  })\n\n  test('HTML', async () => {\n    await page.goto(viteTestUrl + '/counter/index.html')\n    let btn = await page.$('button')\n    expect(await btn.textContent()).toBe('Counter 0')\n\n    const loadPromise = page.waitForEvent('load')\n    editFile('counter/index.html', (code) =>\n      code.replace('Counter', 'Compteur'),\n    )\n    await loadPromise\n    btn = await page.$('button')\n    expect(await btn.textContent()).toBe('Compteur 0')\n  })\n\n  test('handle virtual module updates', async () => {\n    await page.goto(viteTestUrl)\n    const el = await page.$('.virtual')\n    expect(await el.textContent()).toBe('[success]0')\n    editFile('importedVirtual.js', (code) => code.replace('[success]', '[wow]'))\n    await expect\n      .poll(async () => {\n        const el = await page.$('.virtual')\n        return await el.textContent()\n      })\n      .toBe('[wow]0')\n  })\n\n  test('invalidate virtual module', async () => {\n    await page.goto(viteTestUrl)\n    const el = await page.$('.virtual')\n    expect(await el.textContent()).toBe('[wow]0')\n    const btn = await page.$('.virtual-update')\n    btn.click()\n    await expect\n      .poll(async () => {\n        const el = await page.$('.virtual')\n        return await el.textContent()\n      })\n      .toBe('[wow]1')\n  })\n\n  test('handle virtual module accept updates', async () => {\n    await page.goto(viteTestUrl)\n    const el = await page.$('.virtual-dep')\n    expect(await el.textContent()).toBe('0')\n    editFile('importedVirtual.js', (code) => code.replace('[success]', '[wow]'))\n    await expect\n      .poll(async () => {\n        const el = await page.$('.virtual-dep')\n        return await el.textContent()\n      })\n      .toBe('[wow]0')\n  })\n\n  test('invalidate virtual module and accept', async () => {\n    await page.goto(viteTestUrl)\n    const el = await page.$('.virtual-dep')\n    expect(await el.textContent()).toBe('0')\n    const btn = await page.$('.virtual-update-dep')\n    btn.click()\n    await expect\n      .poll(async () => {\n        const el = await page.$('.virtual-dep')\n        return await el.textContent()\n      })\n      .toBe('[wow]2')\n  })\n\n  test('keep hmr reload after missing import on server startup', async () => {\n    const file = 'missing-import/a.js'\n    const importCode = \"import 'missing-modules'\"\n    const unImportCode = `// ${importCode}`\n\n    await untilBrowserLogAfter(\n      () =>\n        page.goto(viteTestUrl + '/missing-import/index.html', {\n          waitUntil: 'load',\n        }),\n      /connected/, // wait for HMR connection\n    )\n\n    await untilBrowserLogAfter(async () => {\n      const loadPromise = page.waitForEvent('load')\n      editFile(file, (code) => code.replace(importCode, unImportCode))\n      await loadPromise\n    }, ['missing test', /connected/])\n\n    await untilBrowserLogAfter(async () => {\n      const loadPromise = page.waitForEvent('load')\n      editFile(file, (code) => code.replace(unImportCode, importCode))\n      await loadPromise\n    }, [/500/, /connected/])\n  })\n\n  test('should hmr when file is deleted and restored', async () => {\n    await page.goto(viteTestUrl)\n\n    const parentFile = 'file-delete-restore/parent.js'\n    const childFile = 'file-delete-restore/child.js'\n\n    await expect\n      .poll(() => page.textContent('.file-delete-restore'))\n      .toMatch('parent:child')\n\n    editFile(childFile, (code) =>\n      code.replace(\"value = 'child'\", \"value = 'child1'\"),\n    )\n    await expect\n      .poll(() => page.textContent('.file-delete-restore'))\n      .toMatch('parent:child1')\n\n    // delete the file\n    editFile(parentFile, (code) =>\n      code.replace(\n        \"export { value as childValue } from './child'\",\n        \"export const childValue = 'not-child'\",\n      ),\n    )\n    const originalChildFileCode = readFile(childFile)\n    await Promise.all([\n      untilBrowserLogAfter(\n        () => removeFile(childFile),\n        `${childFile} is disposed`,\n      ),\n      expect\n        .poll(() => page.textContent('.file-delete-restore'))\n        .toMatch('parent:not-child'),\n    ])\n\n    await untilBrowserLogAfter(async () => {\n      const loadPromise = page.waitForEvent('load')\n      addFile(childFile, originalChildFileCode)\n      editFile(parentFile, (code) =>\n        code.replace(\n          \"export const childValue = 'not-child'\",\n          \"export { value as childValue } from './child'\",\n        ),\n      )\n      await loadPromise\n    }, [/connected/])\n    await expect\n      .poll(() => page.textContent('.file-delete-restore'))\n      .toMatch('parent:child')\n  })\n\n  test('delete file should not break hmr', async () => {\n    await page.goto(viteTestUrl)\n\n    await expect\n      .poll(() => page.textContent('.intermediate-file-delete-display'))\n      .toMatch('count is 1')\n\n    // add state\n    await page.click('.intermediate-file-delete-increment')\n    await expect\n      .poll(() => page.textContent('.intermediate-file-delete-display'))\n      .toMatch('count is 2')\n\n    // update import, hmr works\n    editFile('intermediate-file-delete/index.js', (code) =>\n      code.replace(\"from './re-export.js'\", \"from './display.js'\"),\n    )\n    editFile('intermediate-file-delete/display.js', (code) =>\n      code.replace('count is ${count}', 'count is ${count}!'),\n    )\n    await expect\n      .poll(() => page.textContent('.intermediate-file-delete-display'))\n      .toMatch('count is 2!')\n\n    // remove unused file, page reload because it's considered entry point now\n    removeFile('intermediate-file-delete/re-export.js')\n    await expect\n      .poll(() => page.textContent('.intermediate-file-delete-display'))\n      .toMatch('count is 1!')\n\n    // re-add state\n    await page.click('.intermediate-file-delete-increment')\n    await expect\n      .poll(() => page.textContent('.intermediate-file-delete-display'))\n      .toMatch('count is 2!')\n\n    // hmr works after file deletion\n    editFile('intermediate-file-delete/display.js', (code) =>\n      code.replace('count is ${count}!', 'count is ${count}'),\n    )\n    await expect\n      .poll(() => page.textContent('.intermediate-file-delete-display'))\n      .toMatch('count is 2')\n  })\n\n  test('deleted file should trigger dispose and prune callbacks', async () => {\n    await page.goto(viteTestUrl)\n\n    const parentFile = 'file-delete-restore/parent.js'\n    const childFile = 'file-delete-restore/child.js'\n    const originalChildFileCode = readFile(childFile)\n\n    await untilBrowserLogAfter(\n      () => {\n        // delete the file\n        editFile(parentFile, (code) =>\n          code.replace(\n            \"export { value as childValue } from './child'\",\n            \"export const childValue = 'not-child'\",\n          ),\n        )\n        removeFile(childFile)\n      },\n      [\n        'file-delete-restore/child.js is disposed',\n        'file-delete-restore/child.js is pruned',\n      ],\n      false,\n    )\n    await expect\n      .poll(() => page.textContent('.file-delete-restore'))\n      .toMatch('parent:not-child')\n\n    // restore the file\n    addFile(childFile, originalChildFileCode)\n    editFile(parentFile, (code) =>\n      code.replace(\n        \"export const childValue = 'not-child'\",\n        \"export { value as childValue } from './child'\",\n      ),\n    )\n    await expect\n      .poll(() => page.textContent('.file-delete-restore'))\n      .toMatch('parent:child')\n  })\n\n  test('deleting import from non-self-accepting module can trigger prune event', async () => {\n    await page.goto(viteTestUrl)\n    await expect.poll(() => page.textContent('.prune')).toMatch('prune-init')\n    editFile('prune/dep1.js', (code) =>\n      code.replace(`import './dep2.js'`, `// import './dep2.js'`),\n    )\n    // Prune is triggered when there are other dependencies.\n    await expect\n      .poll(() => page.textContent('.prune'))\n      .toMatch('prune-init|dep2-disposed|dep2-pruned')\n    editFile('prune/dep1.js', (code) =>\n      code.replace(`import './dep3.js'`, `// import './dep3.js'`),\n    )\n    // Prune is triggered when there are no more dependencies.\n    await expect\n      .poll(() => page.textContent('.prune'))\n      .toMatch('prune-init|dep2-disposed|dep2-pruned|dep3-disposed|dep3-pruned')\n  })\n\n  test('import.meta.hot?.accept', async () => {\n    await page.goto(viteTestUrl)\n\n    const el = await page.$('.optional-chaining')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('optional-chaining/child.js', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      '(optional-chaining) child update',\n    )\n    await expect.poll(() => el.textContent()).toMatch('2')\n  })\n\n  test('hmr works for self-accepted module within circular imported files', async () => {\n    await page.goto(viteTestUrl + '/self-accept-within-circular/index.html')\n    const el = await page.$('.self-accept-within-circular')\n    expect(await el.textContent()).toBe('c')\n    const lastServerLogIndex = serverLogs.length\n    editFile('self-accept-within-circular/c.js', (code) =>\n      code.replace(`export const c = 'c'`, `export const c = 'cc'`),\n    )\n    await expect\n      .poll(() => page.textContent('.self-accept-within-circular'))\n      .toBe('cc')\n    // Should still keep hmr update, but it'll error on the browser-side and will refresh itself.\n    expect(\n      serverLogs.slice(lastServerLogIndex).map(stripVTControlCharacters),\n    ).toContain('hmr update /self-accept-within-circular/c.js')\n  })\n\n  test('hmr should not reload if no accepted within circular imported files', async () => {\n    await page.goto(viteTestUrl + '/circular/index.html')\n    const el = await page.$('.circular')\n    expect(await el.textContent()).toBe(\n      'mod-a -> mod-b -> mod-c -> mod-a (expected error)',\n    )\n    editFile('circular/mod-b.js', (code) =>\n      code.replace(`mod-b ->`, `mod-b (edited) ->`),\n    )\n    await expect\n      .poll(() => el.textContent())\n      .toBe('mod-a -> mod-b (edited) -> mod-c -> mod-a (expected error)')\n  })\n\n  test('not inlined assets HMR', async () => {\n    await page.goto(viteTestUrl)\n    const el = await page.$('#logo-no-inline')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('logo-no-inline.svg', (code) =>\n          code.replace('height=\"30px\"', 'height=\"40px\"'),\n        ),\n      /Logo-no-inline updated/,\n    )\n    await expect\n      .poll(() => el.evaluate((it) => `${it.clientHeight}`))\n      .toMatch('40')\n  })\n\n  test('inlined assets HMR', async () => {\n    await page.goto(viteTestUrl)\n    const el = await page.$('#logo')\n    await untilBrowserLogAfter(\n      () =>\n        editFile('logo.svg', (code) =>\n          code.replace('height=\"30px\"', 'height=\"40px\"'),\n        ),\n      /Logo updated/,\n    )\n    await expect\n      .poll(() => el.evaluate((it) => `${it.clientHeight}`))\n      .toMatch('40')\n  })\n\n  test('CSS HMR with this.addWatchFile', async () => {\n    await page.goto(viteTestUrl + '/css-deps/index.html')\n    expect(await getColor('.css-deps')).toBe('red')\n    editFile('css-deps/dep.js', (code) => code.replace(`red`, `green`))\n    await expect.poll(() => getColor('.css-deps')).toBe('green')\n  })\n\n  test('hmr should happen after missing file is created', async () => {\n    const file = 'missing-file/a.js'\n    const code = 'console.log(\"a.js\")'\n\n    await untilBrowserLogAfter(\n      () =>\n        page.goto(viteTestUrl + '/missing-file/index.html', {\n          waitUntil: 'load',\n        }),\n      /connected/, // wait for HMR connection\n    )\n\n    await untilBrowserLogAfter(async () => {\n      const loadPromise = page.waitForEvent('load')\n      addFile(file, code)\n      await loadPromise\n    }, [/connected/, 'a.js'])\n  })\n\n  test('deduplicate server rendered link stylesheet', async () => {\n    await page.goto(viteTestUrl + '/css-link/index.html')\n    await expect.poll(() => getColor('.test-css-link')).toBe('orange')\n\n    // remove color\n    editFile('css-link/styles.css', (code) =>\n      code.replace('color: orange;', '/* removed */'),\n    )\n    await expect.poll(() => getColor('.test-css-link')).toBe('black')\n\n    // add color\n    editFile('css-link/styles.css', (code) =>\n      code.replace('/* removed */', 'color: blue;'),\n    )\n    await expect.poll(() => getColor('.test-css-link')).toBe('blue')\n\n    // // remove css import from js\n    editFile('css-link/main.js', (code) =>\n      code.replace(`import './styles.css'`, ``),\n    )\n    await expect.poll(() => getColor('.test-css-link')).toBe('black')\n  })\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/dynamic-imports/deps-all-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nconsole.log(`all >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'c', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/dynamic-imports/deps-some-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nconsole.log(`some >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/dynamic-imports/dynamic-imports.ts",
    "content": "Promise.all([import('./deps-all-accepted'), import('./deps-some-accepted')])\n  .then(([all, some]) => {\n    console.log('loaded:all:' + all.a + all.b + all.c + all.default)\n    console.log('loaded:some:' + some.a + some.b + some.c + some.default)\n    console.log('>>> ready <<<')\n  })\n  .catch((err) => {\n    console.error(err)\n  })\n"
  },
  {
    "path": "playground/hmr/accept-exports/dynamic-imports/index.html",
    "content": "<script type=\"module\" src=\"./dynamic-imports.ts\"></script>\n\n<div class=\"app\"></div>\n"
  },
  {
    "path": "playground/hmr/accept-exports/export-from/depA.ts",
    "content": "export const a = 'Ax'\n"
  },
  {
    "path": "playground/hmr/accept-exports/export-from/export-from.ts",
    "content": "import { a } from './hub'\n\nconsole.log(a)\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n} else {\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/export-from/hub.ts",
    "content": "export * from './depA'\n"
  },
  {
    "path": "playground/hmr/accept-exports/export-from/index.html",
    "content": "<script type=\"module\" src=\"./export-from.ts\"></script>\n\n<div class=\"app\"></div>\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-accepted/callback.ts",
    "content": "export const x = 'X'\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['x'], (m) => {\n    console.log(`reloaded >>> ${m.x}`)\n  })\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-accepted/dep.ts",
    "content": "export default 'dep0'\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-accepted/index.html",
    "content": "<script type=\"module\" src=\"./main-accepted.ts\"></script>\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-accepted/main-accepted.ts",
    "content": "import def, { a } from './target'\nimport { x } from './callback'\n\n// we don't want to pollute other checks' logs...\nif (0 > 1) console.log(x)\n\nconsole.log(`>>>>>> ${a} ${def}`)\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-accepted/target.ts",
    "content": "import dep from './dep'\n\nexport const a = 'A0'\n\nconst bValue = 'B0'\nexport { bValue as b }\n\nconst def = 'D0'\n\nexport default def\n\nconsole.log(`<<<<<< ${a} ${bValue} ${def} ; ${dep}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-non-accepted/default.ts",
    "content": "export const x = 'y'\n\nconst def = 'def0'\n\nexport default def\n\nconsole.log(`<<< default: ${def}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['x'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-non-accepted/dep.ts",
    "content": "export default 'dep0'\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-non-accepted/index.html",
    "content": "<script type=\"module\" src=\"./main-non-accepted.ts\"></script>\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-non-accepted/main-non-accepted.ts",
    "content": "import { a } from './named'\nimport def from './default'\n\nconsole.log(`>>>>>> ${a} ${def}`)\n"
  },
  {
    "path": "playground/hmr/accept-exports/main-non-accepted/named.ts",
    "content": "import dep from './dep'\n\nexport const a = 'A0'\n\nexport const b = 'B0'\n\nconsole.log(`<<< named: ${a} ; ${dep}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['b'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/reexports.bak/accept-named.ts",
    "content": "export { a, b } from './source'\n\nif (import.meta.hot) {\n  // import.meta.hot.accept('./source', (m) => {\n  //   console.log(`accept-named reexport:${m.a},${m.b}`)\n  // })\n  import.meta.hot.acceptExports('a', (m) => {\n    console.log(`accept-named reexport:${m.a},${m.b}`)\n  })\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/reexports.bak/index.html",
    "content": "<script type=\"module\" src=\"./reexports.ts\"></script>\n"
  },
  {
    "path": "playground/hmr/accept-exports/reexports.bak/reexports.ts",
    "content": "import { a } from './accept-named'\n\nconsole.log('accept-named:' + a)\n\nconsole.log('>>> ready')\n"
  },
  {
    "path": "playground/hmr/accept-exports/reexports.bak/source.ts",
    "content": "export const a = 'a0'\nexport const b = 'b0'\n"
  },
  {
    "path": "playground/hmr/accept-exports/side-effects/index.html",
    "content": "<script type=\"module\" src=\"./side-effects.ts\"></script>\n\n<div class=\"app\"></div>\n"
  },
  {
    "path": "playground/hmr/accept-exports/side-effects/side-effects.ts",
    "content": "export const x = 'x'\n\nexport const y = 'y'\n\nexport default 'z'\n\nconsole.log('>>> side FX')\n\ndocument.querySelector('.app').textContent = 'hey'\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['default'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/star-imports/deps-all-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nconsole.log(`all >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'c', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/star-imports/deps-some-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nconsole.log(`some >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/star-imports/index.html",
    "content": "<script type=\"module\" src=\"./star-imports.ts\"></script>\n"
  },
  {
    "path": "playground/hmr/accept-exports/star-imports/star-imports.ts",
    "content": "import * as all from './deps-all-accepted'\nimport * as some from './deps-some-accepted'\n\nconsole.log('loaded:all:' + all.a + all.b + all.c + all.default)\nconsole.log('loaded:some:' + some.a + some.b + some.c + some.default)\nconsole.log('>>> ready <<<')\n"
  },
  {
    "path": "playground/hmr/accept-exports/unused-exports/index.html",
    "content": "<script type=\"module\" src=\"./index.ts\"></script>\n"
  },
  {
    "path": "playground/hmr/accept-exports/unused-exports/index.ts",
    "content": "import './unused'\nimport { foo } from './used'\n\nconsole.log('used:' + foo)\n"
  },
  {
    "path": "playground/hmr/accept-exports/unused-exports/unused.ts",
    "content": "export const x = 'x'\n\nexport const y = 'y'\n\nexport default 'z'\n\nconsole.log('-- unused --')\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports([])\n}\n"
  },
  {
    "path": "playground/hmr/accept-exports/unused-exports/used.ts",
    "content": "export const foo = 'foo0'\n\nexport const bar = 'bar0'\n\nconsole.log('-- used --')\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports([])\n}\n"
  },
  {
    "path": "playground/hmr/circular/index.js",
    "content": "import { msg } from './mod-a'\n\ndocument.querySelector('.circular').textContent = msg\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr/circular/mod-a.js",
    "content": "export const value = 'mod-a'\n\nimport { value as _value } from './mod-b'\n\nexport const msg = `mod-a -> ${_value}`\n"
  },
  {
    "path": "playground/hmr/circular/mod-b.js",
    "content": "import { value as _value } from './mod-c'\n\nexport const value = `mod-b -> ${_value}`\n"
  },
  {
    "path": "playground/hmr/circular/mod-c.js",
    "content": "import { value as _value } from './mod-a'\n\n// Should error as `_value` is not defined yet within the circular imports\nlet __value\ntry {\n  __value = `${_value} (unexpected no error)`\n} catch {\n  __value = 'mod-a (expected error)'\n}\n\nexport const value = `mod-c -> ${__value}`\n"
  },
  {
    "path": "playground/hmr/counter/dep.ts",
    "content": "// This file is never loaded\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {})\n}\n"
  },
  {
    "path": "playground/hmr/counter/index.html",
    "content": "<button>Counter 0</button>\n<script type=\"module\" src=\"./index.ts\"></script>\n"
  },
  {
    "path": "playground/hmr/counter/index.ts",
    "content": "const btn = document.querySelector('button')\nlet count = 0\nconst update = () => {\n  btn.textContent = `Counter ${count}`\n}\nbtn.onclick = () => {\n  count++\n  update()\n}\nfunction neverCalled() {\n  import('./dep')\n}\n"
  },
  {
    "path": "playground/hmr/css-deps/dep.js",
    "content": "// This file is depended by main.css via this.addWatchFile\nexport const color = 'red'\n\n// Self-accept so that updating this file would not trigger a page reload.\n// We only want to observe main.css updating itself.\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr/css-deps/index.html",
    "content": "<div class=\"css-deps\">should be red</div>\n\n<script type=\"module\">\n  import './main.css'\n  // Import dep.js so that not only the CSS depends on dep.js, as Vite will do\n  // a full page reload if the only importers are CSS files.\n  import './dep.js'\n</script>\n"
  },
  {
    "path": "playground/hmr/css-deps/main.css",
    "content": ".css-deps {\n  color: replaced;\n}\n"
  },
  {
    "path": "playground/hmr/css-link/index.html",
    "content": "<div class=\"test-css-link\">test-css-link</div>\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/hmr/css-link/main.js",
    "content": "import './styles.css'\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr/css-link/plugin.ts",
    "content": "import path from 'node:path'\nimport { type Plugin, normalizePath } from 'vite'\n\n// use plugin to simulate server rendered css link\nexport function TestCssLinkPlugin(): Plugin {\n  return {\n    name: 'test-css-link',\n    transformIndexHtml: {\n      handler(_html, ctx) {\n        if (!ctx.filename.endsWith('/css-link/index.html')) return\n        return [\n          {\n            tag: 'link',\n            attrs: {\n              rel: 'stylesheet',\n              href: '/css-link/styles.css',\n              'data-vite-dev-id': normalizePath(\n                path.resolve(import.meta.dirname, 'styles.css'),\n              ),\n            },\n          },\n        ]\n      },\n    },\n  }\n}\n"
  },
  {
    "path": "playground/hmr/css-link/styles.css",
    "content": ".test-css-link {\n  color: orange;\n}\n"
  },
  {
    "path": "playground/hmr/customFile.js",
    "content": "export const msg = 'custom'\n"
  },
  {
    "path": "playground/hmr/event.d.ts",
    "content": "import 'vite/types/customEvent'\n\ndeclare module 'vite/types/customEvent' {\n  interface CustomEventMap {\n    'custom:foo': { msg: string }\n    'custom:remote-add': { a: number; b: number }\n    'custom:remote-add-result': { result: string }\n  }\n}\n"
  },
  {
    "path": "playground/hmr/file-delete-restore/child.js",
    "content": "import { rerender } from './runtime'\n\nexport const value = 'child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept((newMod) => {\n    if (!newMod) return\n\n    rerender({ child: newMod.value })\n  })\n\n  import.meta.hot.dispose(() => {\n    console.log('file-delete-restore/child.js is disposed')\n  })\n\n  import.meta.hot.prune(() => {\n    console.log('file-delete-restore/child.js is pruned')\n  })\n}\n"
  },
  {
    "path": "playground/hmr/file-delete-restore/index.js",
    "content": "import { render } from './runtime'\nimport { childValue, parentValue } from './parent'\n\nrender({ parent: parentValue, child: childValue })\n"
  },
  {
    "path": "playground/hmr/file-delete-restore/parent.js",
    "content": "import { rerender } from './runtime'\n\nexport const parentValue = 'parent'\nexport { value as childValue } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept((newMod) => {\n    if (!newMod) return\n\n    rerender({ child: newMod.childValue, parent: newMod.parentValue })\n  })\n}\n"
  },
  {
    "path": "playground/hmr/file-delete-restore/runtime.js",
    "content": "let state = {}\n\nexport const render = (newState) => {\n  state = newState\n  apply()\n}\n\nexport const rerender = (updates) => {\n  state = { ...state, ...updates }\n  apply()\n}\n\nconst apply = () => {\n  document.querySelector('.file-delete-restore').textContent =\n    Object.values(state).join(':')\n}\n"
  },
  {
    "path": "playground/hmr/global.css",
    "content": "body {\n  background: white;\n}\n"
  },
  {
    "path": "playground/hmr/hmr.ts",
    "content": "import { virtual } from 'virtual:file'\nimport { virtual as virtualDep } from 'virtual:file-dep'\nimport { foo as depFoo, nestedFoo } from './hmrDep'\nimport './importing-updated'\nimport './invalidation-circular-deps'\nimport './file-delete-restore'\nimport './optional-chaining/parent'\nimport './intermediate-file-delete'\nimport './circular'\nimport './prune'\nimport logo from './logo.svg'\nimport logoNoInline from './logo-no-inline.svg'\nimport { msg as softInvalidationMsg } from './soft-invalidation'\n\nexport const foo = 1\ntext('.app', foo)\ntext('.dep', depFoo)\ntext('.nested', nestedFoo)\ntext('.virtual', virtual)\ntext('.virtual-dep', virtualDep)\ntext('.soft-invalidation', softInvalidationMsg)\nsetImgSrc('#logo', logo)\nsetImgSrc('#logo-no-inline', logoNoInline)\n\ntext('.virtual-dep', 0)\n\nconst btn = document.querySelector('.virtual-update') as HTMLButtonElement\nbtn.onclick = () => {\n  if (import.meta.hot) {\n    import.meta.hot.send('virtual:increment')\n  }\n}\n\nconst btnDep = document.querySelector(\n  '.virtual-update-dep',\n) as HTMLButtonElement\nbtnDep.onclick = () => {\n  if (import.meta.hot) {\n    import.meta.hot.send('virtual:increment', '-dep')\n  }\n}\n\nif (import.meta.hot) {\n  import.meta.hot.accept(({ foo }) => {\n    console.log('(self-accepting 1) foo is now:', foo)\n  })\n\n  import.meta.hot.accept(({ foo }) => {\n    console.log('(self-accepting 2) foo is now:', foo)\n  })\n\n  const handleDep = (type, newFoo, newNestedFoo) => {\n    console.log(`(${type}) foo is now: ${newFoo}`)\n    console.log(`(${type}) nested foo is now: ${newNestedFoo}`)\n    text('.dep', newFoo)\n    text('.nested', newNestedFoo)\n  }\n\n  import.meta.hot.accept('./logo.svg', (newUrl) => {\n    setImgSrc('#logo', newUrl.default)\n    console.log('Logo updated', newUrl.default)\n  })\n\n  import.meta.hot.accept('./logo-no-inline.svg', (newUrl) => {\n    setImgSrc('#logo-no-inline', newUrl.default)\n    console.log('Logo-no-inline updated', newUrl.default)\n  })\n\n  import.meta.hot.accept('./hmrDep', ({ foo, nestedFoo }) => {\n    handleDep('single dep', foo, nestedFoo)\n  })\n\n  import.meta.hot.accept('virtual:file-dep', ({ virtual }) => {\n    text('.virtual-dep', virtual)\n  })\n\n  import.meta.hot.accept(['./hmrDep'], ([{ foo, nestedFoo }]) => {\n    handleDep('multi deps', foo, nestedFoo)\n  })\n\n  import.meta.hot.dispose(() => {\n    console.log(`foo was:`, foo)\n  })\n\n  import.meta.hot.on('vite:afterUpdate', (event) => {\n    console.log(`>>> vite:afterUpdate -- ${event.type}`)\n  })\n\n  import.meta.hot.on('vite:beforeUpdate', (event) => {\n    console.log(`>>> vite:beforeUpdate -- ${event.type}`)\n\n    const cssUpdate = event.updates.find(\n      (update) =>\n        update.type === 'css-update' && update.path.includes('global.css'),\n    )\n    if (cssUpdate) {\n      text(\n        '.css-prev',\n        (document.querySelector('.global-css') as HTMLLinkElement).href,\n      )\n\n      // Wait until the tag has been swapped out, which includes the time taken\n      // to download and parse the new stylesheet. Assert the swapped link.\n      const observer = new MutationObserver((mutations) => {\n        mutations.forEach((mutation) => {\n          mutation.addedNodes.forEach((node) => {\n            if (\n              node.nodeType === Node.ELEMENT_NODE &&\n              (node as Element).tagName === 'LINK'\n            ) {\n              text('.link-tag-added', 'yes')\n            }\n          })\n          mutation.removedNodes.forEach((node) => {\n            if (\n              node.nodeType === Node.ELEMENT_NODE &&\n              (node as Element).tagName === 'LINK'\n            ) {\n              text('.link-tag-removed', 'yes')\n              text(\n                '.css-post',\n                (document.querySelector('.global-css') as HTMLLinkElement).href,\n              )\n            }\n          })\n        })\n      })\n\n      observer.observe(document.querySelector('#style-tags-wrapper'), {\n        childList: true,\n      })\n    }\n  })\n\n  import.meta.hot.on('vite:error', (event) => {\n    console.log(`>>> vite:error -- ${event.err.message}`)\n  })\n\n  import.meta.hot.on('vite:invalidate', ({ path }) => {\n    console.log(`>>> vite:invalidate -- ${path}`)\n  })\n\n  import.meta.hot.on('custom:foo', ({ msg }) => {\n    text('.custom', msg)\n  })\n\n  import.meta.hot.on('custom:remove', removeCb)\n\n  // send custom event to server to calculate 1 + 2\n  import.meta.hot.send('custom:remote-add', { a: 1, b: 2 })\n  import.meta.hot.on('custom:remote-add-result', ({ result }) => {\n    text('.custom-communication', result)\n  })\n}\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nfunction setImgSrc(el, src) {\n  ;(document.querySelector(el) as HTMLImageElement).src = src\n}\n\nfunction removeCb({ msg }) {\n  text('.toRemove', msg)\n  import.meta.hot.off('custom:remove', removeCb)\n}\n"
  },
  {
    "path": "playground/hmr/hmrDep.js",
    "content": "export const foo = 1\nexport { foo as nestedFoo } from './hmrNestedDep'\n\nif (import.meta.hot) {\n  const data = import.meta.hot.data\n  if ('fromDispose' in data) {\n    console.log(`(dep) foo from dispose: ${data.fromDispose}`)\n  }\n\n  import.meta.hot.dispose((data) => {\n    console.log(`(dep) foo was: ${foo}`)\n    data.fromDispose = foo\n  })\n}\n"
  },
  {
    "path": "playground/hmr/hmrNestedDep.js",
    "content": "export const foo = 1\n"
  },
  {
    "path": "playground/hmr/importedVirtual.js",
    "content": "export const virtual = '[success]'\n"
  },
  {
    "path": "playground/hmr/importing-updated/a.js",
    "content": "const val = 'a0'\ndocument.querySelector('.importing-reloaded').innerHTML += `a.js: ${val}<br>`\n\nexport default val\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr/importing-updated/b.js",
    "content": "import a from './a.js'\n\nconst val = `b0,${a}`\ndocument.querySelector('.importing-reloaded').innerHTML += `b.js: ${val}<br>`\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr/importing-updated/index.js",
    "content": "import './a'\nimport './b'\n"
  },
  {
    "path": "playground/hmr/index.html",
    "content": "<div id=\"style-tags-wrapper\">\n  <link\n    class=\"global-css\"\n    rel=\"stylesheet\"\n    href=\"./global.css?param=required\"\n  />\n</div>\n<button class=\"virtual-update\">update virtual module</button>\n<button class=\"virtual-update-dep\">update virtual module via accept</button>\n\n<script type=\"module\" src=\"./invalidation/root.js\"></script>\n<script type=\"module\" src=\"./hmr.ts\"></script>\n<style>\n  .import-image {\n    width: 30px;\n    height: 30px;\n    background: url('./icon.png') no-repeat;\n    background-size: contain;\n  }\n</style>\n\n<div class=\"app\"></div>\n<div class=\"dep\"></div>\n<div class=\"nested\"></div>\n<div class=\"custom\"></div>\n<div class=\"toRemove\"></div>\n<div class=\"virtual\"></div>\n<div class=\"virtual-dep\"></div>\n<div class=\"soft-invalidation\"></div>\n<div class=\"invalidation-parent\"></div>\n<div class=\"invalidation-root\"></div>\n<div class=\"invalidation-circular-deps\"></div>\n<div class=\"invalidation-circular-deps-handled\"></div>\n<div class=\"custom-communication\"></div>\n<div class=\"css-prev\"></div>\n<div class=\"css-post\"></div>\n<div class=\"link-tag-added\">no</div>\n<div class=\"link-tag-removed\">no</div>\n<div class=\"import-image\"></div>\n<div class=\"importing-reloaded\"></div>\n<div class=\"file-delete-restore\"></div>\n<div class=\"optional-chaining\"></div>\n<button class=\"intermediate-file-delete-increment\">1</button>\n<div class=\"intermediate-file-delete-display\"></div>\n<img id=\"logo\" />\n<img id=\"logo-no-inline\" />\n<div class=\"circular\"></div>\n<div class=\"prune\">prune-init</div>\n"
  },
  {
    "path": "playground/hmr/intermediate-file-delete/display.js",
    "content": "export const displayCount = (count) => `count is ${count}`\n"
  },
  {
    "path": "playground/hmr/intermediate-file-delete/index.js",
    "content": "import { displayCount } from './re-export.js'\n\nconst button = document.querySelector('.intermediate-file-delete-increment')\n\nconst render = () => {\n  document.querySelector('.intermediate-file-delete-display').textContent =\n    displayCount(Number(button.textContent))\n}\n\nrender()\n\nbutton.addEventListener('click', () => {\n  button.textContent = `${Number(button.textContent) + 1}`\n  render()\n})\n\nif (import.meta.hot) import.meta.hot.accept()\n"
  },
  {
    "path": "playground/hmr/intermediate-file-delete/re-export.js",
    "content": "export * from './display.js'\n"
  },
  {
    "path": "playground/hmr/invalidation/child.js",
    "content": "if (import.meta.hot) {\n  // Need to accept, to register a callback for HMR\n  import.meta.hot.accept(() => {\n    // Trigger HMR in importers\n    import.meta.hot.invalidate()\n  })\n}\n\nexport const value = 'child'\n"
  },
  {
    "path": "playground/hmr/invalidation/parent.js",
    "content": "import { value } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n\nconsole.log('(invalidation) parent is executing')\n\ndocument.querySelector('.invalidation-parent').innerHTML = value\n"
  },
  {
    "path": "playground/hmr/invalidation/root.js",
    "content": "import './parent.js'\n\nif (import.meta.hot) {\n  // Need to accept, to register a callback for HMR\n  import.meta.hot.accept(() => {\n    // Triggers full page reload because no importers\n    import.meta.hot.invalidate()\n  })\n}\n\nconst root = document.querySelector('.invalidation-root')\n\n// Non HMR-able behaviour\nif (!root.innerHTML) {\n  root.innerHTML = 'Init'\n}\n"
  },
  {
    "path": "playground/hmr/invalidation-circular-deps/circular-invalidate/child.js",
    "content": "import './parent'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {\n    import.meta.hot.invalidate()\n  })\n}\n\nexport const value = 'child'\n"
  },
  {
    "path": "playground/hmr/invalidation-circular-deps/circular-invalidate/parent.js",
    "content": "import { value } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {\n    import.meta.hot.invalidate()\n  })\n}\n\nconsole.log('(invalidation circular deps) parent is executing')\nsetTimeout(() => {\n  document.querySelector('.invalidation-circular-deps').innerHTML = value\n})\n"
  },
  {
    "path": "playground/hmr/invalidation-circular-deps/index.js",
    "content": "import './circular-invalidate/parent'\nimport './invalidate-handled-in-circle/parent'\n"
  },
  {
    "path": "playground/hmr/invalidation-circular-deps/invalidate-handled-in-circle/child.js",
    "content": "import './parent'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {\n    import.meta.hot.invalidate()\n  })\n}\n\nexport const value = 'child'\n"
  },
  {
    "path": "playground/hmr/invalidation-circular-deps/invalidate-handled-in-circle/parent.js",
    "content": "import { value } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {})\n}\n\nconsole.log('(invalidation circular deps handled) parent is executing')\nsetTimeout(() => {\n  document.querySelector('.invalidation-circular-deps-handled').innerHTML =\n    value\n})\n"
  },
  {
    "path": "playground/hmr/missing-file/index.html",
    "content": "<div>Page</div>\n<script type=\"module\" src=\"main.js\"></script>\n"
  },
  {
    "path": "playground/hmr/missing-file/main.js",
    "content": "import './a.js'\n"
  },
  {
    "path": "playground/hmr/missing-import/a.js",
    "content": "import 'missing-modules'\n\nconsole.log('missing test')\n"
  },
  {
    "path": "playground/hmr/missing-import/index.html",
    "content": "<div>Page</div>\n<script type=\"module\" src=\"main.js\"></script>\n"
  },
  {
    "path": "playground/hmr/missing-import/main.js",
    "content": "import './a.js'\n"
  },
  {
    "path": "playground/hmr/modules.d.ts",
    "content": "declare module 'virtual:file' {\n  export const virtual: string\n}\n\ndeclare module 'virtual:file-dep' {\n  export const virtual: string\n}\n"
  },
  {
    "path": "playground/hmr/optional-chaining/child.js",
    "content": "export const foo = 1\n"
  },
  {
    "path": "playground/hmr/optional-chaining/parent.js",
    "content": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport { foo } from './child'\n\nimport.meta.hot?.accept('./child', ({ foo }) => {\n  console.log('(optional-chaining) child update')\n  document.querySelector('.optional-chaining').textContent = foo\n})\n"
  },
  {
    "path": "playground/hmr/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-hmr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/hmr/prune/dep1.js",
    "content": "import './dep2.js'\nimport './dep3.js'\n"
  },
  {
    "path": "playground/hmr/prune/dep2.js",
    "content": "if (import.meta.hot) {\n  import.meta.hot.dispose(() => {\n    document.querySelector('.prune').textContent += '|dep2-disposed'\n  })\n  import.meta.hot.prune(() => {\n    document.querySelector('.prune').textContent += '|dep2-pruned'\n  })\n}\n"
  },
  {
    "path": "playground/hmr/prune/dep3.js",
    "content": "if (import.meta.hot) {\n  import.meta.hot.dispose(() => {\n    document.querySelector('.prune').textContent += '|dep3-disposed'\n  })\n  import.meta.hot.prune(() => {\n    document.querySelector('.prune').textContent += '|dep3-pruned'\n  })\n}\n"
  },
  {
    "path": "playground/hmr/prune/index.js",
    "content": "import './dep1.js'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {})\n}\n"
  },
  {
    "path": "playground/hmr/self-accept-within-circular/a.js",
    "content": "import { b } from './b'\n\nexport const a = {\n  b,\n}\n"
  },
  {
    "path": "playground/hmr/self-accept-within-circular/b.js",
    "content": "import { c } from './c'\n\nconst b = {\n  c,\n}\n\nexport { b }\n"
  },
  {
    "path": "playground/hmr/self-accept-within-circular/c.js",
    "content": "import './b'\n\nexport const c = 'c'\n\nfunction render(content) {\n  document.querySelector('.self-accept-within-circular').textContent = content\n}\nrender(c)\n\nimport.meta.hot?.accept((nextExports) => {\n  render(nextExports.c)\n})\n"
  },
  {
    "path": "playground/hmr/self-accept-within-circular/index.html",
    "content": "<script type=\"module\" src=\"index.js\"></script>\n<div class=\"self-accept-within-circular\"></div>\n"
  },
  {
    "path": "playground/hmr/self-accept-within-circular/index.js",
    "content": "import { a } from './a'\n\nconsole.log(a)\n"
  },
  {
    "path": "playground/hmr/soft-invalidation/child.js",
    "content": "export const foo = 'bar'\n"
  },
  {
    "path": "playground/hmr/soft-invalidation/index.js",
    "content": "import { foo } from './child'\n\n// @ts-expect-error global\nexport const msg = `soft-invalidation/index.js is transformed ${__TRANSFORM_COUNT__} times. child is ${foo}`\n"
  },
  {
    "path": "playground/hmr/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html",
    "content": "<div id=\"app\">title</div>\n"
  },
  {
    "path": "playground/hmr/vite.config.ts",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { defineConfig } from 'vite'\nimport type { Plugin } from 'vite'\nimport { TestCssLinkPlugin } from './css-link/plugin'\n\nexport default defineConfig(({ command }) => ({\n  experimental: {\n    hmrPartialAccept: true,\n  },\n  build: {\n    rollupOptions: {\n      input: [\n        path.resolve(import.meta.dirname, './index.html'),\n        ...(command === 'build'\n          ? []\n          : [path.resolve(import.meta.dirname, './missing-import/index.html')]),\n        path.resolve(\n          import.meta.dirname,\n          './unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html',\n        ),\n        path.resolve(import.meta.dirname, './counter/index.html'),\n        path.resolve(\n          import.meta.dirname,\n          './self-accept-within-circular/index.html',\n        ),\n        path.resolve(import.meta.dirname, './css-deps/index.html'),\n      ],\n    },\n    assetsInlineLimit(filePath) {\n      if (filePath.endsWith('logo-no-inline.svg')) {\n        return false\n      }\n    },\n  },\n  plugins: [\n    {\n      name: 'mock-custom',\n      async hotUpdate({ file, read }) {\n        if (file.endsWith('customFile.js')) {\n          const content = await read()\n          const msg = content.match(/export const msg = '(\\w+)'/)[1]\n          this.environment.hot.send('custom:foo', { msg })\n          this.environment.hot.send('custom:remove', { msg })\n        }\n      },\n      configureServer(server) {\n        server.environments.client.hot.on(\n          'custom:remote-add',\n          ({ a, b }, client) => {\n            client.send('custom:remote-add-result', { result: a + b })\n          },\n        )\n      },\n    },\n    virtualPlugin(),\n    transformCountPlugin(),\n    watchCssDepsPlugin(),\n    TestCssLinkPlugin(),\n    hotEventsPlugin(),\n  ],\n}))\n\nfunction virtualPlugin(): Plugin {\n  let num = 0\n  return {\n    name: 'virtual-file',\n    resolveId(id) {\n      if (id.startsWith('virtual:file')) {\n        return '\\0' + id\n      }\n    },\n    load(id) {\n      if (id.startsWith('\\0virtual:file')) {\n        return `\\\nimport { virtual as _virtual } from \"/importedVirtual.js\";\nexport const virtual = _virtual + '${num}';`\n      }\n    },\n    configureServer(server) {\n      server.environments.client.hot.on('virtual:increment', async (suffix) => {\n        const mod = await server.environments.client.moduleGraph.getModuleById(\n          '\\0virtual:file' + (suffix || ''),\n        )\n        if (mod) {\n          num++\n          server.environments.client.reloadModule(mod)\n        }\n      })\n    },\n  }\n}\n\nfunction transformCountPlugin(): Plugin {\n  let num = 0\n  return {\n    name: 'transform-count',\n    transform(code) {\n      if (code.includes('__TRANSFORM_COUNT__')) {\n        return code.replace('__TRANSFORM_COUNT__', String(++num))\n      }\n    },\n  }\n}\n\nfunction watchCssDepsPlugin(): Plugin {\n  return {\n    name: 'watch-css-deps',\n    async transform(code, id) {\n      // replace the `replaced` identifier in the CSS file with the adjacent\n      // `dep.js` file's `color` variable.\n      if (id.includes('css-deps/main.css')) {\n        const depPath = path.resolve(import.meta.dirname, './css-deps/dep.js')\n        const dep = await fs.readFile(depPath, 'utf-8')\n        const color = dep.match(/color = '(.+?)'/)[1]\n        this.addWatchFile(depPath)\n        return code.replace('replaced', color)\n      }\n    },\n  }\n}\n\nfunction hotEventsPlugin(): Plugin {\n  return {\n    name: 'hot-events',\n    configureServer(server) {\n      let connectCount = 0\n      let disconnectCount = 0\n      const clientEnv = server.environments.client\n      clientEnv.hot.on('vite:client:connect', () => connectCount++)\n      clientEnv.hot.on('vite:client:disconnect', () => disconnectCount++)\n\n      server.middlewares.use((req, res, next) => {\n        if (req.url === '/hot-events-counts') {\n          res.setHeader('Content-Type', 'application/json')\n          res.end(JSON.stringify({ connectCount, disconnectCount }))\n          return\n        }\n        next()\n      })\n    },\n  }\n}\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/__tests__/hmr-full-bundle-mode.spec.ts",
    "content": "import { setTimeout } from 'node:timers/promises'\nimport { expect, test } from 'vitest'\nimport { editFile, isBuild, page } from '~utils'\n\nconst assetUrl = /asset-[\\w-]+\\.png/\n\nif (isBuild) {\n  test('should render', async () => {\n    expect(await page.textContent('h1')).toContain('HMR Full Bundle Mode')\n    await expect.poll(() => page.textContent('.app')).toBe('hello')\n    await expect.poll(() => page.textContent('.hmr')).toBe('hello')\n  })\n} else {\n  // INITIAL -> BUNDLING -> BUNDLED\n  test('show bundling in progress', async () => {\n    const reloadPromise = page.waitForEvent('load')\n    await expect\n      .poll(() => page.textContent('body'))\n      .toContain('Bundling in progress')\n    await reloadPromise // page shown after reload\n    await expect.poll(() => page.textContent('h1')).toBe('HMR Full Bundle Mode')\n    await expect.poll(() => page.textContent('.app')).toBe('hello')\n    await expect.poll(() => page.textContent('.asset')).toMatch(assetUrl)\n    await expect\n      .poll(() => page.textContent('.worker-query'))\n      .toBe('worker-query')\n    await expect.poll(() => page.textContent('.worker-url')).toBe('worker-url')\n  })\n\n  // BUNDLED -> GENERATE_HMR_PATCH -> BUNDLING -> BUNDLE_ERROR -> BUNDLING -> BUNDLED\n  test('handle bundle error', async () => {\n    editFile('main.js', (code) =>\n      code.replace(\"text('.app', 'hello')\", \"text('.app', 'hello'); text(\"),\n    )\n    await expect.poll(() => page.isVisible('vite-error-overlay')).toBe(true)\n    editFile('main.js', (code) =>\n      code.replace(\"text('.app', 'hello'); text(\", \"text('.app', 'hello')\"),\n    )\n    await expect.poll(() => page.isVisible('vite-error-overlay')).toBe(false)\n    await expect.poll(() => page.textContent('.app')).toBe('hello')\n  })\n\n  // BUNDLED -> GENERATE_HMR_PATCH -> BUNDLING -> BUNDLED\n  test('update bundle', async () => {\n    editFile('main.js', (code) =>\n      code.replace(\"text('.app', 'hello')\", \"text('.app', 'hello1')\"),\n    )\n    await expect.poll(() => page.textContent('.app')).toBe('hello1')\n\n    editFile('main.js', (code) =>\n      code.replace(\"text('.app', 'hello1')\", \"text('.app', 'hello')\"),\n    )\n    await expect.poll(() => page.textContent('.app')).toBe('hello')\n    await expect.poll(() => page.textContent('.asset')).toMatch(assetUrl)\n  })\n\n  // BUNDLED -> GENERATE_HMR_PATCH -> BUNDLING -> BUNDLING -> BUNDLED\n  test('debounce bundle', async () => {\n    editFile('main.js', (code) =>\n      code.replace(\n        \"text('.app', 'hello')\",\n        \"text('.app', 'hello1')\\n\" + '// @delay-transform',\n      ),\n    )\n    await setTimeout(100)\n    editFile('main.js', (code) =>\n      code.replace(\"text('.app', 'hello1')\", \"text('.app', 'hello2')\"),\n    )\n    await expect.poll(() => page.textContent('.app')).toBe('hello2')\n\n    editFile('main.js', (code) =>\n      code.replace(\n        \"text('.app', 'hello2')\\n\" + '// @delay-transform',\n        \"text('.app', 'hello')\",\n      ),\n    )\n    await expect.poll(() => page.textContent('.app')).toBe('hello')\n  })\n\n  // BUNDLED -> GENERATING_HMR_PATCH -> BUNDLED\n  test('handle generate hmr patch error', async () => {\n    await expect.poll(() => page.textContent('.hmr')).toBe('hello')\n    editFile('hmr.js', (code) =>\n      code.replace(\"const foo = 'hello'\", \"const foo = 'hello\"),\n    )\n    await expect.poll(() => page.isVisible('vite-error-overlay')).toBe(true)\n\n    editFile('hmr.js', (code) =>\n      code.replace(\"const foo = 'hello\", \"const foo = 'hello'\"),\n    )\n    await expect.poll(() => page.isVisible('vite-error-overlay')).toBe(false)\n    await expect.poll(() => page.textContent('.hmr')).toContain('hello')\n  })\n\n  // BUNDLED -> GENERATING_HMR_PATCH -> BUNDLED\n  test('generate hmr patch', async () => {\n    await expect.poll(() => page.textContent('.hmr')).toBe('hello')\n    editFile('hmr.js', (code) =>\n      code.replace(\"const foo = 'hello'\", \"const foo = 'hello1'\"),\n    )\n    await expect.poll(() => page.textContent('.hmr')).toBe('hello1')\n\n    editFile('hmr.js', (code) =>\n      code.replace(\"const foo = 'hello1'\", \"const foo = 'hello'\"),\n    )\n    await expect.poll(() => page.textContent('.hmr')).toContain('hello')\n    await expect.poll(() => page.textContent('.asset')).toMatch(assetUrl)\n  })\n\n  // BUNDLED -> GENERATING_HMR_PATCH -> GENERATING_HMR_PATCH -> BUNDLED\n  test('continuous generate hmr patch', async () => {\n    editFile('hmr.js', (code) =>\n      code.replace(\n        \"const foo = 'hello'\",\n        \"const foo = 'hello1'\\n\" + '// @delay-transform',\n      ),\n    )\n    await setTimeout(100)\n    editFile('hmr.js', (code) =>\n      code.replace(\"const foo = 'hello1'\", \"const foo = 'hello2'\"),\n    )\n    await expect.poll(() => page.textContent('.hmr')).toBe('hello2')\n\n    editFile('hmr.js', (code) =>\n      code.replace(\n        \"const foo = 'hello2'\\n\" + '// @delay-transform',\n        \"const foo = 'hello'\",\n      ),\n    )\n    await expect.poll(() => page.textContent('.hmr')).toBe('hello')\n  })\n\n  test('worker with ?worker query', async () => {\n    await expect\n      .poll(() => page.textContent('.worker-query'))\n      .toBe('worker-query')\n    editFile('worker-query.js', (code) =>\n      code.replace(\n        \"const msg = 'worker-query'\",\n        \"const msg = 'worker-query-updated'\",\n      ),\n    )\n    await expect\n      .poll(() => page.textContent('.worker-query'))\n      .toBe('worker-query-updated')\n\n    editFile('worker-query.js', (code) =>\n      code.replace(\n        \"const msg = 'worker-query-updated'\",\n        \"const msg = 'worker-query'\",\n      ),\n    )\n    await expect\n      .poll(() => page.textContent('.worker-query'))\n      .toBe('worker-query')\n  })\n\n  test('worker with new URL', async () => {\n    await expect.poll(() => page.textContent('.worker-url')).toBe('worker-url')\n    editFile('worker-url.js', (code) =>\n      code.replace(\n        \"const msg = 'worker-url'\",\n        \"const msg = 'worker-url-updated'\",\n      ),\n    )\n    await expect\n      .poll(() => page.textContent('.worker-url'))\n      .toBe('worker-url-updated')\n\n    editFile('worker-url.js', (code) =>\n      code.replace(\n        \"const msg = 'worker-url-updated'\",\n        \"const msg = 'worker-url'\",\n      ),\n    )\n    await expect.poll(() => page.textContent('.worker-url')).toBe('worker-url')\n  })\n}\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/hmr.js",
    "content": "export const foo = 'hello'\ntext('.hmr', foo)\n\nimport assetUrlImported from './asset.png'\n\nexport const assetUrl = assetUrlImported\ntext('.asset', assetUrl)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nimport.meta.hot?.accept((mod) => {\n  if (mod) {\n    text('.hmr', mod.foo)\n    text('.asset', mod.assetUrl)\n  }\n})\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/index.html",
    "content": "<h1>HMR Full Bundle Mode</h1>\n\n<div class=\"app\"></div>\n<div class=\"hmr\"></div>\n<div class=\"asset\"></div>\n<div class=\"worker-query\"></div>\n<div class=\"worker-url\"></div>\n\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/main.js",
    "content": "import './hmr.js'\nimport assetUrl from './asset.png'\nimport WorkerQuery from './worker-query.js?worker'\n\ntext('.app', 'hello')\ntext('.asset', assetUrl)\n\nconst workerQuery = new WorkerQuery()\nworkerQuery.postMessage('ping')\nworkerQuery.addEventListener('message', (e) => {\n  text('.worker-query', e.data)\n})\n\nconst workerUrl = new Worker(new URL('./worker-url.js', import.meta.url), {\n  type: 'module',\n})\nworkerUrl.postMessage('ping')\nworkerUrl.addEventListener('message', (e) => {\n  text('.worker-url', e.data)\n})\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-hmr-full-bundle-mode\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/vite.config.ts",
    "content": "import { type Plugin, defineConfig } from 'vite'\n\nexport default defineConfig({\n  experimental: {\n    bundledDev: true,\n  },\n  plugins: [waitBundleCompleteUntilAccess(), delayTransformComment()],\n})\n\nfunction waitBundleCompleteUntilAccess(): Plugin {\n  let resolvers: PromiseWithResolvers<void>\n\n  return {\n    name: 'wait-bundle-complete-until-access',\n    apply: 'serve',\n    configureServer(server) {\n      let accessCount = 0\n      resolvers = promiseWithResolvers()\n\n      server.middlewares.use((_req, _res, next) => {\n        accessCount++\n        if (accessCount === 1) {\n          resolvers.resolve()\n        }\n        next()\n      })\n    },\n    async generateBundle() {\n      await resolvers.promise\n      await new Promise<void>((resolve) => setTimeout(resolve, 300))\n    },\n  }\n}\n\nfunction delayTransformComment(): Plugin {\n  return {\n    name: 'delay-transform-comment',\n    async transform(code) {\n      if (code.includes('// @delay-transform')) {\n        await new Promise<void>((resolve) => setTimeout(resolve, 300))\n      }\n    },\n  }\n}\n\ninterface PromiseWithResolvers<T> {\n  promise: Promise<T>\n  resolve: (value: T | PromiseLike<T>) => void\n  reject: (reason?: any) => void\n}\nfunction promiseWithResolvers<T>(): PromiseWithResolvers<T> {\n  let resolve: any\n  let reject: any\n  const promise = new Promise<T>((_resolve, _reject) => {\n    resolve = _resolve\n    reject = _reject\n  })\n  return { promise, resolve, reject }\n}\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/worker-query.js",
    "content": "const msg = 'worker-query'\n\nself.onmessage = (e) => {\n  if (e.data === 'ping') {\n    self.postMessage(msg)\n  }\n}\n"
  },
  {
    "path": "playground/hmr-full-bundle-mode/worker-url.js",
    "content": "const msg = 'worker-url'\n\nself.onmessage = (e) => {\n  if (e.data === 'ping') {\n    self.postMessage(msg)\n  }\n}\n"
  },
  {
    "path": "playground/hmr-root/__tests__/hmr-root.spec.ts",
    "content": "import { expect, test } from 'vitest'\n\nimport { editFile, isServe, page } from '~utils'\n\ntest.runIf(isServe)('should watch files outside root', async () => {\n  expect(await page.textContent('#foo')).toBe('foo')\n  editFile('foo.js', (code) => code.replace(\"'foo'\", \"'foobar'\"))\n  await page.waitForEvent('load')\n  await expect.poll(() => page.textContent('#foo')).toBe('foobar')\n})\n"
  },
  {
    "path": "playground/hmr-root/foo.js",
    "content": "export const foo = 'foo'\n"
  },
  {
    "path": "playground/hmr-root/root/index.html",
    "content": "<div id=\"foo\"></div>\n\n<script type=\"module\">\n  import { foo } from '../foo.js'\n\n  document.querySelector('#foo').textContent = foo\n</script>\n"
  },
  {
    "path": "playground/hmr-root/vite.config.ts",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  root: path.join(import.meta.dirname, './root'),\n})\n"
  },
  {
    "path": "playground/hmr-ssr/__tests__/hmr-ssr.spec.ts",
    "content": "import fs from 'node:fs'\nimport { posix, resolve } from 'node:path'\nimport EventEmitter from 'node:events'\nimport {\n  afterAll,\n  beforeAll,\n  describe,\n  expect,\n  onTestFinished,\n  test,\n  vi,\n} from 'vitest'\nimport type {\n  InlineConfig,\n  Plugin,\n  RunnableDevEnvironment,\n  ViteDevServer,\n} from 'vite'\nimport { createRunnableDevEnvironment, createServer } from 'vite'\nimport type { ModuleRunner } from 'vite/module-runner'\nimport {\n  addFile,\n  createInMemoryLogger,\n  editFile,\n  isBuild,\n  promiseWithResolvers,\n  readFile,\n  removeFile,\n  slash,\n  testDir,\n} from '~utils'\n\nlet server: ViteDevServer\nconst clientLogs: string[] = []\nconst serverLogs: string[] = []\nlet runner: ModuleRunner\n\nconst logsEmitter = new EventEmitter()\n\nafterAll(async () => {\n  await server?.close()\n})\n\nconst hmr = (key: string) => (globalThis.__HMR__[key] as string) || ''\n\nconst updated = (file: string, via?: string) => {\n  if (via) {\n    return `[vite] hot updated: ${file} via ${via}`\n  }\n  return `[vite] hot updated: ${file}`\n}\n\ndescribe.skipIf(isBuild)('hmr works correctly', () => {\n  const hotEventCounts = { connect: 0, disconnect: 0 }\n\n  beforeAll(async () => {\n    function hotEventsPlugin(): Plugin {\n      return {\n        name: 'hot-events',\n        configureServer(server) {\n          server.environments.ssr.hot.on(\n            'vite:client:connect',\n            () => hotEventCounts.connect++,\n          )\n          server.environments.ssr.hot.on(\n            'vite:client:disconnect',\n            () => hotEventCounts.disconnect++,\n          )\n        },\n      }\n    }\n\n    await setupModuleRunner('/hmr.ts', { plugins: [hotEventsPlugin()] })\n  })\n\n  test('should connect', async () => {\n    expect(clientLogs).toContain('[vite] connected.')\n    expect(hotEventCounts).toStrictEqual({ connect: 1, disconnect: 0 })\n  })\n\n  test('self accept', async () => {\n    const el = () => hmr('.app')\n    await untilConsoleLogAfter(\n      () =>\n        editFile('hmr.ts', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        'foo was: 1',\n        '(self-accepting 1) foo is now: 2',\n        '(self-accepting 2) foo is now: 2',\n        updated('/hmr.ts'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('2')\n\n    await untilConsoleLogAfter(\n      () =>\n        editFile('hmr.ts', (code) =>\n          code.replace('const foo = 2', 'const foo = 3'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        'foo was: 2',\n        '(self-accepting 1) foo is now: 3',\n        '(self-accepting 2) foo is now: 3',\n        updated('/hmr.ts'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('3')\n  })\n\n  test('accept dep', async () => {\n    const el = () => hmr('.dep')\n    await untilConsoleLogAfter(\n      () =>\n        editFile('hmrDep.js', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 1',\n        '(dep) foo from dispose: 1',\n        '(single dep) foo is now: 2',\n        '(single dep) nested foo is now: 1',\n        '(multi deps) foo is now: 2',\n        '(multi deps) nested foo is now: 1',\n        updated('/hmrDep.js', '/hmr.ts'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('2')\n\n    await untilConsoleLogAfter(\n      () =>\n        editFile('hmrDep.js', (code) =>\n          code.replace('const foo = 2', 'const foo = 3'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 2',\n        '(dep) foo from dispose: 2',\n        '(single dep) foo is now: 3',\n        '(single dep) nested foo is now: 1',\n        '(multi deps) foo is now: 3',\n        '(multi deps) nested foo is now: 1',\n        updated('/hmrDep.js', '/hmr.ts'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('3')\n  })\n\n  test('nested dep propagation', async () => {\n    const el = () => hmr('.nested')\n    await untilConsoleLogAfter(\n      () =>\n        editFile('hmrNestedDep.js', (code) =>\n          code.replace('const foo = 1', 'const foo = 2'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 3',\n        '(dep) foo from dispose: 3',\n        '(single dep) foo is now: 3',\n        '(single dep) nested foo is now: 2',\n        '(multi deps) foo is now: 3',\n        '(multi deps) nested foo is now: 2',\n        updated('/hmrDep.js', '/hmr.ts'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('2')\n\n    await untilConsoleLogAfter(\n      () =>\n        editFile('hmrNestedDep.js', (code) =>\n          code.replace('const foo = 2', 'const foo = 3'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        '(dep) foo was: 3',\n        '(dep) foo from dispose: 3',\n        '(single dep) foo is now: 3',\n        '(single dep) nested foo is now: 3',\n        '(multi deps) foo is now: 3',\n        '(multi deps) nested foo is now: 3',\n        updated('/hmrDep.js', '/hmr.ts'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('3')\n  })\n\n  test('invalidate', async () => {\n    const el = () => hmr('.invalidation')\n    await untilConsoleLogAfter(\n      () =>\n        editFile('invalidation/child.js', (code) =>\n          code.replace('child', 'child updated'),\n        ),\n      [\n        '>>> vite:beforeUpdate -- update',\n        `>>> vite:invalidate -- /invalidation/child.js`,\n        '[vite] invalidate /invalidation/child.js',\n        updated('/invalidation/child.js'),\n        '>>> vite:afterUpdate -- update',\n        '>>> vite:beforeUpdate -- update',\n        '(invalidation) parent is executing',\n        updated('/invalidation/parent.js'),\n        '>>> vite:afterUpdate -- update',\n      ],\n      true,\n    )\n    await expect.poll(() => el()).toMatch('child updated')\n  })\n\n  test('soft invalidate', async () => {\n    const el = () => hmr('.soft-invalidation')\n    expect(el()).toBe(\n      'soft-invalidation/index.js is transformed 1 times. child is bar',\n    )\n    editFile('soft-invalidation/child.js', (code) =>\n      code.replace('bar', 'updated'),\n    )\n    await expect\n      .poll(() => el())\n      .toBe(\n        'soft-invalidation/index.js is transformed 1 times. child is updated',\n      )\n  })\n\n  test('invalidate in circular dep should not trigger infinite HMR', async () => {\n    const el = () => hmr('.invalidation-circular-deps')\n    await expect.poll(() => el()).toMatch('child')\n    editFile(\n      'invalidation-circular-deps/circular-invalidate/child.js',\n      (code) => code.replace('child', 'child updated'),\n    )\n    await expect.poll(() => el()).toMatch('child updated')\n  })\n\n  test('invalidate in circular dep should be hot updated if possible', async () => {\n    const el = () => hmr('.invalidation-circular-deps-handled')\n    await expect.poll(() => el()).toMatch('child')\n    editFile(\n      'invalidation-circular-deps/invalidate-handled-in-circle/child.js',\n      (code) => code.replace('child', 'child updated'),\n    )\n    await expect.poll(() => el()).toMatch('child updated')\n  })\n\n  test('plugin hmr handler + custom event', async () => {\n    const el = () => hmr('.custom')\n    editFile('customFile.js', (code) => code.replace('custom', 'edited'))\n    await expect.poll(() => el()).toMatch('edited')\n  })\n\n  test('plugin hmr remove custom events', async () => {\n    const el = () => hmr('.toRemove')\n    editFile('customFile.js', (code) => code.replace('custom', 'edited'))\n    await expect.poll(() => el()).toMatch('edited')\n    editFile('customFile.js', (code) => code.replace('edited', 'custom'))\n    await expect.poll(() => el()).toMatch('edited')\n  })\n\n  test('plugin client-server communication', async () => {\n    const el = () => hmr('.custom-communication')\n    await expect.poll(() => el()).toMatch('3')\n  })\n\n  test('queries are correctly resolved', async () => {\n    const query1 = () => hmr('query1')\n    const query2 = () => hmr('query2')\n\n    expect(query1()).toBe('query1')\n    expect(query2()).toBe('query2')\n\n    editFile('queries/multi-query.js', (code) => code + '//comment')\n    await expect.poll(() => query1()).toBe('//commentquery1')\n    await expect.poll(() => query2()).toBe('//commentquery2')\n  })\n})\n\ndescribe('self accept with different entry point formats', () => {\n  test.each(['./unresolved.ts', './unresolved', '/unresolved'])(\n    'accepts if entry point is relative to root %s',\n    async (entrypoint) => {\n      await setupModuleRunner(entrypoint, {}, '/unresolved.ts')\n\n      const originalUnresolvedFile = readFile('unresolved.ts')\n      onTestFinished(() => {\n        const filepath = resolve(testDir, 'unresolved.ts')\n        fs.writeFileSync(filepath, originalUnresolvedFile, 'utf-8')\n      })\n\n      const el = () => hmr('.app')\n      await untilConsoleLogAfter(\n        () =>\n          editFile('unresolved.ts', (code) =>\n            code.replace('const foo = 1', 'const foo = 2'),\n          ),\n        [\n          'foo was: 1',\n          '(self-accepting 1) foo is now: 2',\n          '(self-accepting 2) foo is now: 2',\n          updated(entrypoint),\n        ],\n        true,\n      )\n      await expect.poll(() => el()).toMatch('2')\n\n      await untilConsoleLogAfter(\n        () =>\n          editFile('unresolved.ts', (code) =>\n            code.replace('const foo = 2', 'const foo = 3'),\n          ),\n        [\n          'foo was: 2',\n          '(self-accepting 1) foo is now: 3',\n          '(self-accepting 2) foo is now: 3',\n          updated(entrypoint),\n        ],\n        true,\n      )\n      await expect.poll(() => el()).toMatch('3')\n    },\n  )\n})\n\ndescribe('acceptExports', () => {\n  const HOT_UPDATED = /hot updated/\n  const CONNECTED = /connected/\n  const PROGRAM_RELOAD = /program reload/\n\n  const baseDir = 'accept-exports'\n\n  describe('when all used exports are accepted', () => {\n    const testDir = baseDir + '/main-accepted'\n\n    const fileName = 'target.ts'\n    const file = `${testDir}/${fileName}`\n    const url = `/${file}`\n\n    let dep = 'dep0'\n\n    beforeAll(async () => {\n      await untilConsoleLogAfter(\n        () => setupModuleRunner(`/${testDir}/index`),\n        [CONNECTED, />>>>>>/],\n        (logs) => {\n          expect(logs).toContain(`<<<<<< A0 B0 D0 ; ${dep}`)\n          expect(logs).toContain('>>>>>> A0 D0')\n        },\n      )\n    })\n\n    test('the callback is called with the new version the module', async () => {\n      const callbackFile = `${testDir}/callback.ts`\n      const callbackUrl = `/${callbackFile}`\n\n      await untilConsoleLogAfter(\n        () => {\n          editFile(callbackFile, (code) =>\n            code\n              .replace(\"x = 'X'\", \"x = 'Y'\")\n              .replace('reloaded >>>', 'reloaded (2) >>>'),\n          )\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual([\n            'reloaded >>> Y',\n            `[vite] hot updated: ${callbackUrl}`,\n          ])\n        },\n      )\n\n      await untilConsoleLogAfter(\n        () => {\n          editFile(callbackFile, (code) => code.replace(\"x = 'Y'\", \"x = 'Z'\"))\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual([\n            'reloaded (2) >>> Z',\n            `[vite] hot updated: ${callbackUrl}`,\n          ])\n        },\n      )\n    })\n\n    test('stops HMR bubble on dependency change', async () => {\n      const depFileName = 'dep.ts'\n      const depFile = `${testDir}/${depFileName}`\n\n      await untilConsoleLogAfter(\n        () => {\n          editFile(depFile, (code) => code.replace('dep0', (dep = 'dep1')))\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual([\n            `<<<<<< A0 B0 D0 ; ${dep}`,\n            `[vite] hot updated: ${url}`,\n          ])\n        },\n      )\n    })\n\n    test('accepts itself and refreshes on change', async () => {\n      await untilConsoleLogAfter(\n        () => {\n          editFile(file, (code) => code.replace(/(\\b[A-Z])0/g, '$11'))\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual([\n            `<<<<<< A1 B1 D1 ; ${dep}`,\n            `[vite] hot updated: ${url}`,\n          ])\n        },\n      )\n    })\n\n    test('accepts itself and refreshes on 2nd change', async () => {\n      await untilConsoleLogAfter(\n        () => {\n          editFile(file, (code) =>\n            code\n              .replace(/(\\b[A-Z])1/g, '$12')\n              .replace(\n                \"acceptExports(['a', 'default']\",\n                \"acceptExports(['b', 'default']\",\n              ),\n          )\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual([\n            `<<<<<< A2 B2 D2 ; ${dep}`,\n            `[vite] hot updated: ${url}`,\n          ])\n        },\n      )\n    })\n\n    test('does not accept itself anymore after acceptedExports change', async () => {\n      await untilConsoleLogAfter(\n        async () => {\n          editFile(file, (code) => code.replace(/(\\b[A-Z])2/g, '$13'))\n        },\n        [PROGRAM_RELOAD, />>>>>>/],\n        (logs) => {\n          expect(logs).toContain(`<<<<<< A3 B3 D3 ; ${dep}`)\n          expect(logs).toContain('>>>>>> A3 D3')\n        },\n      )\n    })\n  })\n\n  describe('when some used exports are not accepted', () => {\n    const testDir = baseDir + '/main-non-accepted'\n\n    const namedFileName = 'named.ts'\n    const namedFile = `${testDir}/${namedFileName}`\n    const defaultFileName = 'default.ts'\n    const defaultFile = `${testDir}/${defaultFileName}`\n    const depFileName = 'dep.ts'\n    const depFile = `${testDir}/${depFileName}`\n\n    const a = 'A0'\n    let dep = 'dep0'\n\n    beforeAll(async () => {\n      await untilConsoleLogAfter(\n        () => setupModuleRunner(`/${testDir}/index`),\n        [CONNECTED, />>>>>>/],\n        (logs) => {\n          expect(logs).toContain(`<<< named: ${a} ; ${dep}`)\n          expect(logs).toContain(`<<< default: def0`)\n          expect(logs).toContain(`>>>>>> ${a} def0`)\n        },\n      )\n    })\n\n    test('does not stop the HMR bubble on change to dep', async () => {\n      await untilConsoleLogAfter(\n        async () => {\n          editFile(depFile, (code) => code.replace('dep0', (dep = 'dep1')))\n        },\n        [PROGRAM_RELOAD, />>>>>>/],\n        (logs) => {\n          expect(logs).toContain(`<<< named: ${a} ; ${dep}`)\n        },\n      )\n    })\n\n    describe('does not stop the HMR bubble on change to self', () => {\n      test('with named exports', async () => {\n        await untilConsoleLogAfter(\n          async () => {\n            editFile(namedFile, (code) => code.replace(a, 'A1'))\n          },\n          [PROGRAM_RELOAD, />>>>>>/],\n          (logs) => {\n            expect(logs).toContain(`<<< named: A1 ; ${dep}`)\n          },\n        )\n      })\n\n      test('with default export', async () => {\n        await untilConsoleLogAfter(\n          async () => {\n            editFile(defaultFile, (code) => code.replace('def0', 'def1'))\n          },\n          [PROGRAM_RELOAD, />>>>>>/],\n          (logs) => {\n            expect(logs).toContain(`<<< default: def1`)\n          },\n        )\n      })\n    })\n\n    describe(\"doesn't reload if files not in the entrypoint importers chain is changed\", async () => {\n      const testFile = 'non-tested/index.js'\n\n      beforeAll(async () => {\n        clientLogs.length = 0\n        // so it's in the module graph\n        const ssrEnvironment = server.environments.ssr\n        await ssrEnvironment.transformRequest(testFile)\n        await ssrEnvironment.transformRequest('non-tested/dep.js')\n      })\n\n      test('does not full reload', async () => {\n        editFile(\n          testFile,\n          (code) => code + '\\n\\nexport const query5 = \"query5\"',\n        )\n        const start = Date.now()\n        // for 2 seconds check that there is no log about the file being reloaded\n        while (Date.now() - start < 2000) {\n          if (\n            clientLogs.some(\n              (log) =>\n                log.match(PROGRAM_RELOAD) ||\n                log.includes('non-tested/index.js'),\n            )\n          ) {\n            throw new Error('File was reloaded')\n          }\n          await new Promise((r) => setTimeout(r, 100))\n        }\n      }, 5_000)\n\n      test('does not update', async () => {\n        editFile('non-tested/dep.js', (code) => code + '//comment')\n        const start = Date.now()\n        // for 2 seconds check that there is no log about the file being reloaded\n        while (Date.now() - start < 2000) {\n          if (\n            clientLogs.some(\n              (log) =>\n                log.match(PROGRAM_RELOAD) || log.includes('non-tested/dep.js'),\n            )\n          ) {\n            throw new Error('File was updated')\n          }\n          await new Promise((r) => setTimeout(r, 100))\n        }\n      }, 5_000)\n    })\n  })\n\n  test('accepts itself when imported for side effects only (no bindings imported)', async () => {\n    const testDir = baseDir + '/side-effects'\n    const file = 'side-effects.ts'\n\n    await untilConsoleLogAfter(\n      () => setupModuleRunner(`/${testDir}/index`),\n      [CONNECTED, />>>/],\n      (logs) => {\n        expect(logs).toContain('>>> side FX')\n      },\n    )\n\n    await untilConsoleLogAfter(\n      () => {\n        editFile(`${testDir}/${file}`, (code) =>\n          code.replace('>>> side FX', '>>> side FX !!'),\n        )\n      },\n      HOT_UPDATED,\n      (logs) => {\n        expect(logs).toEqual(['>>> side FX !!', updated(`/${testDir}/${file}`)])\n      },\n    )\n  })\n\n  describe('acceptExports([])', () => {\n    const testDir = baseDir + '/unused-exports'\n\n    test('accepts itself if no exports are imported', async () => {\n      const fileName = 'unused.ts'\n      const file = `${testDir}/${fileName}`\n      const url = '/' + file\n\n      await untilConsoleLogAfter(\n        () => setupModuleRunner(`/${testDir}/index`),\n        [CONNECTED, '-- unused --'],\n        (logs) => {\n          expect(logs).toContain('-- unused --')\n        },\n      )\n\n      await untilConsoleLogAfter(\n        () => {\n          editFile(file, (code) => code.replace('-- unused --', '-> unused <-'))\n        },\n        HOT_UPDATED,\n        (logs) => {\n          expect(logs).toEqual(['-> unused <-', updated(url)])\n        },\n      )\n    })\n\n    test(\"doesn't accept itself if any of its exports is imported\", async () => {\n      const fileName = 'used.ts'\n      const file = `${testDir}/${fileName}`\n\n      await untilConsoleLogAfter(\n        () => setupModuleRunner(`/${testDir}/index`),\n        [CONNECTED, '-- used --', 'used:foo0'],\n        (logs) => {\n          expect(logs).toContain('-- used --')\n          expect(logs).toContain('used:foo0')\n        },\n      )\n\n      await untilConsoleLogAfter(\n        async () => {\n          editFile(file, (code) =>\n            code.replace('foo0', 'foo1').replace('-- used --', '-> used <-'),\n          )\n        },\n        [PROGRAM_RELOAD, /used:foo/],\n        (logs) => {\n          expect(logs).toContain('-> used <-')\n          expect(logs).toContain('used:foo1')\n        },\n      )\n    })\n  })\n\n  describe('indiscriminate imports: import *', () => {\n    const testStarExports = (testDirName: string) => {\n      const testDir = `${baseDir}/${testDirName}`\n\n      test('accepts itself if all its exports are accepted', async () => {\n        const fileName = 'deps-all-accepted.ts'\n        const file = `${testDir}/${fileName}`\n        const url = '/' + file\n\n        await untilConsoleLogAfter(\n          () => setupModuleRunner(`/${testDir}/index`),\n          [CONNECTED, '>>> ready <<<'],\n          (logs) => {\n            expect(logs).toContain('loaded:all:a0b0c0default0')\n            expect(logs).toContain('all >>>>>> a0, b0, c0')\n          },\n        )\n\n        await untilConsoleLogAfter(\n          () => {\n            editFile(file, (code) => code.replace(/([abc])0/g, '$11'))\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual(['all >>>>>> a1, b1, c1', updated(url)])\n          },\n        )\n\n        await untilConsoleLogAfter(\n          () => {\n            editFile(file, (code) => code.replace(/([abc])1/g, '$12'))\n          },\n          HOT_UPDATED,\n          (logs) => {\n            expect(logs).toEqual(['all >>>>>> a2, b2, c2', updated(url)])\n          },\n        )\n      })\n\n      test(\"doesn't accept itself if one export is not accepted\", async () => {\n        const fileName = 'deps-some-accepted.ts'\n        const file = `${testDir}/${fileName}`\n\n        await untilConsoleLogAfter(\n          () => setupModuleRunner(`/${testDir}/index`),\n          [CONNECTED, '>>> ready <<<'],\n          (logs) => {\n            expect(logs).toContain('loaded:some:a0b0c0default0')\n            expect(logs).toContain('some >>>>>> a0, b0, c0')\n          },\n        )\n\n        await untilConsoleLogAfter(\n          async () => {\n            editFile(file, (code) => code.replace(/([abc])0/g, '$11'))\n          },\n          [PROGRAM_RELOAD, '>>> ready <<<'],\n          (logs) => {\n            expect(logs).toContain('loaded:some:a1b1c1default0')\n            expect(logs).toContain('some >>>>>> a1, b1, c1')\n          },\n        )\n      })\n    }\n\n    describe('import * from ...', () => testStarExports('star-imports'))\n\n    describe('dynamic import(...)', () => testStarExports('dynamic-imports'))\n  })\n})\n\ntest('handle virtual module updates', async () => {\n  await setupModuleRunner('/hmr.ts')\n  const el = () => hmr('.virtual')\n  expect(el()).toBe('[success]0')\n  editFile('importedVirtual.js', (code) => code.replace('[success]', '[wow]'))\n  await expect.poll(el).toBe('[wow]0')\n})\n\ntest('invalidate virtual module', async () => {\n  await setupModuleRunner('/hmr.ts')\n  const el = () => hmr('.virtual')\n  expect(el()).toBe('[wow]0')\n  globalThis.__HMR__['virtual:increment']()\n  await expect.poll(el).toBe('[wow]1')\n})\n\ntest('should hmr when file is deleted and restored', async () => {\n  await setupModuleRunner('/hmr.ts')\n\n  const parentFile = 'file-delete-restore/parent.js'\n  const childFile = 'file-delete-restore/child.js'\n\n  await expect.poll(() => hmr('.file-delete-restore')).toMatch('parent:child')\n\n  editFile(childFile, (code) =>\n    code.replace(\"value = 'child'\", \"value = 'child1'\"),\n  )\n  await expect.poll(() => hmr('.file-delete-restore')).toMatch('parent:child1')\n\n  // delete the file\n  editFile(parentFile, (code) =>\n    code.replace(\n      \"export { value as childValue } from './child'\",\n      \"export const childValue = 'not-child'\",\n    ),\n  )\n  const originalChildFileCode = readFile(childFile)\n  removeFile(childFile)\n  await expect\n    .poll(() => hmr('.file-delete-restore'))\n    .toMatch('parent:not-child')\n\n  // restore the file\n  addFile(childFile, originalChildFileCode)\n  editFile(parentFile, (code) =>\n    code.replace(\n      \"export const childValue = 'not-child'\",\n      \"export { value as childValue } from './child'\",\n    ),\n  )\n  await expect.poll(() => hmr('.file-delete-restore')).toMatch('parent:child')\n})\n\ntest('delete file should not break hmr', async () => {\n  await setupModuleRunner('/hmr.ts', undefined, undefined, {\n    '.intermediate-file-delete-increment': '1',\n  })\n\n  await expect\n    .poll(() => hmr('.intermediate-file-delete-display'))\n    .toMatch('count is 1')\n\n  // add state\n  globalThis.__HMR__['.delete-intermediate-file']()\n  await expect\n    .poll(() => hmr('.intermediate-file-delete-display'))\n    .toMatch('count is 2')\n\n  // update import, hmr works\n  editFile('intermediate-file-delete/index.js', (code) =>\n    code.replace(\"from './re-export.js'\", \"from './display.js'\"),\n  )\n  editFile('intermediate-file-delete/display.js', (code) =>\n    code.replace('count is ${count}', 'count is ${count}!'),\n  )\n  await expect\n    .poll(() => hmr('.intermediate-file-delete-display'))\n    .toMatch('count is 2!')\n\n  // remove unused file\n  removeFile('intermediate-file-delete/re-export.js')\n  __HMR__['.intermediate-file-delete-increment'] = '1' // reset state\n  await expect\n    .poll(() => hmr('.intermediate-file-delete-display'))\n    .toMatch('count is 1!')\n\n  // re-add state\n  globalThis.__HMR__['.delete-intermediate-file']()\n  await expect\n    .poll(() => hmr('.intermediate-file-delete-display'))\n    .toMatch('count is 2!')\n\n  // hmr works after file deletion\n  editFile('intermediate-file-delete/display.js', (code) =>\n    code.replace('count is ${count}!', 'count is ${count}'),\n  )\n  await expect\n    .poll(() => hmr('.intermediate-file-delete-display'))\n    .toMatch('count is 2')\n})\n\ntest('deleted file should trigger dispose and prune callbacks', async () => {\n  await setupModuleRunner('/hmr.ts')\n\n  const parentFile = 'file-delete-restore/parent.js'\n  const childFile = 'file-delete-restore/child.js'\n  const originalChildFileCode = readFile(childFile)\n\n  await untilConsoleLogAfter(\n    () => {\n      // delete the file\n      editFile(parentFile, (code) =>\n        code.replace(\n          \"export { value as childValue } from './child'\",\n          \"export const childValue = 'not-child'\",\n        ),\n      )\n      removeFile(childFile)\n    },\n    [\n      'file-delete-restore/child.js is disposed',\n      'file-delete-restore/child.js is pruned',\n    ],\n    false,\n  )\n\n  await expect\n    .poll(() => hmr('.file-delete-restore'))\n    .toMatch('parent:not-child')\n\n  // restore the file\n  addFile(childFile, originalChildFileCode)\n  editFile(parentFile, (code) =>\n    code.replace(\n      \"export const childValue = 'not-child'\",\n      \"export { value as childValue } from './child'\",\n    ),\n  )\n  await expect.poll(() => hmr('.file-delete-restore')).toMatch('parent:child')\n})\n\ntest('import.meta.hot?.accept', async () => {\n  await setupModuleRunner('/hmr.ts')\n  await untilConsoleLogAfter(\n    () =>\n      editFile('optional-chaining/child.js', (code) =>\n        code.replace('const foo = 1', 'const foo = 2'),\n      ),\n    '(optional-chaining) child update',\n  )\n  await expect.poll(() => hmr('.optional-chaining')?.toString()).toMatch('2')\n})\n\ntest('hmr works for self-accepted module within circular imported files', async () => {\n  await setupModuleRunner('/self-accept-within-circular/index')\n  const el = () => hmr('.self-accept-within-circular')\n  expect(el()).toBe('c')\n  editFile('self-accept-within-circular/c.js', (code) =>\n    code.replace(`export const c = 'c'`, `export const c = 'cc'`),\n  )\n  // it throws a same error as browser case,\n  // but it doesn't auto reload and it calls `hot.accept(nextExports)` with `nextExports = undefined`\n\n  // test reloading manually for now\n  server.moduleGraph.invalidateAll() // TODO: why is `runner.clearCache()` not enough?\n  await runner.import('/self-accept-within-circular/index')\n  await expect.poll(() => el()).toBe('cc')\n})\n\ntest('hmr should not reload if no accepted within circular imported files', async () => {\n  await setupModuleRunner('/circular/index')\n  const el = () => hmr('.circular')\n  expect(el()).toBe(\n    // tests in the browser check that there is an error, but vite runtime just returns undefined in those cases\n    'mod-a -> mod-b -> mod-c -> undefined (expected no error)',\n  )\n  editFile('circular/mod-b.js', (code) =>\n    code.replace(`mod-b ->`, `mod-b (edited) ->`),\n  )\n  await expect\n    .poll(() => el())\n    .toBe('mod-a -> mod-b (edited) -> mod-c -> undefined (expected no error)')\n})\n\ntest('not inlined assets HMR', async () => {\n  await setupModuleRunner('/hmr.ts')\n  const el = () => hmr('#logo-no-inline')\n  await untilConsoleLogAfter(\n    () =>\n      editFile('logo-no-inline.svg', (code) =>\n        code.replace('height=\"30px\"', 'height=\"40px\"'),\n      ),\n    /Logo-no-inline updated/,\n  )\n  await vi.waitUntil(() => el().includes('logo-no-inline.svg?t='))\n})\n\ntest('inlined assets HMR', async () => {\n  await setupModuleRunner('/hmr.ts')\n  const el = () => hmr('#logo')\n  const initialLogoUrl = el()\n  expect(initialLogoUrl).toMatch(/^data:image\\/svg\\+xml/)\n  await untilConsoleLogAfter(\n    () =>\n      editFile('logo.svg', (code) =>\n        code.replace('height=\"30px\"', 'height=\"40px\"'),\n      ),\n    /Logo updated/,\n  )\n  // Should be updated with new data url\n  const updatedLogoUrl = el()\n  expect(updatedLogoUrl).toMatch(/^data:image\\/svg\\+xml/)\n  expect(updatedLogoUrl).not.toEqual(initialLogoUrl)\n})\n\ntype UntilBrowserLogAfterCallback = (logs: string[]) => PromiseLike<void> | void\n\nexport async function untilConsoleLogAfter(\n  operation: () => any,\n  target: string | RegExp | Array<string | RegExp>,\n  expectOrder?: boolean,\n  callback?: UntilBrowserLogAfterCallback,\n): Promise<string[]>\nexport async function untilConsoleLogAfter(\n  operation: () => any,\n  target: string | RegExp | Array<string | RegExp>,\n  callback?: UntilBrowserLogAfterCallback,\n): Promise<string[]>\nexport async function untilConsoleLogAfter(\n  operation: () => any,\n  target: string | RegExp | Array<string | RegExp>,\n  arg3?: boolean | UntilBrowserLogAfterCallback,\n  arg4?: UntilBrowserLogAfterCallback,\n): Promise<string[]> {\n  const expectOrder = typeof arg3 === 'boolean' ? arg3 : false\n  const callback = typeof arg3 === 'boolean' ? arg4 : arg3\n\n  const promise = untilConsoleLog(target, expectOrder)\n  await operation()\n  const logs = await promise\n  if (callback) {\n    await callback(logs)\n  }\n  return logs\n}\n\nasync function untilConsoleLog(\n  target?: string | RegExp | Array<string | RegExp>,\n  expectOrder = true,\n): Promise<string[]> {\n  const { promise, resolve, reject } = promiseWithResolvers<void>()\n  let timeoutId: ReturnType<typeof setTimeout>\n\n  const logsMessages = []\n\n  try {\n    const isMatch = (matcher: string | RegExp) => (text: string) =>\n      typeof matcher === 'string' ? text === matcher : matcher.test(text)\n\n    let processMsg: (text: string) => boolean\n\n    if (!target) {\n      processMsg = () => true\n    } else if (Array.isArray(target)) {\n      if (expectOrder) {\n        const remainingTargets = [...target]\n        processMsg = (text: string) => {\n          const nextTarget = remainingTargets.shift()\n          expect(text).toMatch(nextTarget)\n          return remainingTargets.length === 0\n        }\n      } else {\n        const remainingMatchers = target.map(isMatch)\n        processMsg = (text: string) => {\n          const nextIndex = remainingMatchers.findIndex((matcher) =>\n            matcher(text),\n          )\n          if (nextIndex >= 0) {\n            remainingMatchers.splice(nextIndex, 1)\n          }\n          return remainingMatchers.length === 0\n        }\n      }\n    } else {\n      processMsg = isMatch(target)\n    }\n\n    const handleMsg = (text: string) => {\n      try {\n        text = text.replace(/\\n$/, '')\n        logsMessages.push(text)\n        const done = processMsg(text)\n        if (done) {\n          resolve()\n          logsEmitter.off('log', handleMsg)\n        }\n      } catch (err) {\n        reject(err)\n        logsEmitter.off('log', handleMsg)\n      }\n    }\n\n    timeoutId = setTimeout(() => {\n      const nextTarget = Array.isArray(target)\n        ? expectOrder\n          ? target[0]\n          : target.join(', ')\n        : target\n      reject(\n        new Error(\n          `Timeout waiting for console logs. Waiting for: ${nextTarget}`,\n        ),\n      )\n      logsEmitter.off('log', handleMsg)\n    }, 5000)\n\n    logsEmitter.on('log', handleMsg)\n  } catch (err) {\n    reject(err)\n  }\n\n  await promise\n  clearTimeout(timeoutId)\n\n  return logsMessages\n}\n\nfunction isWatched(server: ViteDevServer, watchedFile: string) {\n  const watched = server.watcher.getWatched()\n  for (const [dir, files] of Object.entries(watched)) {\n    const unixDir = slash(dir)\n    for (const file of files) {\n      const filePath = posix.join(unixDir, file)\n      if (filePath.includes(watchedFile)) {\n        return true\n      }\n    }\n  }\n  return false\n}\n\nfunction waitForWatcher(server: ViteDevServer, watched: string) {\n  return new Promise<void>((resolve) => {\n    function checkWatched() {\n      if (isWatched(server, watched)) {\n        resolve()\n      } else {\n        setTimeout(checkWatched, 20)\n      }\n    }\n    checkWatched()\n  })\n}\n\nasync function setupModuleRunner(\n  entrypoint: string,\n  serverOptions: InlineConfig = {},\n  waitForFile: string = entrypoint,\n  initHmrState: Record<string, string> = {},\n) {\n  if (server) {\n    await server.close()\n    clientLogs.length = 0\n    serverLogs.length = 0\n    runner.clearCache()\n  }\n\n  globalThis.__HMR__ = initHmrState as any\n\n  const logger = new HMRMockLogger()\n  // @ts-expect-error not typed for HMR\n  globalThis.log = (...msg) => logger.log(...msg)\n\n  server = await createServer({\n    configFile: resolve(testDir, 'vite.config.ts'),\n    root: testDir,\n    customLogger: createInMemoryLogger(serverLogs),\n    server: {\n      middlewareMode: true,\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n      hmr: {\n        port: 9609,\n      },\n      preTransformRequests: false,\n    },\n    environments: {\n      ssr: {\n        dev: {\n          createEnvironment(name, config) {\n            return createRunnableDevEnvironment(name, config, {\n              runnerOptions: { hmr: { logger } },\n            })\n          },\n        },\n      },\n    },\n    optimizeDeps: {\n      disabled: true,\n      noDiscovery: true,\n      include: [],\n    },\n    ...serverOptions,\n  })\n\n  runner = (server.environments.ssr as RunnableDevEnvironment).runner\n\n  await waitForWatcher(server, waitForFile)\n\n  await runner.import(entrypoint)\n\n  return {\n    runtime: runner,\n    server,\n  }\n}\n\nclass HMRMockLogger {\n  log(...msg: unknown[]) {\n    const log = msg.join(' ')\n    clientLogs.push(log)\n    logsEmitter.emit('log', log)\n  }\n\n  debug(...msg: unknown[]) {\n    const log = ['[vite]', ...msg].join(' ')\n    clientLogs.push(log)\n    logsEmitter.emit('log', log)\n  }\n  error(msg: string) {\n    const log = ['[vite]', msg].join(' ')\n    clientLogs.push(log)\n    logsEmitter.emit('log', log)\n  }\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/dynamic-imports/deps-all-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nlog(`all >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'c', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/dynamic-imports/deps-some-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nlog(`some >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/dynamic-imports/dynamic-imports.ts",
    "content": "Promise.all([import('./deps-all-accepted'), import('./deps-some-accepted')])\n  .then(([all, some]) => {\n    log('loaded:all:' + all.a + all.b + all.c + all.default)\n    log('loaded:some:' + some.a + some.b + some.c + some.default)\n    log('>>> ready <<<')\n  })\n  .catch((err) => {\n    log(err)\n  })\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/dynamic-imports/index.ts",
    "content": "import './dynamic-imports.ts'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/export-from/depA.ts",
    "content": "export const a = 'Ax'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/export-from/export-from.ts",
    "content": "import { a } from './hub'\n\nlog(a)\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n} else {\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/export-from/hub.ts",
    "content": "export * from './depA'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/export-from/index.html",
    "content": "<script type=\"module\" src=\"./export-from.ts\"></script>\n\n<div class=\"app\"></div>\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-accepted/callback.ts",
    "content": "export const x = 'X'\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['x'], (m) => {\n    log(`reloaded >>> ${m.x}`)\n  })\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-accepted/dep.ts",
    "content": "export default 'dep0'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-accepted/index.ts",
    "content": "import './main-accepted'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-accepted/main-accepted.ts",
    "content": "import def, { a } from './target'\nimport { x } from './callback'\n\n// we don't want to pollute other checks' logs...\nif (0 > 1) log(x)\n\nlog(`>>>>>> ${a} ${def}`)\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-accepted/target.ts",
    "content": "import dep from './dep'\n\nexport const a = 'A0'\n\nconst bValue = 'B0'\nexport { bValue as b }\n\nconst def = 'D0'\n\nexport default def\n\nlog(`<<<<<< ${a} ${bValue} ${def} ; ${dep}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-non-accepted/default.ts",
    "content": "export const x = 'y'\n\nconst def = 'def0'\n\nexport default def\n\nlog(`<<< default: ${def}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['x'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-non-accepted/dep.ts",
    "content": "export default 'dep0'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-non-accepted/index.ts",
    "content": "import './main-non-accepted.ts'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-non-accepted/main-non-accepted.ts",
    "content": "import { a } from './named'\nimport def from './default'\n\nlog(`>>>>>> ${a} ${def}`)\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/main-non-accepted/named.ts",
    "content": "import dep from './dep'\n\nexport const a = 'A0'\n\nexport const b = 'B0'\n\nlog(`<<< named: ${a} ; ${dep}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['b'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/reexports.bak/accept-named.ts",
    "content": "export { a, b } from './source'\n\nif (import.meta.hot) {\n  // import.meta.hot.accept('./source', (m) => {\n  //   log(`accept-named reexport:${m.a},${m.b}`)\n  // })\n  import.meta.hot.acceptExports('a', (m) => {\n    log(`accept-named reexport:${m.a},${m.b}`)\n  })\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/reexports.bak/index.html",
    "content": "<script type=\"module\" src=\"./reexports.ts\"></script>\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/reexports.bak/reexports.ts",
    "content": "import { a } from './accept-named'\n\nlog('accept-named:' + a)\n\nlog('>>> ready')\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/reexports.bak/source.ts",
    "content": "export const a = 'a0'\nexport const b = 'b0'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/side-effects/index.ts",
    "content": "import './side-effects.ts'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/side-effects/side-effects.ts",
    "content": "export const x = 'x'\n\nexport const y = 'y'\n\nexport default 'z'\n\nlog('>>> side FX')\n\nglobalThis.__HMR__['.app'] = 'hey'\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['default'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/star-imports/deps-all-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nlog(`all >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'c', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/star-imports/deps-some-accepted.ts",
    "content": "export const a = 'a0'\n\nexport const b = 'b0'\n\nconst aliased = 'c0'\nexport { aliased as c }\n\nexport default 'default0'\n\nlog(`some >>>>>> ${a}, ${b}, ${aliased}`)\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports(['a', 'b', 'default'])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/star-imports/index.ts",
    "content": "import './star-imports.ts'\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/star-imports/star-imports.ts",
    "content": "import * as all from './deps-all-accepted'\nimport * as some from './deps-some-accepted'\n\nlog('loaded:all:' + all.a + all.b + all.c + all.default)\nlog('loaded:some:' + some.a + some.b + some.c + some.default)\nlog('>>> ready <<<')\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/unused-exports/index.html",
    "content": "<script type=\"module\" src=\"./index.ts\"></script>\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/unused-exports/index.ts",
    "content": "import './unused'\nimport { foo } from './used'\n\nlog('used:' + foo)\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/unused-exports/unused.ts",
    "content": "export const x = 'x'\n\nexport const y = 'y'\n\nexport default 'z'\n\nlog('-- unused --')\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports([])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/accept-exports/unused-exports/used.ts",
    "content": "export const foo = 'foo0'\n\nexport const bar = 'bar0'\n\nlog('-- used --')\n\nif (import.meta.hot) {\n  import.meta.hot.acceptExports([])\n}\n"
  },
  {
    "path": "playground/hmr-ssr/circular/index.js",
    "content": "import { msg } from './mod-a'\n\nglobalThis.__HMR__['.circular'] = msg\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr-ssr/circular/mod-a.js",
    "content": "export const value = 'mod-a'\n\nimport { value as _value } from './mod-b'\n\nexport const msg = `mod-a -> ${_value}`\n"
  },
  {
    "path": "playground/hmr-ssr/circular/mod-b.js",
    "content": "import { value as _value } from './mod-c'\n\nexport const value = `mod-b -> ${_value}`\n"
  },
  {
    "path": "playground/hmr-ssr/circular/mod-c.js",
    "content": "import { value as _value } from './mod-a'\n\n// Should error as `_value` is not defined yet within the circular imports\nlet __value\ntry {\n  __value = `${_value} (expected no error)`\n} catch {\n  __value = 'mod-a (unexpected error)'\n}\n\nexport const value = `mod-c -> ${__value}`\n"
  },
  {
    "path": "playground/hmr-ssr/counter/dep.ts",
    "content": "// This file is never loaded\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {})\n}\n"
  },
  {
    "path": "playground/hmr-ssr/counter/index.ts",
    "content": "let count = 0\nexport function increment() {\n  count++\n}\nexport function getCount() {\n  return count\n}\n// @ts-expect-error not used but this is to test that it works\nfunction neverCalled() {\n  import('./dep')\n}\n"
  },
  {
    "path": "playground/hmr-ssr/customFile.js",
    "content": "export const msg = 'custom'\n"
  },
  {
    "path": "playground/hmr-ssr/event.d.ts",
    "content": "import 'vite/types/customEvent'\n\ndeclare module 'vite/types/customEvent' {\n  interface CustomEventMap {\n    'custom:foo': { msg: string }\n    'custom:remote-add': { a: number; b: number }\n    'custom:remote-add-result': { result: string }\n  }\n}\n\ndeclare global {\n  let log: (...msg: unknown[]) => void\n  let logger: {\n    error: (msg: string | Error) => void\n    debug: (...msg: unknown[]) => void\n  }\n}\n"
  },
  {
    "path": "playground/hmr-ssr/file-delete-restore/child.js",
    "content": "import { rerender } from './runtime'\n\nexport const value = 'child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept((newMod) => {\n    if (!newMod) return\n\n    rerender({ child: newMod.value })\n  })\n\n  import.meta.hot.dispose(() => {\n    log('file-delete-restore/child.js is disposed')\n  })\n\n  import.meta.hot.prune(() => {\n    log('file-delete-restore/child.js is pruned')\n  })\n}\n"
  },
  {
    "path": "playground/hmr-ssr/file-delete-restore/index.js",
    "content": "import { render } from './runtime'\nimport { childValue, parentValue } from './parent'\n\nrender({ parent: parentValue, child: childValue })\n"
  },
  {
    "path": "playground/hmr-ssr/file-delete-restore/parent.js",
    "content": "import { rerender } from './runtime'\n\nexport const parentValue = 'parent'\nexport { value as childValue } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept((newMod) => {\n    if (!newMod) return\n\n    rerender({ child: newMod.childValue, parent: newMod.parentValue })\n  })\n}\n"
  },
  {
    "path": "playground/hmr-ssr/file-delete-restore/runtime.js",
    "content": "let state = {}\n\nexport const render = (newState) => {\n  state = newState\n  apply()\n}\n\nexport const rerender = (updates) => {\n  state = { ...state, ...updates }\n  apply()\n}\n\nconst apply = () => {\n  globalThis.__HMR__['.file-delete-restore'] = Object.values(state).join(':')\n}\n"
  },
  {
    "path": "playground/hmr-ssr/hmr.ts",
    "content": "import { virtual } from 'virtual:file'\nimport { foo as depFoo, nestedFoo } from './hmrDep'\nimport './importing-updated'\nimport './invalidation-circular-deps'\nimport './invalidation/parent'\nimport './file-delete-restore'\nimport './optional-chaining/parent'\nimport './intermediate-file-delete'\nimport './circular'\nimport './queries'\nimport logo from './logo.svg'\nimport logoNoInline from './logo-no-inline.svg'\nimport { msg as softInvalidationMsg } from './soft-invalidation'\n\nexport const foo = 1\ntext('.app', foo)\ntext('.dep', depFoo)\ntext('.nested', nestedFoo)\ntext('.virtual', virtual)\ntext('.soft-invalidation', softInvalidationMsg)\nsetImgSrc('#logo', logo)\nsetImgSrc('#logo-no-inline', logoNoInline)\n\nglobalThis.__HMR__['virtual:increment'] = () => {\n  if (import.meta.hot) {\n    import.meta.hot.send('virtual:increment')\n  }\n}\n\nif (import.meta.hot) {\n  import.meta.hot.accept(({ foo }) => {\n    log('(self-accepting 1) foo is now:', foo)\n  })\n\n  import.meta.hot.accept(({ foo }) => {\n    log('(self-accepting 2) foo is now:', foo)\n  })\n\n  const handleDep = (type, newFoo, newNestedFoo) => {\n    log(`(${type}) foo is now: ${newFoo}`)\n    log(`(${type}) nested foo is now: ${newNestedFoo}`)\n    text('.dep', newFoo)\n    text('.nested', newNestedFoo)\n  }\n\n  import.meta.hot.accept('./logo.svg', (newUrl) => {\n    setImgSrc('#logo', newUrl.default)\n    log('Logo updated', newUrl.default)\n  })\n\n  import.meta.hot.accept('./logo-no-inline.svg', (newUrl) => {\n    setImgSrc('#logo-no-inline', newUrl.default)\n    log('Logo-no-inline updated', newUrl.default)\n  })\n\n  import.meta.hot.accept('./hmrDep', ({ foo, nestedFoo }) => {\n    handleDep('single dep', foo, nestedFoo)\n  })\n\n  import.meta.hot.accept(['./hmrDep'], ([{ foo, nestedFoo }]) => {\n    handleDep('multi deps', foo, nestedFoo)\n  })\n\n  import.meta.hot.dispose(() => {\n    log(`foo was:`, foo)\n  })\n\n  import.meta.hot.on('vite:afterUpdate', (event) => {\n    log(`>>> vite:afterUpdate -- ${event.type}`)\n  })\n\n  import.meta.hot.on('vite:beforeUpdate', (event) => {\n    log(`>>> vite:beforeUpdate -- ${event.type}`)\n\n    const cssUpdate = event.updates.find(\n      (update) =>\n        update.type === 'css-update' && update.path.includes('global.css'),\n    )\n    if (cssUpdate) {\n      log('CSS updates are not supported in SSR')\n    }\n  })\n\n  import.meta.hot.on('vite:error', (event) => {\n    log(`>>> vite:error -- ${event.err.message}`)\n  })\n\n  import.meta.hot.on('vite:invalidate', ({ path }) => {\n    log(`>>> vite:invalidate -- ${path}`)\n  })\n\n  import.meta.hot.on('custom:foo', ({ msg }) => {\n    text('.custom', msg)\n  })\n\n  import.meta.hot.on('custom:remove', removeCb)\n\n  // send custom event to server to calculate 1 + 2\n  import.meta.hot.send('custom:remote-add', { a: 1, b: 2 })\n  import.meta.hot.on('custom:remote-add-result', ({ result }) => {\n    text('.custom-communication', result)\n  })\n}\n\nfunction text(el, text) {\n  hmr(el, text)\n}\n\nfunction setImgSrc(el, src) {\n  hmr(el, src)\n}\n\nfunction removeCb({ msg }) {\n  text('.toRemove', msg)\n  import.meta.hot.off('custom:remove', removeCb)\n}\n\nfunction hmr(key: string, value: unknown) {\n  ;(globalThis.__HMR__ as any)[key] = String(value)\n}\n"
  },
  {
    "path": "playground/hmr-ssr/hmrDep.js",
    "content": "export const foo = 1\nexport { foo as nestedFoo } from './hmrNestedDep'\n\nif (import.meta.hot) {\n  const data = import.meta.hot.data\n  if ('fromDispose' in data) {\n    log(`(dep) foo from dispose: ${data.fromDispose}`)\n  }\n\n  import.meta.hot.dispose((data) => {\n    log(`(dep) foo was: ${foo}`)\n    data.fromDispose = foo\n  })\n}\n"
  },
  {
    "path": "playground/hmr-ssr/hmrNestedDep.js",
    "content": "export const foo = 1\n"
  },
  {
    "path": "playground/hmr-ssr/importedVirtual.js",
    "content": "export const virtual = '[success]'\n"
  },
  {
    "path": "playground/hmr-ssr/importing-updated/a.js",
    "content": "const val = 'a0'\nglobalThis.__HMR__['.importing-reloaded'] ??= ''\nglobalThis.__HMR__['.importing-reloaded'] += `a.js: ${val}<br>`\n\nexport default val\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr-ssr/importing-updated/b.js",
    "content": "import a from './a.js'\n\nconst val = `b0,${a}`\n\nglobalThis.__HMR__['.importing-reloaded'] ??= ''\nglobalThis.__HMR__['.importing-reloaded'] += `b.js: ${val}<br>`\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n"
  },
  {
    "path": "playground/hmr-ssr/importing-updated/index.js",
    "content": "import './a'\nimport './b'\n"
  },
  {
    "path": "playground/hmr-ssr/intermediate-file-delete/display.js",
    "content": "export const displayCount = (count) => `count is ${count}`\n"
  },
  {
    "path": "playground/hmr-ssr/intermediate-file-delete/index.js",
    "content": "import { displayCount } from './re-export.js'\n\nconst incrementValue = () =>\n  globalThis.__HMR__['.intermediate-file-delete-increment']\n\nconst render = () => {\n  globalThis.__HMR__['.intermediate-file-delete-display'] = displayCount(\n    Number(incrementValue()),\n  )\n}\n\nrender()\n\nglobalThis.__HMR__['.delete-intermediate-file'] = () => {\n  globalThis.__HMR__['.intermediate-file-delete-increment'] = `${\n    Number(incrementValue()) + 1\n  }`\n  render()\n}\n\nif (import.meta.hot) import.meta.hot.accept()\n"
  },
  {
    "path": "playground/hmr-ssr/intermediate-file-delete/re-export.js",
    "content": "export * from './display.js'\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation/child.js",
    "content": "if (import.meta.hot) {\n  // Need to accept, to register a callback for HMR\n  import.meta.hot.accept(() => {\n    // Trigger HMR in importers\n    import.meta.hot.invalidate()\n  })\n}\n\nexport const value = 'child'\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation/parent.js",
    "content": "import { value } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept()\n}\n\nlog('(invalidation) parent is executing')\n\nglobalThis.__HMR__['.invalidation'] = value\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation-circular-deps/circular-invalidate/child.js",
    "content": "import './parent'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {\n    import.meta.hot.invalidate()\n  })\n}\n\nexport const value = 'child'\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation-circular-deps/circular-invalidate/parent.js",
    "content": "import { value } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {\n    import.meta.hot.invalidate()\n  })\n}\n\nlog('(invalidation circular deps) parent is executing')\nsetTimeout(() => {\n  globalThis.__HMR__['.invalidation-circular-deps'] = value\n})\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation-circular-deps/index.js",
    "content": "import './circular-invalidate/parent'\nimport './invalidate-handled-in-circle/parent'\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation-circular-deps/invalidate-handled-in-circle/child.js",
    "content": "import './parent'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {\n    import.meta.hot.invalidate()\n  })\n}\n\nexport const value = 'child'\n"
  },
  {
    "path": "playground/hmr-ssr/invalidation-circular-deps/invalidate-handled-in-circle/parent.js",
    "content": "import { value } from './child'\n\nif (import.meta.hot) {\n  import.meta.hot.accept(() => {})\n}\n\nlog('(invalidation circular deps handled) parent is executing')\nsetTimeout(() => {\n  globalThis.__HMR__['.invalidation-circular-deps-handled'] = value\n})\n"
  },
  {
    "path": "playground/hmr-ssr/missing-import/a.js",
    "content": "import 'missing-modules'\n\nlog('missing test')\n"
  },
  {
    "path": "playground/hmr-ssr/missing-import/index.js",
    "content": "import './main.js'\n"
  },
  {
    "path": "playground/hmr-ssr/missing-import/main.js",
    "content": "import './a.js'\n"
  },
  {
    "path": "playground/hmr-ssr/modules.d.ts",
    "content": "declare module 'virtual:file' {\n  export const virtual: string\n}\ndeclare module '*?query1' {\n  const string: string\n  export default string\n}\ndeclare module '*?query2' {\n  const string: string\n  export default string\n}\n"
  },
  {
    "path": "playground/hmr-ssr/non-tested/dep.js",
    "content": "export const test = 'true'\n\nimport.meta.hot.accept()\n"
  },
  {
    "path": "playground/hmr-ssr/non-tested/index.js",
    "content": "import { test } from './dep.js'\n\nfunction main() {\n  test()\n}\n\nmain()\n\nimport.meta.hot.accept('./dep.js')\n"
  },
  {
    "path": "playground/hmr-ssr/optional-chaining/child.js",
    "content": "export const foo = 1\n"
  },
  {
    "path": "playground/hmr-ssr/optional-chaining/parent.js",
    "content": "// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport { foo } from './child'\n\nimport.meta.hot?.accept('./child', ({ foo }) => {\n  log('(optional-chaining) child update')\n  globalThis.__HMR__['.optional-chaining'] = foo\n})\n"
  },
  {
    "path": "playground/hmr-ssr/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-hmr-ssr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/hmr-ssr/queries/index.js",
    "content": "import query1 from './multi-query?query1'\nimport query2 from './multi-query?query2'\n\nhmr('query1', query1)\nhmr('query2', query2)\n\nfunction hmr(key, value) {\n  globalThis.__HMR__[key] = String(value)\n}\n"
  },
  {
    "path": "playground/hmr-ssr/queries/multi-query.js",
    "content": ""
  },
  {
    "path": "playground/hmr-ssr/self-accept-within-circular/a.js",
    "content": "import { b } from './b'\n\nexport const a = {\n  b,\n}\n"
  },
  {
    "path": "playground/hmr-ssr/self-accept-within-circular/b.js",
    "content": "import { c } from './c'\n\nconst b = {\n  c,\n}\n\nexport { b }\n"
  },
  {
    "path": "playground/hmr-ssr/self-accept-within-circular/c.js",
    "content": "import './b'\n\nexport const c = 'c'\n\nfunction render(content) {\n  globalThis.__HMR__['.self-accept-within-circular'] = content\n}\nrender(c)\n\nimport.meta.hot?.accept((nextExports) => {\n  render(nextExports?.c)\n})\n"
  },
  {
    "path": "playground/hmr-ssr/self-accept-within-circular/index.js",
    "content": "import { a } from './a'\n\nlog(a)\n"
  },
  {
    "path": "playground/hmr-ssr/soft-invalidation/child.js",
    "content": "export const foo = 'bar'\n"
  },
  {
    "path": "playground/hmr-ssr/soft-invalidation/index.js",
    "content": "import { foo } from './child'\n\n// @ts-expect-error global\nexport const msg = `soft-invalidation/index.js is transformed ${__TRANSFORM_COUNT__} times. child is ${foo}`\n"
  },
  {
    "path": "playground/hmr-ssr/unresolved.ts",
    "content": "export const foo = 1\nhmr('.app', foo)\n\nif (import.meta.hot) {\n  import.meta.hot.accept(({ foo }) => {\n    log('(self-accepting 1) foo is now:', foo)\n  })\n\n  import.meta.hot.accept(({ foo }) => {\n    log('(self-accepting 2) foo is now:', foo)\n  })\n\n  import.meta.hot.dispose(() => {\n    log(`foo was:`, foo)\n  })\n}\n\nfunction hmr(key: string, value: unknown) {\n  ;(globalThis.__HMR__ as any)[key] = String(value)\n}\n"
  },
  {
    "path": "playground/hmr-ssr/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport type { Plugin } from 'vite'\n\nexport default defineConfig({\n  experimental: {\n    hmrPartialAccept: true,\n  },\n  build: {\n    assetsInlineLimit(filePath) {\n      if (filePath.endsWith('logo-no-inline.svg')) {\n        return false\n      }\n    },\n  },\n  plugins: [\n    {\n      name: 'mock-custom',\n      async hotUpdate({ file, read, server }) {\n        if (file.endsWith('customFile.js')) {\n          const content = await read()\n          const msg = content.match(/export const msg = '(\\w+)'/)[1]\n          this.environment.hot.send('custom:foo', { msg })\n          this.environment.hot.send('custom:remove', { msg })\n        }\n      },\n      configureServer(server) {\n        server.environments.ssr.hot.on(\n          'custom:remote-add',\n          ({ a, b }, client) => {\n            client.send('custom:remote-add-result', { result: a + b })\n          },\n        )\n      },\n    },\n    virtualPlugin(),\n    transformCountPlugin(),\n    queryPlugin(),\n  ],\n})\n\nfunction virtualPlugin(): Plugin {\n  let num = 0\n  return {\n    name: 'virtual-file',\n    resolveId(id, importer) {\n      if (id === 'virtual:file' || id === '\\0virtual:file') {\n        return '\\0virtual:file'\n      }\n    },\n    load(id) {\n      if (id === '\\0virtual:file') {\n        return `\\\nimport { virtual as _virtual } from \"/importedVirtual.js\";\nexport const virtual = _virtual + '${num}';`\n      }\n    },\n    configureServer(server) {\n      server.environments.ssr.hot.on('virtual:increment', async () => {\n        const mod =\n          await server.environments.ssr.moduleGraph.getModuleByUrl(\n            '\\0virtual:file',\n          )\n        if (mod) {\n          num++\n          server.environments.ssr.reloadModule(mod)\n        }\n      })\n    },\n  }\n}\n\nfunction queryPlugin(): Plugin {\n  return {\n    name: 'query-resolver',\n    transform(code, id) {\n      if (id.includes('?query1')) {\n        return `export default ${JSON.stringify(code + 'query1')}`\n      }\n\n      if (id.includes('?query2')) {\n        return `export default ${JSON.stringify(code + 'query2')}`\n      }\n    },\n  }\n}\n\nfunction transformCountPlugin(): Plugin {\n  let num = 0\n  return {\n    name: 'transform-count',\n    transform(code) {\n      if (code.includes('__TRANSFORM_COUNT__')) {\n        return code.replace('__TRANSFORM_COUNT__', String(++num))\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "playground/html/__tests__/html.spec.ts",
    "content": "import { beforeAll, describe, expect, test } from 'vitest'\nimport {\n  browserLogs,\n  editFile,\n  getColor,\n  isBuild,\n  isServe,\n  page,\n  serverLogs,\n  untilBrowserLogAfter,\n  viteServer,\n  viteTestUrl,\n} from '~utils'\n\nfunction fetchHtml(p: string) {\n  return fetch(viteTestUrl + p, {\n    headers: { Accept: 'text/html,*/*' },\n  })\n}\n\nfunction testPage(isNested: boolean) {\n  test('pre transform', async () => {\n    expect(await page.$('head meta[name=viewport]')).toBeTruthy()\n  })\n\n  test('string transform', async () => {\n    expect(await page.textContent('h1')).toBe(\n      isNested ? 'Nested' : 'Transformed',\n    )\n  })\n\n  test('tags transform', async () => {\n    const el = await page.$('head meta[name=description]')\n    expect(await el.getAttribute('content')).toBe('a vite app')\n\n    const kw = await page.$('head meta[name=keywords]')\n    expect(await kw.getAttribute('content')).toBe('es modules')\n  })\n\n  test('combined transform', async () => {\n    expect(await page.title()).toBe('Test HTML transforms')\n    // the p should be injected to body\n    expect(await page.textContent('body p.inject')).toBe('This is injected')\n  })\n\n  test('server only transform', async () => {\n    if (!isBuild) {\n      expect(await page.textContent('body p.server')).toMatch(\n        'injected only during dev',\n      )\n    } else {\n      expect(await page.innerHTML('body')).not.toMatch('p class=\"server\"')\n    }\n  })\n\n  test('build only transform', async () => {\n    if (isBuild) {\n      expect(await page.textContent('body p.build')).toMatch(\n        'injected only during build',\n      )\n    } else {\n      expect(await page.innerHTML('body')).not.toMatch('p class=\"build\"')\n    }\n  })\n\n  test('conditional transform', async () => {\n    if (isNested) {\n      expect(await page.textContent('body p.conditional')).toMatch(\n        'injected only for /nested/',\n      )\n    } else {\n      expect(await page.innerHTML('body')).not.toMatch('p class=\"conditional\"')\n    }\n  })\n\n  test('body prepend/append transform', async () => {\n    expect(await page.innerHTML('body')).toMatch(\n      /prepended to body(.*)appended to body/s,\n    )\n  })\n\n  test('css', async () => {\n    expect(await getColor('h1')).toBe(isNested ? 'red' : 'blue')\n    expect(await getColor('p')).toBe('grey')\n  })\n\n  if (isNested) {\n    test('relative path in html asset', async () => {\n      expect(await page.textContent('.relative-js')).toMatch('hello')\n      expect(await getColor('.relative-css')).toMatch('red')\n    })\n  }\n}\n\ndescribe('main', () => {\n  testPage(false)\n\n  test('preserve comments', async () => {\n    const html = await page.innerHTML('body')\n    expect(html).toMatch(`<!-- comment one -->`)\n    expect(html).toMatch(`<!-- comment two -->`)\n  })\n\n  test('external paths works with vite-ignore attribute', async () => {\n    expect(await page.textContent('.external-path')).toBe('works')\n    expect(await page.getAttribute('.external-path', 'vite-ignore')).toBe(null)\n    expect(await getColor('.external-path')).toBe('red')\n    if (isServe) {\n      expect(serverLogs).not.toEqual(\n        expect.arrayContaining([\n          expect.stringMatching('Failed to load url /external-path.js'),\n        ]),\n      )\n    } else {\n      expect(serverLogs).not.toEqual(\n        expect.arrayContaining([\n          expect.stringMatching(\n            /\"\\/external-path\\.js\".*can't be bundled without type=\"module\" attribute/,\n          ),\n        ]),\n      )\n    }\n  })\n\n  test.runIf(isBuild)(\n    'external paths by rollupOptions.external works',\n    async () => {\n      expect(await page.textContent('.external-path-by-rollup-options')).toBe(\n        'works',\n      )\n      expect(serverLogs).not.toEqual(\n        expect.arrayContaining([expect.stringContaining('Could not load')]),\n      )\n    },\n  )\n})\n\ndescribe('nested', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/nested/')\n  })\n\n  testPage(true)\n})\n\ndescribe('nested w/ query', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/nested/index.html?v=1')\n  })\n\n  testPage(true)\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  describe('scriptAsync', () => {\n    beforeAll(async () => {\n      await page.goto(viteTestUrl + '/scriptAsync.html')\n    })\n\n    test('script is async', async () => {\n      expect(await page.$('head script[type=module][async]')).toBeTruthy()\n      expect(await page.$('head script[type=module]:not([async])')).toBeNull()\n    })\n  })\n\n  describe('scriptMixed', () => {\n    beforeAll(async () => {\n      await page.goto(viteTestUrl + '/scriptMixed.html')\n    })\n\n    test('script is mixed', async () => {\n      expect(await page.$('head script[type=module][async]')).toBeNull()\n      expect(await page.$('head script[type=module]:not([async])')).toBeTruthy()\n    })\n  })\n\n  describe('zeroJS', () => {\n    // Ensure that the modulePreload polyfill is discarded in this case\n\n    beforeAll(async () => {\n      await page.goto(viteTestUrl + '/zeroJS.html')\n    })\n\n    test('zeroJS', async () => {\n      expect(await page.$('head script[type=module]')).toBeNull()\n    })\n  })\n\n  describe('inline entry', () => {\n    const _countTags = (selector) => page.$$eval(selector, (t) => t.length)\n    const countScriptTags = _countTags.bind(this, 'script[type=module]')\n    const countPreloadTags = _countTags.bind(this, 'link[rel=modulepreload]')\n\n    test('is inlined', async () => {\n      await page.goto(viteTestUrl + '/inline/shared-2.html?v=1')\n      expect(await countScriptTags()).toBeGreaterThan(1)\n      expect(await countPreloadTags()).toBe(0)\n    })\n\n    test('is not inlined', async () => {\n      await page.goto(viteTestUrl + '/inline/unique.html?v=1')\n      expect(await countScriptTags()).toBe(1)\n      expect(await countPreloadTags()).toBeGreaterThan(0)\n    })\n\n    test('execution order when inlined', async () => {\n      await page.goto(viteTestUrl + '/inline/shared-1.html?v=1')\n      expect((await page.textContent('#output')).trim()).toBe(\n        'dep1 common dep2 dep3 shared',\n      )\n      await page.goto(viteTestUrl + '/inline/shared-2.html?v=1')\n      expect((await page.textContent('#output')).trim()).toBe(\n        'dep1 common dep2 dep3 shared',\n      )\n    })\n\n    test('execution order when not inlined', async () => {\n      await page.goto(viteTestUrl + '/inline/unique.html?v=1')\n      expect((await page.textContent('#output')).trim()).toBe(\n        'dep1 common dep2 unique',\n      )\n    })\n  })\n})\n\ndescribe('noHead', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/noHead.html')\n  })\n\n  test('noHead tags injection', async () => {\n    const el = await page.$('html meta[name=description]')\n    expect(await el.getAttribute('content')).toBe('a vite app')\n\n    const kw = await page.$('html meta[name=keywords]')\n    expect(await kw.getAttribute('content')).toBe('es modules')\n  })\n})\n\ndescribe('noBody', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/noBody.html')\n  })\n\n  test('noBody tags injection', async () => {\n    // this selects the first noscript in body, even without a body tag\n    const el = await page.$('body noscript')\n    expect(await el.innerHTML()).toMatch(`<!-- this is prepended to body -->`)\n\n    const kw = await page.$('html:last-child')\n    expect(await kw.innerHTML()).toMatch(`<!-- this is appended to body -->`)\n  })\n})\n\ndescribe('Unicode path', () => {\n  test('direct access', async () => {\n    await page.goto(\n      viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html',\n    )\n    expect(await page.textContent('h1')).toBe('Unicode path')\n  })\n\n  test('spa fallback', async () => {\n    await page.goto(viteTestUrl + '/unicode-path/中文-にほんご-한글-🌕🌖🌗/')\n    expect(await page.textContent('h1')).toBe('Unicode path')\n  })\n})\n\ndescribe('link with props', () => {\n  test('separate links with different media props', async () => {\n    await page.goto(viteTestUrl + '/link-props/index.html')\n    expect(await getColor('h1')).toBe('red')\n  })\n})\n\ndescribe.runIf(isServe)('SPA fallback', () => {\n  test('should serve index.html via page navigation even when path matches file basename', async () => {\n    const response = await page.goto(viteTestUrl + '/test')\n    expect(response.status()).toBe(200)\n    const content = await page.content()\n    expect(content).toContain('Transformed')\n    expect(content).not.toContain('This is test.js')\n  })\n})\n\ndescribe.runIf(isServe)('invalid', () => {\n  test('should be 500 with overlay', async () => {\n    const response = await page.goto(viteTestUrl + '/invalid.html')\n    expect(response.status()).toBe(500)\n\n    const errorOverlay = await page.waitForSelector('vite-error-overlay')\n    expect(errorOverlay).toBeTruthy()\n\n    const message = await errorOverlay.$$eval('.message-body', (m) => {\n      return m[0].innerHTML\n    })\n    expect(message).toContain('Unable to parse HTML')\n  })\n\n  test('should close overlay when clicked away', async () => {\n    await page.goto(viteTestUrl + '/invalidClick.html')\n    const errorOverlay = await page.waitForSelector('vite-error-overlay')\n    expect(errorOverlay).toBeTruthy()\n\n    await page.click('html')\n    const isVisibleOverlay = await errorOverlay.isVisible()\n    expect(isVisibleOverlay).toBeFalsy()\n  })\n\n  test('should close overlay when escape key is pressed', async () => {\n    await page.goto(viteTestUrl + '/invalidEscape.html')\n    const errorOverlay = await page.waitForSelector('vite-error-overlay')\n    expect(errorOverlay).toBeTruthy()\n\n    await page.keyboard.press('Escape')\n    const isVisibleOverlay = await errorOverlay.isVisible()\n    expect(isVisibleOverlay).toBeFalsy()\n  })\n\n  test('stack is updated', async () => {\n    await page.goto(viteTestUrl + '/invalid.html')\n\n    const errorOverlay = await page.waitForSelector('vite-error-overlay')\n    const hiddenPromise = errorOverlay.waitForElementState('hidden')\n    await page.keyboard.press('Escape')\n    await hiddenPromise\n\n    viteServer.environments.client.hot.send({\n      type: 'error',\n      err: {\n        message: 'someError',\n        stack: [\n          'Error: someError',\n          '    at someMethod (/some/file.ts:1:2)',\n        ].join('\\n'),\n      },\n    })\n    const newErrorOverlay = await page.waitForSelector('vite-error-overlay')\n    const stack = await newErrorOverlay.$$eval('.stack', (m) => m[0].innerHTML)\n    expect(stack).toMatch(/^Error: someError/)\n  })\n\n  test('should reload when fixed', async () => {\n    await untilBrowserLogAfter(\n      () => page.goto(viteTestUrl + '/invalid.html'),\n      /connected/, // wait for HMR connection\n    )\n    editFile('invalid.html', (content) => {\n      return content.replace('<div Bad', '<div> Good')\n    })\n    const content = await page.waitForSelector('text=Good HTML')\n    expect(content).toBeTruthy()\n  })\n})\n\ndescribe('Valid HTML', () => {\n  test('valid HTML is parsed', async () => {\n    await page.goto(viteTestUrl + '/valid.html')\n    expect(await page.textContent('#no-quotes-on-attr')).toBe(\n      'No quotes on Attr working',\n    )\n\n    expect(await getColor('#duplicated-attrs')).toBe('green')\n  })\n})\n\ndescribe('env', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/env.html')\n  })\n\n  test('env works', async () => {\n    expect(await page.textContent('.env')).toBe('bar')\n    expect(await page.textContent('.env-define')).toBe('5173')\n    expect(await page.textContent('.env-define-string')).toBe('string')\n    expect(await page.textContent('.env-define-object-string')).toBe(\n      '{ \"foo\": \"bar\" }',\n    )\n    expect(await page.textContent('.env-define-null-string')).toBe('null')\n    expect(await page.textContent('.env-bar')).toBeTruthy()\n    expect(await page.textContent('.env-prod')).toBe(isBuild + '')\n    expect(await page.textContent('.env-dev')).toBe(isServe + '')\n\n    const iconLink = await page.$('link[rel=icon]')\n    expect(await iconLink.getAttribute('href')).toBe(\n      `${isBuild ? './' : '/'}sprite.svg`,\n    )\n  })\n})\n\ndescribe('importmap', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/importmapOrder.html')\n  })\n\n  // Should put this test at the end to get all browser logs above\n  test('importmap should be prepended', async () => {\n    expect(browserLogs).not.toContain(\n      'An import map is added after module script load was triggered.',\n    )\n  })\n})\n\ndescribe('side-effects', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/side-effects/')\n  })\n\n  test('console.log is not tree-shaken', async () => {\n    expect(browserLogs).toContain('message from sideEffects script')\n  })\n})\n\ndescribe('special character', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/a á.html')\n  })\n\n  test('should fetch html proxy', async () => {\n    expect(browserLogs).toContain('special character')\n  })\n})\n\ndescribe('relative input', () => {\n  beforeAll(async () => {\n    await page.goto(viteTestUrl + '/relative-input.html')\n  })\n\n  test('passing relative path to rollupOptions.input works', async () => {\n    await expect.poll(() => page.textContent('.relative-input')).toBe('OK')\n  })\n})\n\ndescribe.runIf(isServe)('warmup', () => {\n  test('should warmup /warmup/warm.js', async () => {\n    // warmup transform files async during server startup, so the module check\n    // here might take a while to load\n    await expect\n      .poll(() =>\n        viteServer.environments.client.moduleGraph.getModuleByUrl(\n          '/warmup/warm.js',\n        ),\n      )\n      .toBeTruthy()\n  })\n})\n\ntest('html serve behavior', async () => {\n  const [\n    file,\n    fileSlash,\n    fileDotHtml,\n\n    folder,\n    folderSlash,\n    folderSlashIndexHtml,\n\n    both,\n    bothSlash,\n    bothDotHtml,\n    bothSlashIndexHtml,\n  ] = await Promise.all([\n    fetchHtml('/serve/file'), // -> serve/file.html\n    fetchHtml('/serve/file/'), // -> index.html (404 in mpa)\n    fetchHtml('/serve/file.html'), // -> serve/file.html\n\n    fetchHtml('/serve/folder'), // -> index.html (404 in mpa)\n    fetchHtml('/serve/folder/'), // -> serve/folder/index.html\n    fetchHtml('/serve/folder/index.html'), // -> serve/folder/index.html\n\n    fetchHtml('/serve/both'), // -> serve/both.html\n    fetchHtml('/serve/both/'), // -> serve/both/index.html\n    fetchHtml('/serve/both.html'), // -> serve/both.html\n    fetchHtml('/serve/both/index.html'), // -> serve/both/index.html\n  ])\n\n  expect(file.status).toBe(200)\n  expect(await file.text()).toContain('file.html')\n  expect(fileSlash.status).toBe(200)\n  expect(await fileSlash.text()).toContain('index.html (fallback)')\n  expect(fileDotHtml.status).toBe(200)\n  expect(await fileDotHtml.text()).toContain('file.html')\n\n  expect(folder.status).toBe(200)\n  expect(await folder.text()).toContain('index.html (fallback)')\n  expect(folderSlash.status).toBe(200)\n  expect(await folderSlash.text()).toContain('folder/index.html')\n  expect(folderSlashIndexHtml.status).toBe(200)\n  expect(await folderSlashIndexHtml.text()).toContain('folder/index.html')\n\n  expect(both.status).toBe(200)\n  expect(await both.text()).toContain('both.html')\n  expect(bothSlash.status).toBe(200)\n  expect(await bothSlash.text()).toContain('both/index.html')\n  expect(bothDotHtml.status).toBe(200)\n  expect(await bothDotHtml.text()).toContain('both.html')\n  expect(bothSlashIndexHtml.status).toBe(200)\n  expect(await bothSlashIndexHtml.text()).toContain('both/index.html')\n})\n\ntest('html fallback works non browser accept header', async () => {\n  expect((await fetch(viteTestUrl, { headers: { Accept: '' } })).status).toBe(\n    200,\n  )\n  // defaults to \"Accept: */*\"\n  expect((await fetch(viteTestUrl)).status).toBe(200)\n  // wait-on uses axios and axios sends this accept header\n  expect(\n    (\n      await fetch(viteTestUrl, {\n        headers: { Accept: 'application/json, text/plain, */*' },\n      })\n    ).status,\n  ).toBe(200)\n})\n\ntest('escape html attribute', async () => {\n  const el = await page.$('.unescape-div')\n  expect(el).toBeNull()\n})\n\ntest('invalidate inline proxy module on reload', async () => {\n  await page.goto(`${viteTestUrl}/transform-inline-js`)\n  expect(await page.textContent('.test')).toContain('ok')\n  await page.reload()\n  expect(await page.textContent('.test')).toContain('ok')\n  await page.reload()\n  expect(await page.textContent('.test')).toContain('ok')\n})\n\ntest.runIf(isServe)(\n  'malformed URLs in src attributes should show errors',\n  async () => {\n    serverLogs.length = 0\n    await page.goto(`${viteTestUrl}/malformed-url.html`)\n    expect(await page.textContent('.status')).toContain(\n      'Page loaded successfully',\n    )\n    expect(serverLogs).not.toEqual(\n      expect.arrayContaining([\n        expect.stringMatching('Internal server error: URI malformed'),\n      ]),\n    )\n  },\n)\n"
  },
  {
    "path": "playground/html/a á.html",
    "content": "<h1>Special Character</h1>\n\n<script type=\"module\">\n  console.log('special character')\n</script>\n"
  },
  {
    "path": "playground/html/common.css",
    "content": "p {\n  color: grey;\n}\n"
  },
  {
    "path": "playground/html/emptyAttr.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Empty Attr</title>\n  </head>\n  <body>\n    <img src=\"\" alt=\"\" />\n  </body>\n</html>\n"
  },
  {
    "path": "playground/html/env.html",
    "content": "<p class=\"env\">%VITE_FOO%</p>\n<p class=\"env-define\">%VITE_NUMBER%</p>\n<p class=\"env-define-string\">%VITE_STRING%</p>\n<p class=\"env-define-object-string\">%VITE_OBJECT_STRING%</p>\n<p class=\"env-define-null-string\">%VITE_NULL_STRING%</p>\n<p class=\"env-%VITE_FOO%\">class name should be env-bar</p>\n<p class=\"env-prod\">%PROD%</p>\n<p class=\"env-dev\">%DEV%</p>\n<link rel=\"icon\" href=\"%VITE_FAVICON_URL%\" />\n"
  },
  {
    "path": "playground/html/foo.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" href=\"/favicon.ico\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>About</title>\n  </head>\n  <body>\n    <h1>Foo.html</h1>\n    <script type=\"module\" src=\"/src/about.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/html/importmapOrder.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <script type=\"importmap\">\n      {\n        \"imports\": {\n          \"some-pkg\": \"url-of-pkg\"\n        }\n      }\n    </script>\n    <link rel=\"modulepreload\" href=\"url-of-pkg\" />\n    <script type=\"module\" src=\"/main.js\"></script>\n  </head>\n</html>\n"
  },
  {
    "path": "playground/html/index.html",
    "content": "<link rel=\"stylesheet\" href=\"/main.css\" />\n\n<!-- comment one -->\n<h1>Hello</h1>\n<!-- comment two -->\n<script type=\"module\"></script>\n<script type=\"module\" src=\"/main.js\"></script>\n<link rel=\"icon\" href=\"{{cdn_host}}/cdn/images/favicon.ico\" />\n<link rel=\"stylesheet\" href=\"{{cdn_host}}/css.css\" type=\"text/css\" />\n<script src=\"{{cdn_host}}/js.js\" vite-ignore></script>\n<p>index.html (fallback)</p>\n\n<div>External path: <span class=\"external-path\"></span></div>\n<script type=\"module\" src=\"/external-path.js\" vite-ignore></script>\n<script type=\"module\" vite-ignore></script>\n<link rel=\"stylesheet\" href=\"/external-path.css\" vite-ignore />\n<div>\n  External path by rollupOptions.external (build only):\n  <span class=\"external-path-by-rollup-options\"></span>\n</div>\n"
  },
  {
    "path": "playground/html/inline/common.js",
    "content": "import './dep1'\nimport './dep2'\n\nexport function log(name) {\n  document.getElementById('output').innerHTML += name + ' '\n}\n\nlog('common')\n"
  },
  {
    "path": "playground/html/inline/dep1.js",
    "content": "import { log } from './common'\n\nlog('dep1')\n"
  },
  {
    "path": "playground/html/inline/dep2.js",
    "content": "import { log } from './common'\n\nlog('dep2')\n"
  },
  {
    "path": "playground/html/inline/dep3.js",
    "content": "import './dep2'\nimport { log } from './common'\n\nlog('dep3')\n"
  },
  {
    "path": "playground/html/inline/module-graph.dot",
    "content": "digraph Module {\n    common -> { dep1, dep2 } [style=dashed,color=grey]\n    dep1 -> common\n    dep2 -> common\n    dep3 -> { dep2, common }\n\n    subgraph shared {\n        shared [style=filled]\n        shared -> { dep3, common }\n    }\n\n    subgraph unique {\n        unique [style=filled]\n        unique -> { common, dep2 }\n    }\n}\n"
  },
  {
    "path": "playground/html/inline/shared-1.html",
    "content": "<pre id=\"output\"></pre>\n<script type=\"module\" src=\"./shared.js\"></script>\n"
  },
  {
    "path": "playground/html/inline/shared-2.html",
    "content": "<pre id=\"output\"></pre>\n<script type=\"module\" src=\"./shared.js\"></script>\n"
  },
  {
    "path": "playground/html/inline/shared.js",
    "content": "import './dep3'\nimport { log } from './common'\n\nlog('shared')\n"
  },
  {
    "path": "playground/html/inline/shared_a.html",
    "content": "<p>inline a</p>\n"
  },
  {
    "path": "playground/html/inline/unique.html",
    "content": "<pre id=\"output\"></pre>\n<script type=\"module\" src=\"./unique.js\"></script>\n"
  },
  {
    "path": "playground/html/inline/unique.js",
    "content": "import { log } from './common'\nimport './dep2'\n\nlog('unique')\n"
  },
  {
    "path": "playground/html/invalid.html",
    "content": "<div Bad HTML</div>\n"
  },
  {
    "path": "playground/html/invalidClick.html",
    "content": "<div Bad CLICK HTML</div>\n"
  },
  {
    "path": "playground/html/invalidEscape.html",
    "content": "<div Bad ESCAPE HTML</div>\n"
  },
  {
    "path": "playground/html/link-props/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./screen.css\" media=\"screen\" />\n<link rel=\"stylesheet\" href=\"./print.css\" media=\"print\" />\n\n<h1 id=\"link-props\">test color</h1>\n"
  },
  {
    "path": "playground/html/link-props/print.css",
    "content": "#link-props {\n  color: green;\n}\n"
  },
  {
    "path": "playground/html/link-props/screen.css",
    "content": "#link-props {\n  color: red;\n}\n"
  },
  {
    "path": "playground/html/link.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Link to rollup config</title>\n  </head>\n  <body>\n    <a href=\"/link/target\">A Link to a Rollup Import</a>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/html/main.css",
    "content": "h1 {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/html/main.js",
    "content": "import { msg } from './shared'\nimport './common.css'\n\nconsole.log(msg + ' from main')\n"
  },
  {
    "path": "playground/html/malformed-url.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Malformed URL Test</title>\n  </head>\n  <body>\n    <h1>Malformed URL Test</h1>\n    <img\n      src=\"{% if product[0].image_urls[0] %}{{product[0].image_urls[0]}}{% endif %}\"\n      class=\"template-expression\"\n    />\n    <p class=\"status\">Page loaded successfully</p>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/html/nested/asset/main.js",
    "content": "function text(el, text) {\n  document.querySelector(el).textContent = text\n}\ntext('.relative-js', 'hello')\n"
  },
  {
    "path": "playground/html/nested/asset/style.css",
    "content": ".relative-css {\n  color: red;\n}\n"
  },
  {
    "path": "playground/html/nested/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./nested.css\" />\n<h1>Nested</h1>\n<script type=\"module\" src=\"./nested.js\"></script>\n\n<h1>no base path nested</h1>\n<link rel=\"stylesheet\" href=\"asset/style.css\" />\n<div class=\"relative-css\">link style</div>\n<div class=\"relative-js\"></div>\n<script src=\"asset/main.js\" type=\"module\"></script>\n"
  },
  {
    "path": "playground/html/nested/nested.css",
    "content": "h1 {\n  color: red;\n}\n"
  },
  {
    "path": "playground/html/nested/nested.js",
    "content": "import { msg } from '../shared'\nimport '../common.css'\n\nconsole.log(msg + ' from nested')\n"
  },
  {
    "path": "playground/html/noBody.html",
    "content": "<link rel=\"stylesheet\" href=\"/main.css\" />\n\n<!-- comment one -->\n<h1>Hello</h1>\n<!-- comment two -->\n\n<script type=\"module\" src=\"/main.js\"></script>\n"
  },
  {
    "path": "playground/html/noHead.html",
    "content": "<link rel=\"stylesheet\" href=\"/main.css\" />\n\n<!-- comment one -->\n<h1>Hello</h1>\n<!-- comment two -->\n\n<script type=\"module\" src=\"/main.js\"></script>\n"
  },
  {
    "path": "playground/html/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-html\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/html/relative-input/main.js",
    "content": "document.querySelector('.relative-input').textContent = 'OK'\n"
  },
  {
    "path": "playground/html/relative-input.html",
    "content": "<script type=\"module\" src=\"./relative-input/main.js\"></script>\n\n<p class=\"relative-input\"></p>\n"
  },
  {
    "path": "playground/html/scriptAsync.html",
    "content": "<link rel=\"stylesheet\" href=\"/main.css\" />\n\n<h1>scriptAsync.html</h1>\n\n<script async type=\"module\" src=\"/main.js\"></script>\n<script async type=\"module\" src=\"/nested/nested.js\"></script>\n"
  },
  {
    "path": "playground/html/scriptMixed.html",
    "content": "<link rel=\"stylesheet\" href=\"/main.css\" />\n\n<h1>scriptMixed.html</h1>\n\n<script async type=\"module\" src=\"/main.js\"></script>\n<script type=\"module\" src=\"/nested/nested.js\"></script>\n"
  },
  {
    "path": "playground/html/serve/both/index.html",
    "content": "<h1>both/index.html</h1>\n"
  },
  {
    "path": "playground/html/serve/both.html",
    "content": "<h1>both.html</h1>\n"
  },
  {
    "path": "playground/html/serve/file.html",
    "content": "<h1>file.html</h1>\n"
  },
  {
    "path": "playground/html/serve/folder/index.html",
    "content": "<h1>folder/index.html</h1>\n"
  },
  {
    "path": "playground/html/shared.js",
    "content": "export const msg = 'shared'\n"
  },
  {
    "path": "playground/html/side-effects/index.html",
    "content": "<h1>sideEffects false</h1>\n<script type=\"module\" src=\"./sideEffects.js\"></script>\n"
  },
  {
    "path": "playground/html/side-effects/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-html-side-effects\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"sideEffects\": false\n}\n"
  },
  {
    "path": "playground/html/side-effects/sideEffects.js",
    "content": "console.log('message from sideEffects script')\n"
  },
  {
    "path": "playground/html/test.js",
    "content": "// This file is used to test https://github.com/vitejs/vite/issues/20705\n// The dev server should NOT serve this file when navigating to /test\nexport const message =\n  'This is test.js - should not be served for /test navigation'\n"
  },
  {
    "path": "playground/html/transform-inline-js.html",
    "content": "<div>id: {{ id }}</div>\n<div class=\"test\">test: <span id=\"{{ id }}\">???</span></div>\n<script type=\"module\">\n  document.getElementById('{{ id }}').textContent = 'ok'\n</script>\n"
  },
  {
    "path": "playground/html/unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html",
    "content": "<h1>Unicode path</h1>\n"
  },
  {
    "path": "playground/html/valid.html",
    "content": "<!-- accepted HTML parsing errors, browsers accept these -->\n<div id=\"duplicated-attrs\" style=\"color: green;\" style=\"color: red;\">Accept duplicated attribute</div>\n\n<!-- accepted HTML constructs -->\n<datalist>\n  <option value=\"option-without-closing-tag\">    \n</datalist>\n\n<div id=\"no-quotes-on-attr\">No quotes on Attr</div>\n<script type=\"module\" src=/valid.js></script>\n\n<svg>\n  <!-- attr with prefix -->\n  <use xlink:href=\"/sprite.svg#svg\"></use>\n</svg>\n\n<!-- allow self closing on non-void elements -->\n<self-close-non-void />\n"
  },
  {
    "path": "playground/html/valid.js",
    "content": "document.getElementById(`no-quotes-on-attr`).innerHTML =\n  `No quotes on Attr working`\n"
  },
  {
    "path": "playground/html/vite.config.js",
    "content": "import { relative, resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst dirname = import.meta.dirname\n\nexport default defineConfig({\n  base: './',\n  build: {\n    rollupOptions: {\n      input: {\n        main: resolve(dirname, 'index.html'),\n        nested: resolve(dirname, 'nested/index.html'),\n        scriptAsync: resolve(dirname, 'scriptAsync.html'),\n        scriptMixed: resolve(dirname, 'scriptMixed.html'),\n        emptyAttr: resolve(dirname, 'emptyAttr.html'),\n        link: resolve(dirname, 'link.html'),\n        'link/target': resolve(dirname, 'index.html'),\n        zeroJS: resolve(dirname, 'zeroJS.html'),\n        noHead: resolve(dirname, 'noHead.html'),\n        noBody: resolve(dirname, 'noBody.html'),\n        inlinea: resolve(dirname, 'inline/shared_a.html'),\n        inline1: resolve(dirname, 'inline/shared-1.html'),\n        inline2: resolve(dirname, 'inline/shared-2.html'),\n        inline3: resolve(dirname, 'inline/unique.html'),\n        unicodePath: resolve(\n          dirname,\n          'unicode-path/中文-にほんご-한글-🌕🌖🌗/index.html',\n        ),\n        linkProps: resolve(dirname, 'link-props/index.html'),\n        valid: resolve(dirname, 'valid.html'),\n        importmapOrder: resolve(dirname, 'importmapOrder.html'),\n        env: resolve(dirname, 'env.html'),\n        sideEffects: resolve(dirname, 'side-effects/index.html'),\n        'a á': resolve(dirname, 'a á.html'),\n        serveFile: resolve(dirname, 'serve/file.html'),\n        serveFolder: resolve(dirname, 'serve/folder/index.html'),\n        serveBothFile: resolve(dirname, 'serve/both.html'),\n        serveBothFolder: resolve(dirname, 'serve/both/index.html'),\n        write: resolve(dirname, 'write.html'),\n        'transform-inline-js': resolve(dirname, 'transform-inline-js.html'),\n        relativeInput: relative(\n          process.cwd(),\n          resolve(dirname, 'relative-input.html'),\n        ),\n        malformedUrl: resolve(dirname, 'malformed-url.html'),\n      },\n      external: ['/external-path-by-rollup-options.js'],\n    },\n  },\n\n  server: {\n    warmup: {\n      clientFiles: ['./warmup/*'],\n    },\n  },\n\n  define: {\n    'import.meta.env.VITE_NUMBER': 5173,\n    'import.meta.env.VITE_STRING': JSON.stringify('string'),\n    'import.meta.env.VITE_OBJECT_STRING': '{ \"foo\": \"bar\" }',\n    'import.meta.env.VITE_NULL_STRING': 'null',\n  },\n\n  plugins: [\n    {\n      name: 'pre-transform',\n      transformIndexHtml: {\n        order: 'pre',\n        handler(html, { filename }) {\n          if (html.includes('/@vite/client')) {\n            throw new Error('pre transform applied at wrong time!')\n          }\n\n          const doctypeRE = /<!doctype html>/i\n          if (doctypeRE.test(html)) return\n\n          const head = `\n  <head lang=\"en\">\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>{{ title }}</title>\n  </head>`\n          return `<!DOCTYPE html>\n<html lang=\"en\">${filename.includes('noHead') ? '' : head}\n${\n  filename.includes('noBody')\n    ? html\n    : `<body>\n  ${html}\n</body>`\n}\n</html>\n  `\n        },\n      },\n    },\n    {\n      name: 'string-transform',\n      transformIndexHtml(html) {\n        return html.replace('Hello', 'Transformed')\n      },\n    },\n    {\n      name: 'tags-transform',\n      transformIndexHtml() {\n        return [\n          {\n            tag: 'meta',\n            attrs: { name: 'description', content: 'a vite app' },\n            // default injection is head-prepend\n          },\n          {\n            tag: 'meta',\n            attrs: { name: 'keywords', content: 'es modules' },\n            injectTo: 'head',\n          },\n        ]\n      },\n    },\n    {\n      name: 'combined-transform',\n      transformIndexHtml(html) {\n        return {\n          html: html.replace('{{ title }}', 'Test HTML transforms'),\n          tags: [\n            {\n              tag: 'p',\n              attrs: { class: 'inject' },\n              children: 'This is injected',\n              injectTo: 'body',\n            },\n          ],\n        }\n      },\n    },\n    {\n      name: 'serve-only-transform',\n      transformIndexHtml(_, ctx) {\n        if (ctx.server) {\n          return [\n            {\n              tag: 'p',\n              attrs: { class: 'server' },\n              children: 'This is injected only during dev',\n              injectTo: 'body',\n            },\n          ]\n        }\n      },\n    },\n    {\n      name: 'build-only-transform',\n      transformIndexHtml(_, ctx) {\n        if (ctx.bundle) {\n          return [\n            {\n              tag: 'p',\n              attrs: { class: 'build' },\n              children: 'This is injected only during build',\n              injectTo: 'body',\n            },\n          ]\n        }\n      },\n    },\n    {\n      name: 'path-conditional-transform',\n      transformIndexHtml(_, ctx) {\n        if (ctx.path.includes('nested')) {\n          return [\n            {\n              tag: 'p',\n              attrs: { class: 'conditional' },\n              children: 'This is injected only for /nested/index.html',\n              injectTo: 'body',\n            },\n          ]\n        }\n      },\n    },\n    {\n      name: 'body-prepend-transform',\n      transformIndexHtml() {\n        return [\n          {\n            tag: 'noscript',\n            children: '<!-- this is appended to body -->',\n            injectTo: 'body',\n          },\n          {\n            tag: 'noscript',\n            children: '<!-- this is prepended to body -->',\n            injectTo: 'body-prepend',\n          },\n        ]\n      },\n    },\n    {\n      name: 'head-prepend-importmap',\n      transformIndexHtml(_, ctx) {\n        if (ctx.path.includes('importmapOrder')) return\n\n        return [\n          {\n            tag: 'script',\n            attrs: { type: 'importmap' },\n            children: `\n              {\n                \"imports\": {\n                  \"vue\": \"https://unpkg.com/vue@3.4.38/dist/vue.runtime.esm-browser.js\"\n                }\n              }\n            `,\n            injectTo: 'head',\n          },\n        ]\n      },\n    },\n    {\n      name: 'escape-html-attribute',\n      transformIndexHtml: {\n        order: 'post',\n        handler() {\n          return [\n            {\n              tag: 'link',\n              attrs: {\n                href: `\"><div class=unescape-div>extra content</div>`,\n              },\n              injectTo: 'body',\n            },\n          ]\n        },\n      },\n    },\n    {\n      name: 'append-external-path-by-rollup-options',\n      apply: 'build', // this does not work in serve\n      transformIndexHtml: {\n        order: 'pre',\n        handler(_, ctx) {\n          if (!ctx.filename.endsWith('html/index.html')) return\n          return [\n            {\n              tag: 'script',\n              attrs: {\n                type: 'module',\n                src: '/external-path-by-rollup-options.js',\n              },\n              injectTo: 'body',\n            },\n          ]\n        },\n      },\n    },\n    {\n      name: 'transform-inline-js',\n      transformIndexHtml: {\n        order: 'pre',\n        handler(html, ctx) {\n          if (!ctx.filename.endsWith('html/transform-inline-js.html')) return\n          return html.replaceAll(\n            '{{ id }}',\n            Math.random().toString(36).slice(2),\n          )\n        },\n      },\n    },\n    serveExternalPathPlugin(),\n  ],\n})\n\n/** @returns {import('vite').Plugin} */\nfunction serveExternalPathPlugin() {\n  const handler = (req, res, next) => {\n    if (req.url === '/external-path.js') {\n      res.setHeader('Content-Type', 'application/javascript')\n      res.end('document.querySelector(\".external-path\").textContent = \"works\"')\n    } else if (req.url === '/external-path.css') {\n      res.setHeader('Content-Type', 'text/css')\n      res.end('.external-path{color:red}')\n    } else if (req.url === '/external-path-by-rollup-options.js') {\n      res.setHeader('Content-Type', 'application/javascript')\n      res.end(\n        'document.querySelector(\".external-path-by-rollup-options\").textContent = \"works\"',\n      )\n    } else {\n      next()\n    }\n  }\n  return {\n    name: 'serve-external-path',\n    configureServer(server) {\n      server.middlewares.use(handler)\n    },\n    configurePreviewServer(server) {\n      server.middlewares.use(handler)\n    },\n  }\n}\n"
  },
  {
    "path": "playground/html/warmup/warm.js",
    "content": "console.log('From warm.js')\n"
  },
  {
    "path": "playground/html/write.html",
    "content": "<!-- prettier-ignore -->\n<html><head><style>div {}\n</style></head><body><script type=\"module\" src=\"./shared.js\"></script></body></html>\n"
  },
  {
    "path": "playground/html/zeroJS.html",
    "content": "<link rel=\"stylesheet\" href=\"/main.css\" />\n\n<h1>zeroJS.html</h1>\n\n<style>\n  body {\n    background-color: linen;\n  }\n</style>\n"
  },
  {
    "path": "playground/import-assertion/__tests__/import-assertion.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from '~utils'\n\ntest('from source code', async () => {\n  expect(await page.textContent('.src'), 'bar')\n})\n\ntest('from dependency', async () => {\n  expect(await page.textContent('.dep'), 'world')\n})\n"
  },
  {
    "path": "playground/import-assertion/data.json",
    "content": "{\n  \"foo\": \"bar\"\n}\n"
  },
  {
    "path": "playground/import-assertion/import-assertion-dep/data.json",
    "content": "{\n  \"hello\": \"world\"\n}\n"
  },
  {
    "path": "playground/import-assertion/import-assertion-dep/index.js",
    "content": "import json from './data.json' assert { type: 'json' }\n\nexport const hello = json.hello\n"
  },
  {
    "path": "playground/import-assertion/import-assertion-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-import-assertion-dep\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"exports\": \"./index.js\"\n}\n"
  },
  {
    "path": "playground/import-assertion/index.html",
    "content": "<h1>Import assertion</h1>\n\n<h2>From source code</h2>\n<p class=\"src\"></p>\n\n<h2>From dependency</h2>\n<p class=\"dep\"></p>\n\n<script type=\"module\">\n  import * as data from './data.json' assert { type: 'json' }\n  text('.src', data.foo)\n\n  import * as depData from '@vitejs/test-import-assertion-dep'\n  text('.dep', depData.hello)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/import-assertion/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-import-assertion\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-import-assertion-dep\": \"file:./import-assertion-dep\"\n  }\n}\n"
  },
  {
    "path": "playground/js-sourcemap/__tests__/js-sourcemap.spec.ts",
    "content": "import { URL, fileURLToPath } from 'node:url'\nimport { promisify } from 'node:util'\nimport { execFile } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { describe, expect, test } from 'vitest'\nimport { mapFileCommentRegex } from 'convert-source-map'\nimport { commentSourceMap } from '../foo-with-sourcemap-plugin'\nimport {\n  extractSourcemap,\n  findAssetFile,\n  formatSourcemapForSnapshot,\n  isBuild,\n  listAssets,\n  page,\n  readFile,\n  serverLogs,\n} from '~utils'\n\nif (!isBuild) {\n  test('js', async () => {\n    const res = await page.request.get(new URL('./foo.js', page.url()).href)\n    const js = await res.text()\n    const map = extractSourcemap(js)\n    expect(formatSourcemapForSnapshot(map, js)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG;\",\n          \"sources\": [\n            \"foo.js\",\n          ],\n          \"sourcesContent\": [\n            \"export const foo = 'foo'\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MjUAZXhwb3J0IGNvbnN0IGZvbyA9ICdmb28nCjE1MQB7InZlcnNpb24iOjMsInNvdXJjZXMiOlsiZm9vLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBmb28gPSAnZm9vJ1xuIl0sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHOyJ9\"\n      }\n    `)\n  })\n\n  test('plugin return sourcemap with `sources: [\"\"]`', async () => {\n    const res = await page.request.get(new URL('./zoo.js', page.url()).href)\n    const js = await res.text()\n    expect(js).toContain('// add comment')\n\n    const map = extractSourcemap(js)\n    expect(formatSourcemapForSnapshot(map, js)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;\",\n          \"sources\": [\n            \"zoo.js\",\n          ],\n          \"sourcesContent\": [\n            \"export const zoo = 'zoo'\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NDAAZXhwb3J0IGNvbnN0IHpvbyA9ICd6b28nCi8vIGFkZCBjb21tZW50CjIxNgB7InZlcnNpb24iOjMsInNvdXJjZXMiOlsiem9vLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCB6b28gPSAnem9vJ1xuIl0sIm1hcHBpbmdzIjoiQUFBQSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7In0=\"\n      }\n    `)\n  })\n\n  test('js with inline sourcemap injected by a plugin', async () => {\n    const res = await page.request.get(\n      new URL('./foo-with-sourcemap.js', page.url()).href,\n    )\n    const js = await res.text()\n\n    expect(js).toContain(commentSourceMap)\n    const sourcemapComments = js.match(mapFileCommentRegex).length\n    expect(sourcemapComments).toBe(1)\n\n    const map = extractSourcemap(js)\n    expect(formatSourcemapForSnapshot(map, js)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG\",\n          \"sources\": [\n            \"\",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#NzMAZXhwb3J0IGNvbnN0IGZvbyA9ICdmb28nCi8vIGRlZmF1bHQgYm91bmRhcnkgc291cmNlbWFwIHdpdGggbWFnaWMtc3RyaW5nCjk2AHsidmVyc2lvbiI6Mywic291cmNlcyI6WyIiXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcifQ==\"\n      }\n    `)\n  })\n\n  test('ts', async () => {\n    const res = await page.request.get(new URL('./bar.ts', page.url()).href)\n    const js = await res.text()\n    const map = extractSourcemap(js)\n    expect(formatSourcemapForSnapshot(map, js)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \"AAAA,OAAO,MAAM,MAAM\",\n          \"sources\": [\n            \"bar.ts\",\n          ],\n          \"sourcesContent\": [\n            \"export const bar = 'bar'\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MjYAZXhwb3J0IGNvbnN0IGJhciA9ICJiYXIiOwoxMTUAeyJtYXBwaW5ncyI6IkFBQUEsT0FBTyxNQUFNLE1BQU0iLCJzb3VyY2VzIjpbImJhci50cyJdLCJ2ZXJzaW9uIjozLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY29uc3QgYmFyID0gJ2JhcidcbiJdfQ==\"\n      }\n    `)\n  })\n\n  test('multiline import', async () => {\n    const res = await page.request.get(\n      new URL('./with-multiline-import.ts', page.url()).href,\n    )\n    const js = await res.text()\n    const map = extractSourcemap(js)\n    expect(formatSourcemapForSnapshot(map, js)).toMatchInlineSnapshot(`\n      SourceMap {\n        content: {\n          \"mappings\": \";AACA,SACE,WACK;AAEP,QAAQ,IAAI,yBAAyB,IAAI\",\n          \"sources\": [\n            \"with-multiline-import.ts\",\n          ],\n          \"sourcesContent\": [\n            \"// prettier-ignore\n      import {\n        foo\n      } from '@vitejs/test-importee-pkg'\n\n      console.log('with-multiline-import', foo)\n      \",\n          ],\n          \"version\": 3,\n        },\n        visualization: \"https://evanw.github.io/source-map-visualization/#MjQ4AC8vIHByZXR0aWVyLWlnbm9yZQppbXBvcnQgX192aXRlX19janNJbXBvcnQwX192aXRlanNfdGVzdEltcG9ydGVlUGtnIGZyb20gIi9ub2RlX21vZHVsZXMvLnZpdGUvZGVwcy9Adml0ZWpzX3Rlc3QtaW1wb3J0ZWUtcGtnLmpzP3Y9MDAwMDAwMDAiOyBjb25zdCBmb28gPSBfX3ZpdGVfX2Nqc0ltcG9ydDBfX3ZpdGVqc190ZXN0SW1wb3J0ZWVQa2dbImZvbyJdOwpjb25zb2xlLmxvZygid2l0aC1tdWx0aWxpbmUtaW1wb3J0IiwgZm9vKTsKMjQ4AHsibWFwcGluZ3MiOiI7QUFDQSxTQUNFLFdBQ0s7QUFFUCxRQUFRLElBQUkseUJBQXlCLElBQUkiLCJzb3VyY2VzIjpbIndpdGgtbXVsdGlsaW5lLWltcG9ydC50cyJdLCJ2ZXJzaW9uIjozLCJzb3VyY2VzQ29udGVudCI6WyIvLyBwcmV0dGllci1pZ25vcmVcbmltcG9ydCB7XG4gIGZvb1xufSBmcm9tICdAdml0ZWpzL3Rlc3QtaW1wb3J0ZWUtcGtnJ1xuXG5jb25zb2xlLmxvZygnd2l0aC1tdWx0aWxpbmUtaW1wb3J0JywgZm9vKVxuIl19\"\n      }\n    `)\n  })\n\n  test('should not output missing source file warning', () => {\n    serverLogs.forEach((log) => {\n      expect(log).not.toMatch(/Sourcemap for .+ points to missing source files/)\n    })\n  })\n}\n\ndescribe.runIf(isBuild)('build tests', () => {\n  test('should not output sourcemap warning (#4939)', () => {\n    serverLogs.forEach((log) => {\n      expect(log).not.toMatch('Sourcemap is likely to be incorrect')\n    })\n  })\n\n  test('sourcemap is correct when preload information is injected', async () => {\n    const js = findAssetFile(/after-preload-dynamic-[-\\w]{8}\\.js$/)\n    const map = findAssetFile(/after-preload-dynamic-[-\\w]{8}\\.js\\.map/)\n    expect(formatSourcemapForSnapshot(JSON.parse(map), js))\n      .toMatchInlineSnapshot(`\n        SourceMap {\n          content: {\n            \"debugId\": \"00000000-0000-0000-0000-000000000000\",\n            \"ignoreList\": [],\n            \"mappings\": \";gqCAAA,OAAO,qDAEP,QAAQ,IAAI,wBAAwB\",\n            \"sources\": [\n              \"../../after-preload-dynamic.js\",\n            ],\n            \"sourcesContent\": [\n              \"import('./dynamic/dynamic-foo')\n\n        console.log('after preload dynamic')\n        \",\n            ],\n            \"version\": 3,\n          },\n          visualization: \"https://evanw.github.io/source-map-visualization/#MTU0OQBjb25zdCBfX3ZpdGVfX21hcERlcHM9KGksbT1fX3ZpdGVfX21hcERlcHMsZD0obS5mfHwobS5mPVsiYXNzZXRzL2R5bmFtaWMtZm9vLUI0SmtWTWJvLmpzIiwiYXNzZXRzL2R5bmFtaWMtZm9vLURzcUtSckV5LmNzcyJdKSkpPT5pLm1hcChpPT5kW2ldKTsKdmFyIGU9YG1vZHVsZXByZWxvYWRgLHQ9ZnVuY3Rpb24oZSl7cmV0dXJuYC9gK2V9LG49e30scj1mdW5jdGlvbihyLGksYSl7bGV0IG89UHJvbWlzZS5yZXNvbHZlKCk7aWYoaSYmaS5sZW5ndGg+MCl7bGV0IHI9ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoYGxpbmtgKSxzPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYG1ldGFbcHJvcGVydHk9Y3NwLW5vbmNlXWApLGM9cz8ubm9uY2V8fHM/LmdldEF0dHJpYnV0ZShgbm9uY2VgKTtmdW5jdGlvbiBsKGUpe3JldHVybiBQcm9taXNlLmFsbChlLm1hcChlPT5Qcm9taXNlLnJlc29sdmUoZSkudGhlbihlPT4oe3N0YXR1czpgZnVsZmlsbGVkYCx2YWx1ZTplfSksZT0+KHtzdGF0dXM6YHJlamVjdGVkYCxyZWFzb246ZX0pKSkpfW89bChpLm1hcChpPT57aWYoaT10KGksYSksaSBpbiBuKXJldHVybjtuW2ldPSEwO2xldCBvPWkuZW5kc1dpdGgoYC5jc3NgKSxzPW8/YFtyZWw9InN0eWxlc2hlZXQiXWA6YGA7aWYoYSlmb3IobGV0IGU9ci5sZW5ndGgtMTtlPj0wO2UtLSl7bGV0IHQ9cltlXTtpZih0LmhyZWY9PT1pJiYoIW98fHQucmVsPT09YHN0eWxlc2hlZXRgKSlyZXR1cm59ZWxzZSBpZihkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGBsaW5rW2hyZWY9IiR7aX0iXSR7c31gKSlyZXR1cm47bGV0IGw9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChgbGlua2ApO2lmKGwucmVsPW8/YHN0eWxlc2hlZXRgOmUsb3x8KGwuYXM9YHNjcmlwdGApLGwuY3Jvc3NPcmlnaW49YGAsbC5ocmVmPWksYyYmbC5zZXRBdHRyaWJ1dGUoYG5vbmNlYCxjKSxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKGwpLG8pcmV0dXJuIG5ldyBQcm9taXNlKChlLHQpPT57bC5hZGRFdmVudExpc3RlbmVyKGBsb2FkYCxlKSxsLmFkZEV2ZW50TGlzdGVuZXIoYGVycm9yYCwoKT0+dChFcnJvcihgVW5hYmxlIHRvIHByZWxvYWQgQ1NTIGZvciAke2l9YCkpKX0pfSkpfWZ1bmN0aW9uIHMoZSl7bGV0IHQ9bmV3IEV2ZW50KGB2aXRlOnByZWxvYWRFcnJvcmAse2NhbmNlbGFibGU6ITB9KTtpZih0LnBheWxvYWQ9ZSx3aW5kb3cuZGlzcGF0Y2hFdmVudCh0KSwhdC5kZWZhdWx0UHJldmVudGVkKXRocm93IGV9cmV0dXJuIG8udGhlbihlPT57Zm9yKGxldCB0IG9mIGV8fFtdKXQuc3RhdHVzPT09YHJlamVjdGVkYCYmcyh0LnJlYXNvbik7cmV0dXJuIHIoKS5jYXRjaChzKX0pfTtyKCgpPT5pbXBvcnQoYC4vZHluYW1pYy1mb28tQjRKa1ZNYm8uanNgKSxfX3ZpdGVfX21hcERlcHMoWzAsMV0pKSxjb25zb2xlLmxvZyhgYWZ0ZXIgcHJlbG9hZCBkeW5hbWljYCk7ZXhwb3J0e3IgYXMgdH07Ci8vIyBkZWJ1Z0lkPWYxYjI2YTNiLTc0YzQtNDUwMC04ZjI1LWIyODY2OTk1MmQ0YgovLyMgc291cmNlTWFwcGluZ1VSTD1hZnRlci1wcmVsb2FkLWR5bmFtaWMtRHhzbW83ZE0uanMubWFwMjY3AHsidmVyc2lvbiI6MywibWFwcGluZ3MiOiI7Z3FDQUFBLE9BQU8scURBRVAsUUFBUSxJQUFJLHdCQUF3QiIsImlnbm9yZUxpc3QiOltdLCJzb3VyY2VzIjpbIi4uLy4uL2FmdGVyLXByZWxvYWQtZHluYW1pYy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQoJy4vZHluYW1pYy9keW5hbWljLWZvbycpXG5cbmNvbnNvbGUubG9nKCdhZnRlciBwcmVsb2FkIGR5bmFtaWMnKVxuIl0sImRlYnVnSWQiOiIwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDAifQ==\"\n        }\n      `)\n    // verify sourcemap comment is preserved at the last line\n    expect(js).toMatch(\n      /\\n\\/\\/# sourceMappingURL=after-preload-dynamic-[-\\w]{8}\\.js\\.map\\n?$/,\n    )\n  })\n\n  test('sourcemap file field is consistent (#20853)', async () => {\n    const assets = listAssets()\n    const mapAssets = assets.filter((asset) => asset.endsWith('.js.map'))\n\n    for (const mapAsset of mapAssets) {\n      const mapContent = readFile(`dist/assets/${mapAsset}`)\n      const mapObj = JSON.parse(mapContent)\n\n      if (mapObj.file) {\n        expect(\n          mapObj.file,\n          `Sourcemap file field for ${mapAsset} should be just the filename`,\n        ).toMatch(/^[^/]+\\.js$/)\n      }\n    }\n  })\n\n  test('__vite__mapDeps injected after banner', async () => {\n    const js = findAssetFile(/after-preload-dynamic-hashbang-[-\\w]{8}\\.js$/)\n    expect(js.split('\\n').slice(0, 2)).toEqual([\n      '#!/usr/bin/env node',\n      expect.stringContaining('const __vite__mapDeps=(i'),\n    ])\n  })\n\n  test('no unused __vite__mapDeps', async () => {\n    const js = findAssetFile(/after-preload-dynamic-no-dep-[-\\w]{8}\\.js$/)\n    expect(js).not.toMatch(/__vite__mapDeps/)\n  })\n\n  test('sourcemap is correct when using object as \"define\" value', async () => {\n    const js = findAssetFile(/with-define-object.*\\.js$/)\n    const map = findAssetFile(/with-define-object.*\\.js\\.map/)\n    expect(formatSourcemapForSnapshot(JSON.parse(map), js))\n      .toMatchInlineSnapshot(`\n        SourceMap {\n          content: {\n            \"debugId\": \"00000000-0000-0000-0000-000000000000\",\n            \"mappings\": \"AAEA,SAAS,GAAO,CACd,GAAW,CAGb,SAAS,GAAY,CAEnB,QAAQ,MAAM,qBAAA,CAAA,MAAA,OAAA,CAAyC,CAGzD,GAAM\",\n            \"sources\": [\n              \"../../with-define-object.ts\",\n            ],\n            \"sourcesContent\": [\n              \"// test complicated stack since broken sourcemap\n        // might still look correct with a simple case\n        function main() {\n          mainInner()\n        }\n\n        function mainInner() {\n          // @ts-expect-error \"define\"\n          console.trace('with-define-object', __testDefineObject)\n        }\n\n        main()\n        \",\n            ],\n            \"version\": 3,\n          },\n          visualization: \"https://evanw.github.io/source-map-visualization/#MTkwAGZ1bmN0aW9uIGUoKXt0KCl9ZnVuY3Rpb24gdCgpe2NvbnNvbGUudHJhY2UoYHdpdGgtZGVmaW5lLW9iamVjdGAse2hlbGxvOmB0ZXN0YH0pfWUoKTsKLy8jIGRlYnVnSWQ9ZmVmMjQxOWEtZmZmOC00MzMwLTgzZTktMWRkNTVlYmNmOTBkCi8vIyBzb3VyY2VNYXBwaW5nVVJMPXdpdGgtZGVmaW5lLW9iamVjdC1ELThrR2FfXy5qcy5tYXA1MDAAeyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3dpdGgtZGVmaW5lLW9iamVjdC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0ZXN0IGNvbXBsaWNhdGVkIHN0YWNrIHNpbmNlIGJyb2tlbiBzb3VyY2VtYXBcbi8vIG1pZ2h0IHN0aWxsIGxvb2sgY29ycmVjdCB3aXRoIGEgc2ltcGxlIGNhc2VcbmZ1bmN0aW9uIG1haW4oKSB7XG4gIG1haW5Jbm5lcigpXG59XG5cbmZ1bmN0aW9uIG1haW5Jbm5lcigpIHtcbiAgLy8gQHRzLWV4cGVjdC1lcnJvciBcImRlZmluZVwiXG4gIGNvbnNvbGUudHJhY2UoJ3dpdGgtZGVmaW5lLW9iamVjdCcsIF9fdGVzdERlZmluZU9iamVjdClcbn1cblxubWFpbigpXG4iXSwibWFwcGluZ3MiOiJBQUVBLFNBQVMsR0FBTyxDQUNkLEdBQVcsQ0FHYixTQUFTLEdBQVksQ0FFbkIsUUFBUSxNQUFNLHFCQUFBLENBQUEsTUFBQSxPQUFBLENBQXlDLENBR3pELEdBQU0iLCJkZWJ1Z0lkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIn0=\"\n        }\n      `)\n  })\n\n  test('correct sourcemap during ssr dev when using object as \"define\" value', async () => {\n    const execFileAsync = promisify(execFile)\n    await execFileAsync('node', ['test-ssr-dev.js'], {\n      cwd: fileURLToPath(new URL('..', import.meta.url)),\n    })\n  })\n\n  test('source and sourcemap contain matching debug IDs', () => {\n    function getDebugIdFromString(input: string): string | undefined {\n      const match = input.match(/\\/\\/# debugId=([a-fA-F0-9-]+)/)\n      return match ? match[1] : undefined\n    }\n\n    const assets = listAssets().map((asset) => `dist/assets/${asset}`)\n    const jsAssets = assets.filter((asset) => asset.endsWith('.js'))\n\n    for (const jsAsset of jsAssets) {\n      const jsContent = readFile(jsAsset)\n      const hasSourcemap = existsSync(`${jsAsset}.map`)\n      if (!hasSourcemap) continue\n\n      const sourceDebugId = getDebugIdFromString(jsContent)\n      expect(\n        sourceDebugId,\n        `Asset '${jsAsset}' did not contain a debug ID`,\n      ).toBeDefined()\n\n      const mapFile = jsAsset + '.map'\n      const mapContent = readFile(mapFile)\n\n      const mapObj = JSON.parse(mapContent)\n      const mapDebugId = mapObj.debugId\n\n      expect(\n        sourceDebugId,\n        'Debug ID in source didnt match debug ID in sourcemap',\n      ).toEqual(mapDebugId)\n    }\n  })\n})\n"
  },
  {
    "path": "playground/js-sourcemap/after-preload-dynamic-hashbang.js",
    "content": "// hashbang is injected via rollupOptions.output.banner\n\nimport('./dynamic/dynamic-foo')\n\nconsole.log('after preload dynamic hashbang')\n"
  },
  {
    "path": "playground/js-sourcemap/after-preload-dynamic-no-dep.js",
    "content": "import('./dynamic/dynamic-no-dep')\n\nconsole.log('after preload dynamic no dep')\n"
  },
  {
    "path": "playground/js-sourcemap/after-preload-dynamic.js",
    "content": "import('./dynamic/dynamic-foo')\n\nconsole.log('after preload dynamic')\n"
  },
  {
    "path": "playground/js-sourcemap/bar.ts",
    "content": "export const bar = 'bar'\n"
  },
  {
    "path": "playground/js-sourcemap/dynamic/dynamic-foo.css",
    "content": ".dynamic-foo {\n  color: red;\n}\n"
  },
  {
    "path": "playground/js-sourcemap/dynamic/dynamic-foo.js",
    "content": "import './dynamic-foo.css'\n\nconsole.log('dynamic/dynamic-foo')\n"
  },
  {
    "path": "playground/js-sourcemap/dynamic/dynamic-no-dep.js",
    "content": "console.log('dynamic/dynamic-no-dep')\n"
  },
  {
    "path": "playground/js-sourcemap/foo-with-sourcemap-plugin.ts",
    "content": "import type { Plugin } from 'vite'\n\nexport const commentSourceMap = [\n  '// default boundary sourcemap with magic-string',\n  '//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHIn0=',\n].join('\\n')\n\nexport default function transformFooWithInlineSourceMap(): Plugin {\n  return {\n    name: 'transform-foo-with-inline-sourcemap',\n    transform(code, id) {\n      if (id.includes('foo-with-sourcemap.js')) {\n        return `${code}${commentSourceMap}`\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "playground/js-sourcemap/foo-with-sourcemap.js",
    "content": "export const foo = 'foo'\n"
  },
  {
    "path": "playground/js-sourcemap/foo.js",
    "content": "export const foo = 'foo'\n"
  },
  {
    "path": "playground/js-sourcemap/importee-pkg/index.js",
    "content": "// eslint-disable-next-line import-x/no-commonjs\nexports.foo = 'foo'\n"
  },
  {
    "path": "playground/js-sourcemap/importee-pkg/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-importee-pkg\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"./index.js\"\n}\n"
  },
  {
    "path": "playground/js-sourcemap/index.html",
    "content": "<div class=\"wrapper\">\n  <h1>JS Sourcemap</h1>\n  <div class=\"dynamic-foo\">dynamic</div>\n</div>\n\n<script type=\"module\" src=\"./foo.js\"></script>\n<script type=\"module\" src=\"./bar.ts\"></script>\n<script type=\"module\" src=\"./after-preload-dynamic.js\"></script>\n<script type=\"module\" src=\"./after-preload-dynamic-hashbang.js\"></script>\n<script type=\"module\" src=\"./after-preload-dynamic-no-dep.js\"></script>\n<script type=\"module\" src=\"./with-multiline-import.ts\"></script>\n<script type=\"module\" src=\"./zoo.js\"></script>\n<script type=\"module\" src=\"./with-define-object.ts\"></script>\n"
  },
  {
    "path": "playground/js-sourcemap/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-js-sourcemap\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-importee-pkg\": \"file:importee-pkg\",\n    \"magic-string\": \"^0.30.21\"\n  }\n}\n"
  },
  {
    "path": "playground/js-sourcemap/plugin-foo.js",
    "content": "export const foo = 'foo'\n"
  },
  {
    "path": "playground/js-sourcemap/test-ssr-dev.js",
    "content": "import assert from 'node:assert'\nimport { fileURLToPath } from 'node:url'\nimport { createServer } from 'vite'\n\nasync function runTest() {\n  const server = await createServer({\n    root: fileURLToPath(new URL('.', import.meta.url)),\n    configFile: false,\n    optimizeDeps: {\n      noDiscovery: true,\n    },\n    server: {\n      middlewareMode: true,\n      hmr: false,\n      ws: false,\n    },\n    define: {\n      __testDefineObject: '{ \"hello\": \"test\" }',\n    },\n  })\n  const mod = await server.ssrLoadModule('/with-define-object-ssr.ts')\n  const error = await getError(() => mod.error())\n  server.ssrFixStacktrace(error)\n  assert.match(error.stack, /at errorInner (.*with-define-object-ssr.ts:7:9)/)\n  await server.close()\n}\n\nasync function getError(f) {\n  let error\n  try {\n    await f()\n  } catch (e) {\n    error = e\n  }\n  assert.ok(error)\n  return error\n}\n\nrunTest()\n"
  },
  {
    "path": "playground/js-sourcemap/vite.config.js",
    "content": "import { defineConfig } from 'vite'\nimport transformFooWithInlineSourceMap from './foo-with-sourcemap-plugin'\nimport { transformZooWithSourcemapPlugin } from './zoo-with-sourcemap-plugin'\n\nexport default defineConfig({\n  plugins: [\n    transformFooWithInlineSourceMap(),\n    transformZooWithSourcemapPlugin(),\n  ],\n  build: {\n    sourcemap: true,\n    rollupOptions: {\n      output: {\n        // manualChunks(name) {\n        //   if (name.endsWith('after-preload-dynamic.js')) {\n        //     return 'after-preload-dynamic'\n        //   }\n        //   if (name.endsWith('after-preload-dynamic-hashbang.js')) {\n        //     return 'after-preload-dynamic-hashbang'\n        //   }\n        //   if (name.endsWith('after-preload-dynamic-no-dep.js')) {\n        //     return 'after-preload-dynamic-no-dep'\n        //   }\n        //   if (name.includes('with-define-object')) {\n        //     return 'with-define-object'\n        //   }\n        // },\n        codeSplitting: {\n          groups: [\n            { name: 'after-preload-dynamic', test: 'after-preload-dynamic.js' },\n            {\n              name: 'after-preload-dynamic-hashbang',\n              test: 'after-preload-dynamic-hashbang.js',\n            },\n            {\n              name: 'after-preload-dynamic-no-dep',\n              test: 'after-preload-dynamic-no-dep.js',\n            },\n            { name: 'with-define-object', test: 'with-define-object' },\n          ],\n        },\n        banner(chunk) {\n          if (chunk.name.endsWith('after-preload-dynamic-hashbang')) {\n            return '#!/usr/bin/env node'\n          }\n        },\n        sourcemapDebugIds: true,\n      },\n    },\n  },\n  define: {\n    __testDefineObject: '{ \"hello\": \"test\" }',\n  },\n})\n"
  },
  {
    "path": "playground/js-sourcemap/with-define-object-ssr.ts",
    "content": "export function error() {\n  errorInner()\n}\n\nfunction errorInner() {\n  // @ts-expect-error \"define\"\n  throw new Error('with-define-object: ' + JSON.stringify(__testDefineObject))\n}\n"
  },
  {
    "path": "playground/js-sourcemap/with-define-object.ts",
    "content": "// test complicated stack since broken sourcemap\n// might still look correct with a simple case\nfunction main() {\n  mainInner()\n}\n\nfunction mainInner() {\n  // @ts-expect-error \"define\"\n  console.trace('with-define-object', __testDefineObject)\n}\n\nmain()\n"
  },
  {
    "path": "playground/js-sourcemap/with-multiline-import.ts",
    "content": "// prettier-ignore\nimport {\n  foo\n} from '@vitejs/test-importee-pkg'\n\nconsole.log('with-multiline-import', foo)\n"
  },
  {
    "path": "playground/js-sourcemap/zoo-with-sourcemap-plugin.ts",
    "content": "import MagicString from 'magic-string'\nimport type { Plugin } from 'vite'\n\nexport const transformZooWithSourcemapPlugin: () => Plugin = () => ({\n  name: 'sourcemap',\n  transform(code, id) {\n    if (id.includes('zoo.js')) {\n      const ms = new MagicString(code)\n      ms.append('// add comment')\n      return {\n        code: ms.toString(),\n        // NOTE: MagicString without `filename` option generates\n        //       a sourcemap with `sources: ['']` or `sources: [null]`\n        map: ms.generateMap({ hires: true }),\n      }\n    }\n  },\n})\n"
  },
  {
    "path": "playground/js-sourcemap/zoo.js",
    "content": "export const zoo = 'zoo'\n"
  },
  {
    "path": "playground/json/__tests__/csr/json-csr.spec.ts",
    "content": "import { readFileSync } from 'node:fs'\nimport { expect, test } from 'vitest'\nimport deepJson from 'vue/package.json'\nimport testJson from '../../test.json'\nimport hmrJson from '../../hmr.json'\nimport { editFile, isBuild, isServe, page } from '~utils'\n\nconst stringified = JSON.stringify(testJson)\nconst deepStringified = JSON.stringify(deepJson)\nconst hmrStringified = JSON.stringify(hmrJson)\n\ntest('default import', async () => {\n  expect(await page.textContent('.full')).toBe(stringified)\n})\n\ntest('named import', async () => {\n  expect(await page.textContent('.named')).toBe(testJson.hello)\n})\n\ntest('deep import', async () => {\n  expect(await page.textContent('.deep-full')).toBe(deepStringified)\n})\n\ntest('named deep import', async () => {\n  expect(await page.textContent('.deep-named')).toBe(deepJson.name)\n})\n\ntest('dynamic import', async () => {\n  expect(await page.textContent('.dynamic')).toBe(stringified)\n})\n\ntest('dynamic import, named', async () => {\n  expect(await page.textContent('.dynamic-named')).toBe(testJson.hello)\n})\n\ntest('fetch', async () => {\n  expect(await page.textContent('.fetch')).toBe(stringified)\n})\n\ntest('?url', async () => {\n  expect(await page.textContent('.url')).toMatch(\n    isBuild ? 'data:application/json' : '/test.json',\n  )\n})\n\ntest('?raw', async () => {\n  expect(await page.textContent('.raw')).toBe(\n    readFileSync(require.resolve('../../test.json'), 'utf-8'),\n  )\n})\n\ntest('require(json) returns object without default export', async () => {\n  expect(await page.textContent('.require')).toBe(JSON.stringify({ 200: 'ok' }))\n})\n\ntest.runIf(isServe)('should full reload', async () => {\n  expect(await page.textContent('.hmr')).toBe(hmrStringified)\n\n  editFile('hmr.json', (code) =>\n    code.replace('\"this is hmr json\"', '\"this is hmr update json\"'),\n  )\n  await expect\n    .poll(() => page.textContent('.hmr'))\n    .toMatch('\"this is hmr update json\"')\n})\n"
  },
  {
    "path": "playground/json/dep-json-require/content.json",
    "content": "{\n  \"200\": \"ok\"\n}\n"
  },
  {
    "path": "playground/json/dep-json-require/index.js",
    "content": "const content = require('./content.json')\n\nmodule.exports = { content }\n"
  },
  {
    "path": "playground/json/dep-json-require/package.json",
    "content": "{\n  \"name\": \"@vitejs/require\",\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/json/hmr.json",
    "content": "{\n  \"hmr\": \"this is hmr json\"\n}\n"
  },
  {
    "path": "playground/json/index.html",
    "content": "<h2>Normal Import</h2>\n<pre class=\"full\"></pre>\n<pre class=\"named\"></pre>\n\n<h2>Deep Import</h2>\n<pre class=\"deep-full\"></pre>\n<pre class=\"deep-named\"></pre>\n\n<h2>Dynamic Import</h2>\n<pre class=\"dynamic\"></pre>\n<pre class=\"dynamic-named\"></pre>\n\n<h2>fetch</h2>\n<pre class=\"fetch\"></pre>\n\n<h2>Importing as URL</h2>\n<pre class=\"url\"></pre>\n\n<h2>Raw Import</h2>\n<pre class=\"raw\"></pre>\n\n<h2>JSON Module</h2>\n<pre class=\"module\"></pre>\n\n<h2>Has BOM Tag</h2>\n<pre class=\"bom\"></pre>\n\n<h2>require(json) returns object without default export</h2>\n<pre class=\"require\"></pre>\n\n<h2>HMR</h2>\n<pre class=\"hmr\"></pre>\n\n<script type=\"module\">\n  import json, { hello } from './test.json'\n  import deepJson, { name } from 'vue/package.json'\n\n  text('.full', JSON.stringify(json))\n  text('.named', hello)\n\n  text('.deep-full', JSON.stringify(deepJson))\n  text('.deep-named', name)\n\n  import('/test.json').then((mod) => {\n    text('.dynamic', JSON.stringify(mod.default))\n    text('.dynamic-named', mod.hello)\n  })\n\n  fetch(import.meta.env.DEV ? '/test.json' : '/public.json')\n    .then((r) => r.json())\n    .then((data) => {\n      text('.fetch', JSON.stringify(data))\n    })\n\n  import url from './test.json?url'\n  text('.url', url)\n\n  import raw from './test.json?raw'\n  text('.raw', raw)\n\n  import moduleJSON from '@vitejs/test-json-module'\n  text('.module', JSON.stringify(moduleJSON))\n\n  import hasBomJson from './json-bom/has-bom.json'\n  text('.bom', JSON.stringify(hasBomJson))\n\n  import requireJson from '@vitejs/test-json-require'\n  text('.require', JSON.stringify(requireJson.content))\n\n  import hmrJSON from './hmr.json'\n  text('.hmr', JSON.stringify(hmrJSON))\n\n  function text(sel, text) {\n    document.querySelector(sel).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/json/json-bom/has-bom.json",
    "content": "﻿{\n  \"description\": \"This file is marked with BOM.\",\n  \"message\": \"If the parsing is successful, the BOM tag has been removed.\"\n}\n"
  },
  {
    "path": "playground/json/json-module/index.json",
    "content": "{\n  \"hello\": \"hi\"\n}\n"
  },
  {
    "path": "playground/json/json-module/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-json-module\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/json/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-json\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/test-json-require\": \"file:./dep-json-require\",\n    \"@vitejs/test-json-module\": \"file:./json-module\",\n    \"vue\": \"^3.5.30\"\n  }\n}\n"
  },
  {
    "path": "playground/json/public/public.json",
    "content": "{\n  \"hello\": \"this is json\"\n}\n"
  },
  {
    "path": "playground/json/test.json",
    "content": "{\n  \"hello\": \"this is json\"\n}\n"
  },
  {
    "path": "playground/legacy/__tests__/client-and-ssr/legacy-client-legacy-ssr-sequential-builds.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { port } from './serve'\nimport { isBuild, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ndescribe.runIf(isBuild)('client-legacy-ssr-sequential-builds', () => {\n  test('should work', async () => {\n    await page.goto(url)\n    expect(await page.textContent('#app')).toMatch('Hello')\n  })\n\n  test('import.meta.env.MODE', async () => {\n    // SSR build is always modern\n    expect(await page.textContent('#mode')).toMatch('test')\n  })\n})\n"
  },
  {
    "path": "playground/legacy/__tests__/client-and-ssr/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\nimport path from 'node:path'\nimport { ports, rootDir } from '~utils'\n\nexport const port = ports['legacy/client-and-ssr']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  const { build } = await import('vite')\n\n  await build({\n    mode: 'test',\n    root: rootDir,\n    logLevel: 'silent',\n    build: {\n      target: 'esnext',\n      outDir: 'dist/client',\n    },\n  })\n\n  await build({\n    mode: 'test',\n    root: rootDir,\n    logLevel: 'silent',\n    build: {\n      target: 'esnext',\n      ssr: 'entry-server-sequential.js',\n      outDir: 'dist/server',\n    },\n  })\n\n  const { default: express } = await import('express')\n  const app = express()\n\n  app.use('/', async (_req, res) => {\n    const { render } = await import(\n      path.resolve(rootDir, './dist/server/entry-server-sequential.js')\n    )\n    const html = await render()\n    res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n  })\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/legacy/__tests__/legacy.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport {\n  findAssetFile,\n  getColor,\n  isBuild,\n  listAssets,\n  page,\n  readFile,\n  readManifest,\n} from '~utils'\n\ntest('should load the worker', async () => {\n  await expect.poll(() => page.textContent('.worker-message')).toMatch('module')\n})\n\ntest('should work', async () => {\n  await expect.poll(() => page.textContent('#app')).toMatch('Hello')\n})\n\ntest('import.meta.env.LEGACY', async () => {\n  await expect\n    .poll(() => page.textContent('#env'))\n    .toMatch(isBuild ? 'true' : 'false')\n  await expect.poll(() => page.textContent('#env-equal')).toMatch('true')\n})\n\n// https://github.com/vitejs/vite/issues/3400\ntest('transpiles down iterators correctly', async () => {\n  await expect.poll(() => page.textContent('#iterators')).toMatch('hello')\n})\n\ntest('async generator', async () => {\n  await expect\n    .poll(() => page.textContent('#async-generator'))\n    .toMatch('[0,1,2]')\n})\n\ntest('wraps with iife', async () => {\n  await expect\n    .poll(() => page.textContent('#babel-helpers'))\n    .toMatch('exposed babel helpers: false')\n})\n\ntest('generates assets', async () => {\n  await expect\n    .poll(() => page.textContent('#assets'))\n    .toMatch(\n      isBuild\n        ? [\n            'index: text/html',\n            'index-legacy: text/html',\n            'chunk-async: text/html',\n            'chunk-async-legacy: text/html',\n            'immutable-chunk: text/javascript',\n            'immutable-chunk-legacy: text/javascript',\n            'polyfills-legacy: text/html',\n          ].join('\\n')\n        : [\n            'index: text/html',\n            'index-legacy: text/html',\n            'chunk-async: text/html',\n            'chunk-async-legacy: text/html',\n            'immutable-chunk: text/html',\n            'immutable-chunk-legacy: text/html',\n            'polyfills-legacy: text/html',\n          ].join('\\n'),\n    )\n})\n\ntest('correctly emits styles', async () => {\n  expect(await getColor('#app')).toBe('red')\n})\n\n// dynamic import css\ntest('should load dynamic import with css', async () => {\n  await page.click('#dynamic-css-button')\n  await expect.poll(() => getColor('#dynamic-css')).toBe('red')\n})\n\ntest('asset url', async () => {\n  expect(await page.textContent('#asset-path')).toMatch(\n    isBuild ? /\\/assets\\/vite-[-\\w]+\\.svg/ : '/vite.svg',\n  )\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('should generate correct manifest', async () => {\n    const manifest = readManifest()\n    // legacy polyfill\n    expect(manifest['../../vite/legacy-polyfills-legacy']).toBeDefined()\n    expect(manifest['../../vite/legacy-polyfills-legacy'].src).toBe(\n      '../../vite/legacy-polyfills-legacy',\n    )\n    expect(manifest['custom0-legacy.js'].file).toMatch(\n      /chunk-X-legacy\\.[-\\w]{8}.js/,\n    )\n    expect(manifest['custom1-legacy.js'].file).toMatch(\n      /chunk-X-legacy-[-\\w]{8}.js/,\n    )\n    expect(manifest['custom2-legacy.js'].file).toMatch(\n      /chunk-X-legacy[-\\w]{8}.js/,\n    )\n    // modern polyfill\n    expect(manifest['../../vite/legacy-polyfills']).toBeDefined()\n    expect(manifest['../../vite/legacy-polyfills'].src).toBe(\n      '../../vite/legacy-polyfills',\n    )\n  })\n\n  test('should minify legacy chunks with terser', async () => {\n    // This is a ghetto heuristic, but terser output seems to reliably start\n    // with one of the following, and non-terser output (including unminified or\n    // esbuild-minified) does not!\n    const terserPattern = /^(?:!function|System.register)/\n\n    expect(findAssetFile(/chunk-async-legacy/)).toMatch(terserPattern)\n    expect(findAssetFile(/chunk-async(?!-legacy)/)).not.toMatch(terserPattern)\n    expect(findAssetFile(/immutable-chunk-legacy/)).toMatch(terserPattern)\n    expect(findAssetFile(/immutable-chunk(?!-legacy)/)).not.toMatch(\n      terserPattern,\n    )\n    expect(findAssetFile(/index-legacy/)).toMatch(terserPattern)\n    expect(findAssetFile(/index(?!-legacy)/)).not.toMatch(terserPattern)\n    expect(findAssetFile(/polyfills-legacy/)).toMatch(terserPattern)\n  })\n\n  test('should emit css file', async () => {\n    expect(\n      listAssets().some((filename) => filename.endsWith('.css')),\n    ).toBeTruthy()\n  })\n\n  test('includes structuredClone polyfill which is supported after core-js v3', () => {\n    expect(findAssetFile(/polyfills-legacy/)).toMatch('\"structuredClone\"')\n    expect(findAssetFile(/polyfills-[-\\w]{8}\\./)).toMatch('\"structuredClone\"')\n  })\n\n  test('should generate legacy sourcemap file', async () => {\n    expect(\n      listAssets().some((filename) =>\n        /chunk-main-legacy\\.[-\\w]{8}\\.js\\.map$/.test(filename),\n      ),\n    ).toBeTruthy()\n    expect(\n      listAssets().some((filename) =>\n        /polyfills-legacy-[-\\w]{8}\\.js\\.map$/.test(filename),\n      ),\n    ).toBeTruthy()\n    // also for modern polyfills\n    expect(\n      listAssets().some((filename) =>\n        /polyfills-[-\\w]{8}\\.js\\.map$/.test(filename),\n      ),\n    ).toBeTruthy()\n  })\n\n  test('should have only modern entry files guarded', async () => {\n    const guard = /(import\\s*\\()|(import.meta)|(async\\s*function\\*)/\n    expect(findAssetFile(/index(?!-legacy)/)).toMatch(guard)\n    expect(findAssetFile(/polyfills(?!-legacy)/)).toMatch(guard)\n\n    expect(findAssetFile(/chunk-async(?!-legacy)/)).not.toMatch(guard)\n    expect(findAssetFile(/index-legacy/)).not.toMatch(guard)\n  })\n\n  test('should not include preload helper in legacy chunks', async () => {\n    expect(\n      listAssets().filter(\n        (filename) =>\n          filename.includes('-legacy') &&\n          readFile(`dist/assets/${filename}`).includes('Unable to preload'),\n      ),\n    ).toStrictEqual([])\n  })\n})\n"
  },
  {
    "path": "playground/legacy/__tests__/no-polyfills/legacy-no-polyfills.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page, viteTestUrl } from '~utils'\n\ntest('should load and execute the JS file', async () => {\n  await page.goto(viteTestUrl + '/no-polyfills.html')\n  await expect.poll(() => page.textContent('main')).toMatch('👋')\n})\n\ntest.runIf(isBuild)('includes a script tag for SystemJS', async () => {\n  await expect\n    .poll(() => page.getAttribute('#vite-legacy-polyfill', 'src'))\n    .toMatch(/.\\/assets\\/polyfills-legacy-(.+)\\.js/)\n  await expect\n    .poll(() => page.getAttribute('#vite-legacy-entry', 'data-src'))\n    .toMatch(/.\\/assets\\/index-legacy-(.+)\\.js/)\n})\n"
  },
  {
    "path": "playground/legacy/__tests__/no-polyfills-no-systemjs/legacy-no-polyfills-no-systemjs.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page, viteTestUrl } from '~utils'\n\ntest.runIf(isBuild)('includes only a single script tag', async () => {\n  await page.goto(viteTestUrl + '/no-polyfills-no-systemjs.html')\n\n  await expect\n    .poll(() => page.getAttribute('#vite-legacy-entry', 'data-src'))\n    .toMatch(/.\\/assets\\/index-legacy-(.+)\\.js/)\n\n  expect(await page.locator('script').count()).toBe(1)\n  expect(await page.locator('#vite-legacy-polyfill').count()).toBe(0)\n  expect(await page.locator('#vite-legacy-entry').count()).toBe(1)\n})\n"
  },
  {
    "path": "playground/legacy/__tests__/ssr/legacy-ssr.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { port } from './serve'\nimport { isBuild, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ndescribe.runIf(isBuild)('legacy-ssr', () => {\n  test('should work', async () => {\n    await page.goto(url)\n    expect(await page.textContent('#app')).toMatch('Hello')\n  })\n\n  test('import.meta.env.LEGACY', async () => {\n    // SSR build is always modern\n    expect(await page.textContent('#env')).toMatch('false')\n  })\n})\n"
  },
  {
    "path": "playground/legacy/__tests__/ssr/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\nimport path from 'node:path'\nimport { ports, rootDir } from '~utils'\n\nexport const port = ports['legacy/ssr']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  const { build } = await import('vite')\n  await build({\n    root: rootDir,\n    logLevel: 'silent',\n    build: {\n      target: 'esnext',\n      ssr: 'entry-server.js',\n      outDir: 'dist/server',\n    },\n  })\n\n  const { default: express } = await import('express')\n  const app = express()\n\n  app.use('/', async (_req, res) => {\n    const { render } = await import(\n      path.resolve(rootDir, './dist/server/entry-server.js')\n    )\n    const html = await render()\n    res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n  })\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/legacy/__tests__/watch/legacy-styles-only-entry-watch.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport {\n  editFile,\n  findAssetFile,\n  isBuild,\n  notifyRebuildComplete,\n  readManifest,\n  watcher,\n} from '~utils'\n\ntest.runIf(isBuild)('rebuilds styles only entry on change', async () => {\n  expect(findAssetFile(/style-only-entry-.+\\.css/, 'watch')).toContain(\n    '#ff69b4',\n  )\n  expect(findAssetFile(/style-only-entry-legacy-.+\\.js/, 'watch')).toContain(\n    '#ff69b4',\n  )\n  expect(findAssetFile(/polyfills-legacy-.+\\.js/, 'watch')).toBeTruthy()\n  const numberOfManifestEntries = Object.keys(readManifest('watch')).length\n  expect(numberOfManifestEntries).toBe(3)\n\n  editFile('style-only-entry.css', (originalContents) =>\n    originalContents.replace('#ff69b4', '#ffb6c1'),\n  )\n  await notifyRebuildComplete(watcher)\n\n  const updatedManifest = readManifest('watch')\n  expect(Object.keys(updatedManifest)).toHaveLength(numberOfManifestEntries)\n\n  // We must use the file referenced in the manifest here,\n  // since there'll be different versions of the file with different hashes.\n  const reRenderedCssFile = findAssetFile(\n    updatedManifest['style-only-entry.css']!.file.substring('assets/'.length),\n    'watch',\n  )\n  expect(reRenderedCssFile).toContain('#ffb6c1')\n  const reRenderedCssLegacyFile = findAssetFile(\n    updatedManifest['style-only-entry-legacy.css']!.file.substring(\n      'assets/'.length,\n    ),\n    'watch',\n  )\n  expect(reRenderedCssLegacyFile).toContain('#ffb6c1')\n  expect(findAssetFile(/polyfills-legacy-.+\\.js/, 'watch')).toBeTruthy()\n})\n"
  },
  {
    "path": "playground/legacy/async.js",
    "content": "export function fn() {\n  const m = new Map()\n  m.set('foo', 'Hello')\n  document.querySelector('#app').textContent = m.get('foo')\n}\n"
  },
  {
    "path": "playground/legacy/custom0.js",
    "content": "export const foo = 'bar'\n"
  },
  {
    "path": "playground/legacy/custom1.js",
    "content": "export const foo = 'bar'\n"
  },
  {
    "path": "playground/legacy/custom2.js",
    "content": "export const foo = 'bar'\n"
  },
  {
    "path": "playground/legacy/dynamic.css",
    "content": "#dynamic-css {\n  color: red;\n}\n"
  },
  {
    "path": "playground/legacy/entry-server-sequential.js",
    "content": "// This counts as 'server-side' rendering, yes?\nexport async function render() {\n  return /* html */ `\n    <div id=\"app\">Hello</div>\n    <div id=\"mode\">${import.meta.env.MODE}</div>\n  `\n}\n"
  },
  {
    "path": "playground/legacy/entry-server.js",
    "content": "// This counts as 'server-side' rendering, yes?\nexport async function render() {\n  return /* html */ `\n    <div id=\"app\">Hello</div>\n    <div id=\"env\">${import.meta.env.LEGACY}</div>\n  `\n}\n"
  },
  {
    "path": "playground/legacy/immutable-chunk.js",
    "content": "const chunks = [\n  'index',\n  'index-legacy',\n  'chunk-async',\n  'chunk-async-legacy',\n  'immutable-chunk',\n  'immutable-chunk-legacy',\n  'polyfills-legacy',\n]\n\nexport function fn() {\n  return Promise.all(\n    chunks.map(async (name) => {\n      const response = await fetch(`/assets/${name}.js`)\n      return `${name}: ${response.headers.get('Content-Type')}`\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/legacy/index.html",
    "content": "<h1 id=\"app\"></h1>\n<div id=\"env\"></div>\n<div id=\"env-equal\"></div>\n<div id=\"iterators\"></div>\n<div id=\"features-after-corejs-3\"></div>\n<div id=\"async-generator\"></div>\n<div id=\"babel-helpers\"></div>\n<div id=\"assets\" style=\"white-space: break-spaces; background: lightgray\"></div>\n<button id=\"dynamic-css-button\">dynamic css</button>\n<div id=\"dynamic-css\"></div>\n<p>## worker message:</p>\n<div class=\"worker-message\"></div>\n<div id=\"asset-path\"></div>\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/legacy/main.js",
    "content": "import './style.css'\nimport viteSvgPath from './vite.svg'\nimport MyWorker from './worker?worker'\n\nasync function run() {\n  await import('./custom0.js')\n  await import('./custom1.js')\n  await import('./custom2.js')\n  const { fn } = await import('./async.js')\n  fn()\n}\n\nrun()\n\nlet isLegacy\n\n// make sure that branching works despite esbuild's constant folding (#1999)\nif (import.meta.env.LEGACY) {\n  if (import.meta.env.LEGACY === true) isLegacy = true\n} else {\n  if (import.meta.env.LEGACY === false) isLegacy = false\n}\n\ntext('#env', `is legacy: ${isLegacy}`)\n\nconst metaEnvObj = import.meta.env\ntext('#env-equal', import.meta.env.LEGACY === metaEnvObj.LEGACY)\n\n// Iterators\ntext('#iterators', [...new Set(['hello'])].join(''))\n\n// structuredClone is supported core.js v3.20.0+\ntext(\n  '#features-after-corejs-3',\n  JSON.stringify(structuredClone({ foo: 'foo' })),\n)\n\n// async generator\nasync function* asyncGenerator() {\n  for (let i = 0; i < 3; i++) {\n    await new Promise((resolve) => setTimeout(resolve, 10))\n    yield i\n  }\n}\n;(async () => {\n  const result = []\n  for await (const i of asyncGenerator()) {\n    result.push(i)\n  }\n  text('#async-generator', JSON.stringify(result))\n})()\n\n// babel-helpers\n// Using `String.raw` to inject `@babel/plugin-transform-template-literals`\n// helpers.\ntext(\n  '#babel-helpers',\n  String.raw`exposed babel helpers: ${window._templateObject != null}`,\n)\n\n// dynamic chunk names\nimport('./immutable-chunk.js')\n  .then(({ fn }) => fn())\n  .then((assets) => {\n    text('#assets', assets.join('\\n'))\n  })\n\n// dynamic css\ndocument\n  .querySelector('#dynamic-css-button')\n  .addEventListener('click', async () => {\n    await import('./dynamic.css')\n    text('#dynamic-css', 'dynamic import css')\n  })\n\ntext('#asset-path', viteSvgPath)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nconst worker = new MyWorker()\nworker.postMessage('ping')\nworker.addEventListener('message', (ev) => {\n  text('.worker-message', JSON.stringify(ev.data))\n})\n"
  },
  {
    "path": "playground/legacy/module.js",
    "content": "export const module = 'module'\n"
  },
  {
    "path": "playground/legacy/nested/index.html",
    "content": "<h1 id=\"nested html\"></h1>\n<script type=\"module\" src=\"../main.js\"></script>\n"
  },
  {
    "path": "playground/legacy/no-polyfills-no-systemjs.html",
    "content": "<meta charset=\"UTF-8\" />\n<main></main>\n<script type=\"module\" src=\"./no-polyfills-no-systemjs.js\"></script>\n"
  },
  {
    "path": "playground/legacy/no-polyfills-no-systemjs.js",
    "content": "document.querySelector('main').innerHTML = '👋'\n"
  },
  {
    "path": "playground/legacy/no-polyfills.html",
    "content": "<meta charset=\"UTF-8\" />\n<main></main>\n<script type=\"module\" src=\"./no-polyfills.js\"></script>\n"
  },
  {
    "path": "playground/legacy/no-polyfills.js",
    "content": "document.querySelector('main').innerHTML = '👋'\n"
  },
  {
    "path": "playground/legacy/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-legacy\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build --debug legacy\",\n    \"build:custom-filename\": \"vite --config ./vite.config-custom-filename.js build  --debug legacy\",\n    \"build:multiple-output\": \"vite --config ./vite.config-multiple-output.js build\",\n    \"build:no-polyfills\": \"vite --config ./vite.config-no-polyfills.js build\",\n    \"build:no-polyfills-no-systemjs\": \"vite --config ./vite.config-no-polyfills-no-systemjs.js build\",\n    \"build:watch\": \"vite --config ./vite.config-watch.js build --debug legacy\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"workspace:*\",\n    \"@vitejs/plugin-legacy\": \"workspace:*\",\n    \"express\": \"^5.2.1\",\n    \"terser\": \"^5.46.0\"\n  }\n}\n"
  },
  {
    "path": "playground/legacy/style-only-entry.css",
    "content": ":root {\n  background: #ff69b4;\n}\n"
  },
  {
    "path": "playground/legacy/style.css",
    "content": "#app {\n  color: red;\n}\n"
  },
  {
    "path": "playground/legacy/vite.config-custom-filename.js",
    "content": "import { defineConfig } from 'vite'\nimport legacy from '@vitejs/plugin-legacy'\n\nexport default defineConfig({\n  plugins: [legacy({ modernPolyfills: true })],\n  build: {\n    manifest: true,\n    minify: false,\n    rollupOptions: {\n      output: {\n        entryFileNames: `assets/[name].js`,\n        chunkFileNames: `assets/[name].js`,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/legacy/vite.config-multiple-output.js",
    "content": "import { defineConfig } from 'vite'\nimport legacy from '@vitejs/plugin-legacy'\n\nexport default defineConfig({\n  plugins: [legacy({ modernPolyfills: true })],\n  build: {\n    manifest: true,\n    minify: false,\n    rollupOptions: {\n      output: [\n        {\n          assetFileNames() {\n            return 'assets/subdir/[name]-[hash][extname]'\n          },\n          entryFileNames: `assets/subdir/[name].js`,\n          chunkFileNames: `assets/subdir/[name].js`,\n        },\n        {\n          assetFileNames() {\n            return 'assets/subdir/[name]-[hash][extname]'\n          },\n          entryFileNames: `assets/anotherSubdir/[name].js`,\n          chunkFileNames: `assets/anotherSubdir/[name].js`,\n        },\n      ],\n    },\n  },\n})\n"
  },
  {
    "path": "playground/legacy/vite.config-no-polyfills-no-systemjs.js",
    "content": "import path from 'node:path'\nimport legacy from '@vitejs/plugin-legacy'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig(({ isPreview }) => ({\n  base: !isPreview ? './' : '/no-polyfills-no-systemjs/',\n  plugins: [\n    legacy({\n      renderModernChunks: false,\n      polyfills: false,\n      externalSystemJS: true,\n    }),\n    {\n      name: 'remove crossorigin attribute',\n      transformIndexHtml: (html) => html.replaceAll('crossorigin', ''),\n      enforce: 'post',\n    },\n  ],\n\n  build: {\n    outDir: 'dist/no-polyfills-no-systemjs',\n    rollupOptions: {\n      input: {\n        index: path.resolve(\n          import.meta.dirname,\n          'no-polyfills-no-systemjs.html',\n        ),\n      },\n    },\n  },\n}))\n"
  },
  {
    "path": "playground/legacy/vite.config-no-polyfills.js",
    "content": "import path from 'node:path'\nimport legacy from '@vitejs/plugin-legacy'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig(({ isPreview }) => ({\n  base: !isPreview ? './' : '/no-polyfills/',\n  plugins: [\n    legacy({\n      renderModernChunks: false,\n      polyfills: false,\n    }),\n    {\n      name: 'remove crossorigin attribute',\n      transformIndexHtml: (html) => html.replaceAll('crossorigin', ''),\n      enforce: 'post',\n    },\n  ],\n\n  build: {\n    outDir: 'dist/no-polyfills',\n    rollupOptions: {\n      input: {\n        index: path.resolve(import.meta.dirname, 'no-polyfills.html'),\n      },\n    },\n  },\n}))\n"
  },
  {
    "path": "playground/legacy/vite.config-watch.js",
    "content": "import { resolve } from 'node:path'\nimport legacy from '@vitejs/plugin-legacy'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  plugins: [legacy()],\n  build: {\n    manifest: true,\n    rollupOptions: {\n      input: {\n        'style-only-entry': resolve(\n          import.meta.dirname,\n          'style-only-entry.css',\n        ),\n      },\n    },\n    watch: {},\n    outDir: 'dist/watch',\n  },\n})\n"
  },
  {
    "path": "playground/legacy/vite.config.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport legacy from '@vitejs/plugin-legacy'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  base: './',\n  plugins: [\n    legacy({\n      targets: 'IE 11',\n      modernPolyfills: true,\n    }),\n  ],\n\n  build: {\n    cssCodeSplit: false,\n    manifest: true,\n    sourcemap: true,\n    assetsInlineLimit: 100, // keep SVG as assets URL\n    rollupOptions: {\n      input: {\n        index: path.resolve(import.meta.dirname, 'index.html'),\n        nested: path.resolve(import.meta.dirname, 'nested/index.html'),\n      },\n      output: {\n        chunkFileNames(chunkInfo) {\n          if (chunkInfo.name === 'immutable-chunk') {\n            return `assets/${chunkInfo.name}.js`\n          } else if (/custom\\d/.test(chunkInfo.name)) {\n            return `assets/chunk-X${\n              ['.', '-', ''][/custom(\\d)/.exec(chunkInfo.name)[1]]\n            }[hash].js`\n          }\n          return `assets/chunk-[name].[hash].js`\n        },\n      },\n    },\n  },\n\n  // for tests, remove `<script type=\"module\">` tags and remove `nomodule`\n  // attrs so that we run the legacy bundle instead.\n  __test__() {\n    const indexPath = path.resolve(import.meta.dirname, './dist/index.html')\n    let index = fs.readFileSync(indexPath, 'utf-8')\n    index = index\n      .replace(/<script type=\"module\".*?<\\/script>/g, '')\n      .replace(/<script nomodule/g, '<script')\n    fs.writeFileSync(indexPath, index)\n  },\n})\n"
  },
  {
    "path": "playground/legacy/worker.js",
    "content": "import { module } from './module'\n\nself.onmessage = () => {\n  self.postMessage(module)\n}\n"
  },
  {
    "path": "playground/lib/__tests__/lib.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { isBuild, isServe, page, readFile, serverLogs } from '~utils'\n\ndescribe.runIf(isBuild)('build', () => {\n  test('es', async () => {\n    expect(await page.textContent('.es')).toBe('It works')\n  })\n\n  test('umd', async () => {\n    expect(await page.textContent('.umd')).toBe('It works')\n    const code = readFile('dist/my-lib-custom-filename.umd.cjs')\n    const noMinifyCode = readFile(\n      'dist/nominify/my-lib-custom-filename.umd.cjs',\n    )\n    const namedCode = readFile('dist/named/my-lib-named.umd.cjs')\n    // esbuild helpers are injected inside of the UMD wrapper\n    expect(code).toMatch(/^\\/\\*[^*]*\\*\\/\\s*\\(function\\(/)\n    expect(noMinifyCode).toMatch(\n      /^\\/\\*[^*]*\\*\\/\\s*\\(function\\(global.+?function\\smyLib\\(/s,\n    )\n    expect(namedCode).toMatch(/^\\(function\\(/)\n  })\n\n  test('iife', async () => {\n    expect(await page.textContent('.iife')).toBe('It works')\n    const code = readFile('dist/my-lib-custom-filename.iife.js')\n    const noMinifyCode = readFile(\n      'dist/nominify/my-lib-custom-filename.iife.js',\n    )\n    const namedCode = readFile('dist/named/my-lib-named.iife.js')\n    // esbuild helpers are injected inside of the IIFE wrapper\n    expect(code).toMatch(/^\\/\\*[^*]*\\*\\/\\s*var MyLib=\\(function\\(\\)\\{\\s*/)\n    expect(noMinifyCode).toMatch(\n      /^\\/\\*[^*]*\\*\\/\\s*var MyLib\\s*=\\s*\\(function\\(\\)\\s*\\{\\s*/,\n    )\n    expect(namedCode).toMatch(/^var MyLibNamed=\\(function\\([^()]+\\)\\{\\s*/)\n  })\n\n  test('restrisct-helpers-injection', async () => {\n    const code = readFile(\n      'dist/helpers-injection/my-lib-custom-filename.iife.js',\n    )\n    expect(code).toMatch(\n      `\\\\\"use strict\\\\\"; return (\" + expressionSyntax + \").constructor;\"`,\n    )\n  })\n\n  test('Library mode does not include `preload`', async () => {\n    await expect\n      .poll(() => page.textContent('.dynamic-import-message'))\n      .toMatch('hello vite')\n    const code = readFile('dist/lib/dynamic-import-message.es.mjs')\n    expect(code).not.toMatch('__vitePreload')\n\n    // Test that library chunks are hashed\n    expect(code).toMatch(/await import\\(['\"`]\\.\\/message-[-\\w]{8}.js['\"`]\\)/)\n  })\n\n  test('Library mode does not have any reference to pure CSS chunks', async () => {\n    const code = readFile('dist/lib/dynamic-import-message.es.mjs')\n\n    // Does not import pure CSS chunks and replaced by `Promise.resolve({})` instead\n    expect(code).not.toMatch(\n      /await import\\(['\"`]\\.\\/dynamic-[-\\w]{8}.js['\"`]\\)/,\n    )\n    expect(code).toMatch(/await Promise.resolve\\(\\{.*\\}\\)/)\n  })\n\n  test('pure annotations are kept for es output', () => {\n    const es = readFile('dist/my-lib-custom-filename.js')\n    expect(es).toMatch(/[@#]__PURE__/)\n  })\n\n  test('pure annotations are removed for non-es output', () => {\n    const es = readFile('dist/my-lib-custom-filename.iife.js')\n    expect(es).not.toMatch(/[@#]__PURE__/)\n  })\n\n  test('@import hoist', async () => {\n    serverLogs.forEach((log) => {\n      // no warning from esbuild css minifier\n      expect(log).not.toMatch('All \"@import\" rules must come first')\n    })\n  })\n\n  test('preserve process.env', () => {\n    const es = readFile('dist/my-lib-custom-filename.js')\n    const iife = readFile('dist/my-lib-custom-filename.iife.js')\n    const umd = readFile('dist/my-lib-custom-filename.umd.cjs')\n    expect(es).toMatch('process.env.NODE_ENV')\n    expect(iife).toMatch('process.env.NODE_ENV')\n    expect(umd).toMatch('process.env.NODE_ENV')\n  })\n\n  test('debugger statements are removed by terser for es', () => {\n    const terserEs = readFile('dist/terser/my-lib-custom-filename.js')\n    expect(terserEs).not.toMatch('debugger')\n  })\n\n  test('pure annotations are not removed by terser for es', () => {\n    const terserEs = readFile('dist/terser/my-lib-custom-filename.js')\n    expect(terserEs).toMatch(/[@#]__PURE__/)\n  })\n\n  test('pure annotations are removed by terser for non-es output', () => {\n    const terserIife = readFile('dist/terser/my-lib-custom-filename.iife.js')\n    expect(terserIife).not.toMatch(/[@#]__PURE__/)\n  })\n\n  test('single entry with css', () => {\n    const css = readFile('dist/css-single-entry/test-my-lib.css')\n    const js = readFile('dist/css-single-entry/test-my-lib.js')\n    const umd = readFile('dist/css-single-entry/test-my-lib.umd.cjs')\n    expect(css).toMatch('entry-1.css')\n    expect(js).toMatch('css-entry-1')\n    expect(umd).toContain('css-entry-1')\n  })\n\n  test('multi entry with css', () => {\n    const css = readFile('dist/css-multi-entry/test-my-lib.css')\n    const js1 = readFile('dist/css-multi-entry/css-entry-1.js')\n    const js2 = readFile('dist/css-multi-entry/css-entry-2.js')\n    const cjs1 = readFile('dist/css-multi-entry/css-entry-1.cjs')\n    const cjs2 = readFile('dist/css-multi-entry/css-entry-2.cjs')\n    expect(css).toMatch('entry-1.css')\n    expect(css).toMatch('entry-2.css')\n    expect(js1).toMatch('css-entry-1')\n    expect(js2).toMatch('css-entry-2')\n    expect(cjs1).toContain('css-entry-1')\n    expect(cjs2).toContain('css-entry-2')\n  })\n\n  test('multi entry with css and code split', () => {\n    const css1 = readFile('dist/css-code-split/css-entry-1.css')\n    const css2 = readFile('dist/css-code-split/css-entry-2.css')\n    const js1 = readFile('dist/css-code-split/css-entry-1.js')\n    const js2 = readFile('dist/css-code-split/css-entry-2.js')\n    const cjs1 = readFile('dist/css-code-split/css-entry-1.cjs')\n    const cjs2 = readFile('dist/css-code-split/css-entry-2.cjs')\n    expect(css1).toMatch('entry-1.css')\n    expect(css2).toMatch('entry-2.css')\n    expect(js1).toMatch('css-entry-1')\n    expect(js2).toMatch('css-entry-2')\n    expect(cjs1).toContain('css-entry-1')\n    expect(cjs2).toContain('css-entry-2')\n  })\n})\n\ntest.runIf(isServe)('dev', async () => {\n  await expect.poll(() => page.textContent('.demo')).toBe('It works')\n})\n"
  },
  {
    "path": "playground/lib/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport http from 'node:http'\nimport sirv from 'sirv'\nimport {\n  isBuild,\n  page,\n  ports,\n  rootDir,\n  serverLogs,\n  setViteUrl,\n  viteTestUrl,\n} from '~utils'\n\nconst dirname = import.meta.dirname\n\nexport const port = ports.lib\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  setupConsoleWarnCollector()\n\n  if (!isBuild) {\n    const { createServer } = await import('vite')\n    process.env.VITE_INLINE = 'inline-serve'\n    const viteServer = await (\n      await createServer({\n        root: rootDir,\n        logLevel: 'silent',\n        server: {\n          port,\n          strictPort: true,\n          watch: {\n            usePolling: true,\n            interval: 100,\n          },\n          host: true,\n          fs: {\n            strict: !isBuild,\n          },\n        },\n        build: {\n          target: 'esnext',\n        },\n      })\n    ).listen()\n    // use resolved port/base from server\n    const devBase = viteServer.config.base === '/' ? '' : viteServer.config.base\n    setViteUrl(`http://localhost:${port}${devBase}`)\n    await page.goto(viteTestUrl)\n\n    return viteServer\n  } else {\n    const { build } = await import('vite')\n    await build({\n      root: rootDir,\n      logLevel: 'silent',\n      configFile: path.resolve(dirname, '../vite.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.dyimport.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.multiple-output.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.nominify.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.helpers-injection.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.named-exports.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.css-single-entry.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.css-multi-entry.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.css-code-split.config.js'),\n    })\n\n    await build({\n      root: rootDir,\n      logLevel: 'warn', // output esbuild warns\n      configFile: path.resolve(dirname, '../vite.terser.config.js'),\n    })\n\n    // start static file server\n    const serve = sirv(path.resolve(rootDir, 'dist'))\n    const httpServer = http.createServer((req, res) => {\n      if (req.url === '/ping') {\n        res.statusCode = 200\n        res.end('pong')\n      } else {\n        serve(req, res)\n      }\n    })\n\n    return new Promise((resolve, reject) => {\n      try {\n        const server = httpServer.listen(port, async () => {\n          await page.goto(`http://localhost:${port}`)\n          resolve({\n            // for test teardown\n            async close() {\n              await new Promise((resolve) => {\n                server.close(resolve)\n              })\n            },\n          })\n        })\n      } catch (e) {\n        reject(e)\n      }\n    })\n  }\n}\n\nfunction setupConsoleWarnCollector() {\n  const warn = console.warn\n  console.warn = (...args) => {\n    serverLogs.push(args.join(' '))\n    return warn.call(console, ...args)\n  }\n}\n"
  },
  {
    "path": "playground/lib/index.dist.html",
    "content": "<!-- the production demo page, copied into dist/ -->\n<div class=\"es\"></div>\n<div class=\"umd\"></div>\n<div class=\"iife\"></div>\n<div class=\"dynamic-import-message\"></div>\n\n<script>\n  // shim test preserve process.env.NODE_ENV\n  globalThis.process = {\n    env: {\n      NODE_ENV: 'production',\n    },\n  }\n</script>\n\n<script type=\"module\">\n  import myLib from './my-lib-custom-filename.js'\n\n  myLib('.es')\n</script>\n\n<script type=\"module\">\n  import message from './lib/dynamic-import-message.es.mjs'\n\n  message('.dynamic-import-message')\n</script>\n\n<script src=\"./my-lib-custom-filename.umd.cjs\"></script>\n<script>\n  MyLib('.umd')\n  delete window.MyLib // so that it won't affect iife\n</script>\n\n<script src=\"./my-lib-custom-filename.iife.js\"></script>\n<script>\n  MyLib('.iife')\n</script>\n"
  },
  {
    "path": "playground/lib/index.html",
    "content": "<!-- the development demo page -->\n\n<div class=\"demo\"></div>\n\n<script type=\"module\">\n  import myLib from './src/main.js'\n\n  myLib('.demo')\n</script>\n"
  },
  {
    "path": "playground/lib/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-my-lib\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"sirv\": \"^3.0.2\"\n  }\n}\n"
  },
  {
    "path": "playground/lib/src/css-entry-1.js",
    "content": "import './entry-1.css'\n\nexport default 'css-entry-1'\n"
  },
  {
    "path": "playground/lib/src/css-entry-2.js",
    "content": "import './entry-2.css'\n\nexport default 'css-entry-2'\n"
  },
  {
    "path": "playground/lib/src/dynamic.css",
    "content": "@import 'https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.min.css';\n.dynamic {\n  color: red;\n}\n"
  },
  {
    "path": "playground/lib/src/entry-1.css",
    "content": "h1 {\n  content: 'entry-1.css';\n}\n"
  },
  {
    "path": "playground/lib/src/entry-2.css",
    "content": "h2 {\n  content: 'entry-2.css';\n}\n"
  },
  {
    "path": "playground/lib/src/index.css",
    "content": ".index {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/lib/src/main-helpers-injection.js",
    "content": "// Trigger wrong helpers injection if not properly constrained\n;(function () {\n  var getEvalledConstructor = function (expressionSyntax) {\n    try {\n      return $Function(\n        '\"use strict\"; return (' + expressionSyntax + ').constructor;',\n      )()\n    } catch (e) {}\n  }\n  console.log(getEvalledConstructor(0))\n})()\n"
  },
  {
    "path": "playground/lib/src/main-multiple-output.js",
    "content": "// import file to test css build handling\nimport './index.css'\n\nexport default async function message(sel) {\n  document.querySelector(sel).textContent = 'success'\n}\n"
  },
  {
    "path": "playground/lib/src/main-named.js",
    "content": "export const foo = 'foo'\n\n// Force esbuild spread helpers\nconsole.log({ ...foo })\n"
  },
  {
    "path": "playground/lib/src/main.js",
    "content": "export default /* @__PURE__ */ Object.assign(function myLib(sel) {\n  // Force esbuild spread helpers (https://github.com/evanw/esbuild/issues/951)\n  console.log({ ...'foo' })\n\n  document.querySelector(sel).textContent = 'It works'\n\n  // Env vars should not be replaced\n  console.log(process.env.NODE_ENV)\n\n  // make sure umd helper has been moved to the right position\n  console.log(`amd function(){ \"use strict\"; }`)\n\n  // eslint-disable-next-line no-debugger\n  debugger\n})\n\n// For triggering unhandled global esbuild helpers in previous regex-based implementation for injection\n;(function () {})()?.foo\n"
  },
  {
    "path": "playground/lib/src/main2.js",
    "content": "import './index.css'\n\nexport default async function message(sel) {\n  const message = await import('./message.js')\n\n  await import('./dynamic.css')\n\n  document.querySelector(sel).textContent = message.default\n}\n"
  },
  {
    "path": "playground/lib/src/message.js",
    "content": "export default 'hello vite'\n"
  },
  {
    "path": "playground/lib/src/sub-multiple-output.js",
    "content": "// import file to test css build handling\nimport './index.css'\n\nexport default async function message(sel) {\n  document.querySelector(sel).textContent = 'success'\n}\n"
  },
  {
    "path": "playground/lib/vite.config.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  esbuild: {\n    supported: {\n      // Force esbuild inject helpers to test regex\n      'object-rest-spread': false,\n      'optional-chain': false,\n    },\n  },\n  build: {\n    // Force oxc inject helpers to test regex\n    // - object rest spread\n    // - optional chaining\n    target: 'chrome46',\n    rollupOptions: {\n      output: {\n        comments: { legal: true },\n        banner: `/*!\\nMayLib\\n*/`,\n      },\n    },\n    lib: {\n      entry: path.resolve(import.meta.dirname, 'src/main.js'),\n      name: 'MyLib',\n      formats: ['es', 'umd', 'iife'],\n      fileName: 'my-lib-custom-filename',\n    },\n  },\n  plugins: [\n    {\n      name: 'emit-index',\n      generateBundle() {\n        this.emitFile({\n          type: 'asset',\n          fileName: 'index.html',\n          source: fs.readFileSync(\n            path.resolve(import.meta.dirname, 'index.dist.html'),\n            'utf-8',\n          ),\n        })\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/lib/vite.css-code-split.config.js",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    cssCodeSplit: true,\n    lib: {\n      entry: [\n        fileURLToPath(new URL('src/css-entry-1.js', import.meta.url)),\n        fileURLToPath(new URL('src/css-entry-2.js', import.meta.url)),\n      ],\n      name: 'css-code-split',\n    },\n    outDir: 'dist/css-code-split',\n  },\n})\n"
  },
  {
    "path": "playground/lib/vite.css-multi-entry.config.js",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: [\n        fileURLToPath(new URL('src/css-entry-1.js', import.meta.url)),\n        fileURLToPath(new URL('src/css-entry-2.js', import.meta.url)),\n      ],\n      name: 'css-multi-entry',\n    },\n    outDir: 'dist/css-multi-entry',\n  },\n})\n"
  },
  {
    "path": "playground/lib/vite.css-single-entry.config.js",
    "content": "import { fileURLToPath } from 'node:url'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: fileURLToPath(new URL('src/css-entry-1.js', import.meta.url)),\n      name: 'css-single-entry',\n    },\n    outDir: 'dist/css-single-entry',\n  },\n})\n"
  },
  {
    "path": "playground/lib/vite.dyimport.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: path.resolve(import.meta.dirname, 'src/main2.js'),\n      formats: ['es', 'iife'],\n      name: 'message',\n      fileName: (format) => `dynamic-import-message.${format}.mjs`,\n    },\n    outDir: 'dist/lib',\n  },\n  cacheDir: 'node_modules/.vite-dyimport',\n})\n"
  },
  {
    "path": "playground/lib/vite.helpers-injection.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\n// Check that helpers injection is properly constrained\n\nexport default defineConfig({\n  build: {\n    lib: {\n      entry: path.resolve(import.meta.dirname, 'src/main-helpers-injection.js'),\n      name: 'MyLib',\n      formats: ['iife'],\n      fileName: 'my-lib-custom-filename',\n    },\n    minify: false,\n    outDir: 'dist/helpers-injection',\n  },\n  plugins: [],\n  cacheDir: 'node_modules/.vite-helpers-injection',\n})\n"
  },
  {
    "path": "playground/lib/vite.multiple-output.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst root = process.env.VITEST\n  ? path.resolve(import.meta.dirname, '../../playground-temp/lib')\n  : import.meta.dirname\n\nexport default defineConfig({\n  build: {\n    lib: {\n      // set multiple entrypoint to trigger css chunking\n      entry: {\n        main: path.resolve(import.meta.dirname, 'src/main-multiple-output.js'),\n        sub: path.resolve(import.meta.dirname, 'src/sub-multiple-output.js'),\n      },\n      name: 'MyLib',\n    },\n    outDir: 'dist/multiple-output',\n    rollupOptions: {\n      // due to playground-temp, the `dir` needs to be relative to the resolvedRoot\n      output: [\n        {\n          dir: path.resolve(root, 'dist/multiple-output/es'),\n          format: 'es',\n          entryFileNames: 'index.mjs',\n          assetFileNames: 'assets/mylib.css',\n        },\n        {\n          dir: path.resolve(root, 'dist/multiple-output/cjs'),\n          format: 'cjs',\n          entryFileNames: 'index.cjs',\n          assetFileNames: 'assets/mylib.css',\n        },\n      ],\n    },\n    cssCodeSplit: true,\n  },\n  cacheDir: 'node_modules/.vite-multiple-output',\n})\n"
  },
  {
    "path": "playground/lib/vite.named-exports.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nexport default defineConfig({\n  esbuild: {\n    supported: {\n      // Force esbuild inject helpers to test regex\n      'object-rest-spread': false,\n    },\n  },\n  build: {\n    lib: {\n      entry: path.resolve(import.meta.dirname, 'src/main-named.js'),\n      name: 'MyLibNamed',\n      formats: ['umd', 'iife'],\n      fileName: 'my-lib-named',\n    },\n    outDir: 'dist/named',\n  },\n})\n"
  },
  {
    "path": "playground/lib/vite.nominify.config.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config'\n\nexport default defineConfig({\n  ...baseConfig,\n  build: {\n    ...baseConfig.build,\n    minify: false,\n    outDir: 'dist/nominify',\n  },\n  plugins: [],\n  cacheDir: 'node_modules/.vite-nominify',\n})\n"
  },
  {
    "path": "playground/lib/vite.terser.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\nimport baseConfig from './vite.config'\n\nexport default defineConfig({\n  ...baseConfig,\n  build: {\n    ...baseConfig.build,\n    minify: 'terser',\n    terserOptions: {\n      compress: {\n        drop_debugger: true,\n      },\n    },\n    outDir: 'dist/terser',\n    lib: {\n      ...baseConfig.build.lib,\n      entry: path.resolve(import.meta.dirname, 'src/main.js'),\n      formats: ['es', 'iife'],\n    },\n  },\n  plugins: [],\n  cacheDir: 'node_modules/.vite-terser',\n})\n"
  },
  {
    "path": "playground/minify/__tests__/minify.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { expect, test } from 'vitest'\nimport { isBuild, readFile, testDir } from '~utils'\n\ntest.runIf(isBuild)('no minifySyntax', () => {\n  const assetsDir = path.resolve(testDir, 'dist/assets')\n  const files = fs.readdirSync(assetsDir)\n\n  const jsFile = files.find((f) => f.endsWith('.js'))\n  const jsContent = readFile(path.resolve(assetsDir, jsFile))\n\n  const cssFile = files.find((f) => f.endsWith('.css'))\n  const cssContent = readFile(path.resolve(assetsDir, cssFile))\n\n  expect(jsContent).toContain('console.log(\"hello world\")')\n  expect(jsContent).not.toContain('/*! explicit comment */')\n\n  expect(cssContent).toContain('color:#ff0000')\n  expect(cssContent).not.toContain('/*! explicit comment */')\n})\n"
  },
  {
    "path": "playground/minify/dir/module/index.css",
    "content": "/*! explicit comment */\nh2 {\n  color: #ff00ff;\n}\n"
  },
  {
    "path": "playground/minify/dir/module/index.js",
    "content": "/*! explicit comment */\nexport const msg = `[success] minified module`\n"
  },
  {
    "path": "playground/minify/dir/module/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-minify\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/minify/index.html",
    "content": "<h1>Minify</h1>\n\n<script type=\"module\" src=\"./main.js\"></script>\n"
  },
  {
    "path": "playground/minify/main.js",
    "content": "import './test.css'\nimport { msg } from 'minified-module'\n\nconsole.log(msg)\n\nif (window) {\n  console.log('hello world')\n}\n"
  },
  {
    "path": "playground/minify/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-minify\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"minified-module\": \"file:./dir/module\"\n  }\n}\n"
  },
  {
    "path": "playground/minify/test.css",
    "content": "@import 'minified-module/index.css';\n\nh1 {\n  /* do not minify as red text */\n  color: #ff0000;\n}\n"
  },
  {
    "path": "playground/minify/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  esbuild: {\n    legalComments: 'none',\n    minifySyntax: false,\n  },\n  build: {\n    minify: 'esbuild',\n    cssMinify: 'esbuild',\n  },\n})\n"
  },
  {
    "path": "playground/module-graph/__tests__/module-graph.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isServe, page, viteServer } from '~utils'\n\ntest.runIf(isServe)('importedUrls order is preserved', async () => {\n  const el = page.locator('.imported-urls-order')\n  expect(await el.textContent()).toBe('[success]')\n  const mod = await viteServer.environments.client.moduleGraph.getModuleByUrl(\n    '/imported-urls-order.js',\n  )\n  const importedModuleIds = [...mod.importedModules].map((m) => m.url)\n  expect(importedModuleIds).toEqual(['\\x00virtual:slow-module', '/empty.js'])\n})\n"
  },
  {
    "path": "playground/module-graph/empty.js",
    "content": ""
  },
  {
    "path": "playground/module-graph/imported-urls-order.js",
    "content": "import { msg } from 'virtual:slow-module'\nimport './empty.js'\n\nexport default msg\n\n// This module tests that the import order is preserved in this module's `importedUrls` property\n// as the imports can be processed in parallel\n"
  },
  {
    "path": "playground/module-graph/index.html",
    "content": "<div class=\"imported-urls-order\"></div>\n\n<script type=\"module\">\n  import importedUrlsOrderSuccess from './imported-urls-order'\n  text('.imported-urls-order', importedUrlsOrderSuccess)\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/module-graph/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-hmr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/module-graph/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport type { Plugin } from 'vite'\n\nexport default defineConfig({\n  plugins: [slowModulePlugin()],\n})\n\nfunction slowModulePlugin(): Plugin {\n  return {\n    name: 'slow-module',\n    resolveId(id) {\n      if (id === 'virtual:slow-module') {\n        return '\\0virtual:slow-module'\n      }\n    },\n    async load(id) {\n      if (id === '\\0virtual:slow-module') {\n        await new Promise((resolve) => setTimeout(resolve, 500))\n        return `export const msg = '[success]'`\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/__tests__/multiple-entrypoints.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { getColor, page } from '~utils'\n\ntest('should have css applied on second dynamic import', async () => {\n  await expect.poll(() => page.textContent('.content')).toMatch('Initial')\n  await page.click('.b')\n\n  await expect.poll(() => page.textContent('.content')).toMatch('Reference')\n  expect(await getColor('.content')).toBe('red')\n})\n"
  },
  {
    "path": "playground/multiple-entrypoints/deps.json",
    "content": "{\n  \"a0\": \"./a0.js\",\n  \"a1\": \"./a1.js\",\n  \"a2\": \"./a2.js\",\n  \"a3\": \"./a3.js\",\n  \"a4\": \"./a4.js\",\n  \"a5\": \"./a5.js\",\n  \"a6\": \"./a6.js\",\n  \"a7\": \"./a7.js\",\n  \"a8\": \"./a8.js\",\n  \"a9\": \"./a9.js\",\n  \"a10\": \"./a10.js\",\n  \"a11\": \"./a11.js\",\n  \"a12\": \"./a12.js\",\n  \"a13\": \"./a13.js\",\n  \"a14\": \"./a14.js\",\n  \"a15\": \"./a15.js\",\n  \"a16\": \"./a16.js\",\n  \"a17\": \"./a17.js\",\n  \"a18\": \"./a18.js\",\n  \"a19\": \"./a19.js\",\n  \"a20\": \"./a20.js\",\n  \"a21\": \"./a21.js\",\n  \"a22\": \"./a22.js\",\n  \"a23\": \"./a23.js\",\n  \"a24\": \"./a24.js\"\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/dynamic-a.js",
    "content": "import './reference'\n"
  },
  {
    "path": "playground/multiple-entrypoints/dynamic-b.js",
    "content": "import './reference'\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a0.js",
    "content": "import a1 from './a1'\nimport a2 from './a2'\nimport a3 from './a3'\nimport a4 from './a4'\nimport a5 from './a5'\nimport a6 from './a6'\nimport a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport function other() {\n  return (\n    a1() +\n    a2() +\n    a3() +\n    a4() +\n    a5() +\n    a6() +\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a1.js",
    "content": "import a2 from './a2'\nimport a3 from './a3'\nimport a4 from './a4'\nimport a5 from './a5'\nimport a6 from './a6'\nimport a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a0.js')\n\nexport function other() {\n  return (\n    a2() +\n    a3() +\n    a4() +\n    a5() +\n    a6() +\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a10.js",
    "content": "import a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a9.js')\n\nexport function other() {\n  return (\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a11.js",
    "content": "import a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a10.js')\n\nexport function other() {\n  return (\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a12.js",
    "content": "import a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a11.js')\n\nexport function other() {\n  return (\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a13.js",
    "content": "import a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a12.js')\n\nexport function other() {\n  return (\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a14.js",
    "content": "import a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a13.js')\n\nexport function other() {\n  return (\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a15.js",
    "content": "import a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a14.js')\n\nexport function other() {\n  return a16() + a17() + a18() + a19() + a20() + a21() + a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a16.js",
    "content": "import a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a15.js')\n\nexport function other() {\n  return a17() + a18() + a19() + a20() + a21() + a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a17.js",
    "content": "import a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a16.js')\n\nexport function other() {\n  return a18() + a19() + a20() + a21() + a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a18.js",
    "content": "import a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a17.js')\n\nexport function other() {\n  return a19() + a20() + a21() + a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a19.js",
    "content": "import a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a18.js')\n\nexport function other() {\n  return a20() + a21() + a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a2.js",
    "content": "import a3 from './a3'\nimport a4 from './a4'\nimport a5 from './a5'\nimport a6 from './a6'\nimport a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a1.js')\n\nexport function other() {\n  return (\n    a3() +\n    a4() +\n    a5() +\n    a6() +\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a20.js",
    "content": "import a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a19.js')\n\nexport function other() {\n  return a21() + a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a21.js",
    "content": "import a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a20.js')\n\nexport function other() {\n  return a22() + a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a22.js",
    "content": "import a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a21.js')\n\nexport function other() {\n  return a23() + a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a23.js",
    "content": "import a24 from './a24'\n\nexport const that = () => import('./a22.js')\n\nexport function other() {\n  return a24()\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a24.js",
    "content": "export const that = () => import('./a23.js')\n\nexport function other() {\n  return\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a3.js",
    "content": "import a4 from './a4'\nimport a5 from './a5'\nimport a6 from './a6'\nimport a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a2.js')\n\nexport function other() {\n  return (\n    a4() +\n    a5() +\n    a6() +\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a4.js",
    "content": "import a5 from './a5'\nimport a6 from './a6'\nimport a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a3.js')\n\nexport function other() {\n  return (\n    a5() +\n    a6() +\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a5.js",
    "content": "import a6 from './a6'\nimport a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a4.js')\n\nexport function other() {\n  return (\n    a6() +\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a6.js",
    "content": "import a7 from './a7'\nimport a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a5.js')\n\nexport function other() {\n  return (\n    a7() +\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a7.js",
    "content": "import a8 from './a8'\nimport a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a6.js')\n\nexport function other() {\n  return (\n    a8() +\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a8.js",
    "content": "import a9 from './a9'\nimport a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a7.js')\n\nexport function other() {\n  return (\n    a9() +\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/entrypoints/a9.js",
    "content": "import a10 from './a10'\nimport a11 from './a11'\nimport a12 from './a12'\nimport a13 from './a13'\nimport a14 from './a14'\nimport a15 from './a15'\nimport a16 from './a16'\nimport a17 from './a17'\nimport a18 from './a18'\nimport a19 from './a19'\nimport a20 from './a20'\nimport a21 from './a21'\nimport a22 from './a22'\nimport a23 from './a23'\nimport a24 from './a24'\n\nexport const that = () => import('./a8.js')\n\nexport function other() {\n  return (\n    a10() +\n    a11() +\n    a12() +\n    a13() +\n    a14() +\n    a15() +\n    a16() +\n    a17() +\n    a18() +\n    a19() +\n    a20() +\n    a21() +\n    a22() +\n    a23() +\n    a24()\n  )\n}\n\nexport default function () {\n  return 123\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/index.html",
    "content": "<script type=\"module\" src=\"./index.js\"></script>\n\n<button class=\"a\">A</button>\n<button class=\"b\">B</button>\n<div class=\"content\">Initial</div>\n"
  },
  {
    "path": "playground/multiple-entrypoints/index.js",
    "content": "document\n  .querySelector('.a')\n  .addEventListener('click', () => import('./dynamic-a'))\ndocument\n  .querySelector('.b')\n  .addEventListener('click', () => import('./dynamic-b'))\n"
  },
  {
    "path": "playground/multiple-entrypoints/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-multiple-entrypoints\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"devDependencies\": {\n    \"sass\": \"^1.98.0\"\n  }\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/reference.js",
    "content": "import './reference.scss'\n\ndocument.querySelector('.content').textContent = 'Reference'\n"
  },
  {
    "path": "playground/multiple-entrypoints/reference.scss",
    "content": ".content {\n  color: red;\n}\n"
  },
  {
    "path": "playground/multiple-entrypoints/vite.config.js",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst dirname = import.meta.dirname\n\nexport default defineConfig({\n  build: {\n    outDir: './dist',\n    emptyOutDir: true,\n    rollupOptions: {\n      preserveEntrySignatures: 'strict',\n      input: {\n        a0: resolve(dirname, 'entrypoints/a0.js'),\n        a1: resolve(dirname, 'entrypoints/a1.js'),\n        a2: resolve(dirname, 'entrypoints/a2.js'),\n        a3: resolve(dirname, 'entrypoints/a3.js'),\n        a4: resolve(dirname, 'entrypoints/a4.js'),\n        a5: resolve(dirname, 'entrypoints/a5.js'),\n        a6: resolve(dirname, 'entrypoints/a6.js'),\n        a7: resolve(dirname, 'entrypoints/a7.js'),\n        a8: resolve(dirname, 'entrypoints/a8.js'),\n        a9: resolve(dirname, 'entrypoints/a9.js'),\n        a10: resolve(dirname, 'entrypoints/a10.js'),\n        a11: resolve(dirname, 'entrypoints/a11.js'),\n        a12: resolve(dirname, 'entrypoints/a12.js'),\n        a13: resolve(dirname, 'entrypoints/a13.js'),\n        a14: resolve(dirname, 'entrypoints/a14.js'),\n        a15: resolve(dirname, 'entrypoints/a15.js'),\n        a16: resolve(dirname, 'entrypoints/a16.js'),\n        a17: resolve(dirname, 'entrypoints/a17.js'),\n        a18: resolve(dirname, 'entrypoints/a18.js'),\n        a19: resolve(dirname, 'entrypoints/a19.js'),\n        a20: resolve(dirname, 'entrypoints/a20.js'),\n        a21: resolve(dirname, 'entrypoints/a21.js'),\n        a22: resolve(dirname, 'entrypoints/a22.js'),\n        a23: resolve(dirname, 'entrypoints/a23.js'),\n        a24: resolve(dirname, 'entrypoints/a24.js'),\n        index: resolve(dirname, './index.html'),\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/nested-deps/__tests__/nested-deps.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from '~utils'\n\ntest('handle nested package', async () => {\n  expect(await page.textContent('.a')).toBe('A@2.0.0')\n  expect(await page.textContent('.b')).toBe('B@1.0.0')\n  expect(await page.textContent('.nested-a')).toBe('A@1.0.0')\n  const c = await page.textContent('.c')\n  expect(c).toBe('es-C@1.0.0')\n  expect(await page.textContent('.side-c')).toBe(c)\n  expect(await page.textContent('.d')).toBe('D@1.0.0')\n  expect(await page.textContent('.nested-d')).toBe('D-nested@1.0.0')\n  expect(await page.textContent('.nested-e')).toBe('1')\n\n  expect(await page.textContent('.absolute-f')).toBe('F@2.0.0')\n  expect(await page.textContent('.self-referencing')).toBe('true')\n})\n"
  },
  {
    "path": "playground/nested-deps/index.html",
    "content": "<h2>direct dependency A</h2>\n<pre class=\"a\"></pre>\n\n<h2>direct dependency B</h2>\n<pre class=\"b\"></pre>\n\n<h2>nested dependency A</h2>\n<pre class=\"nested-a\"></pre>\n\n<h2>direct dependency C</h2>\n<pre class=\"c\"></pre>\n\n<h2>side dependency C</h2>\n<pre class=\"side-c\"></pre>\n\n<h2>direct dependency D</h2>\n<pre class=\"d\"></pre>\n\n<h2>nested dependency nested-D (dep of D)</h2>\n<pre class=\"nested-d\"></pre>\n\n<h2>exclude dependency of pre-bundled dependency</h2>\n<div>nested module instance count: <span class=\"nested-e\"></span></div>\n\n<h2>absolute dependency path: <span class=\"absolute-f\"></span></h2>\n\n<h2>self referencing</h2>\n<pre class=\"self-referencing\"></pre>\n\n<script type=\"module\">\n  import A from '@vitejs/test-package-a'\n  import B, { A as nestedA } from '@vitejs/test-package-b'\n  import C from '@vitejs/test-package-c'\n  import { C as sideC } from '@vitejs/test-package-c/side'\n  import D, { nestedD } from '@vitejs/test-package-d'\n  import { testExcluded } from '@vitejs/test-package-e'\n  import F from '__F_ABSOLUTE_PACKAGE_PATH__'\n  import { isSelfReference } from '@vitejs/self-referencing/test'\n\n  text('.a', A)\n  text('.b', B)\n  text('.nested-a', nestedA)\n\n  text('.c', C)\n  text('.side-c', sideC)\n\n  text('.d', D)\n  text('.nested-d', nestedD)\n\n  text('.nested-e', testExcluded())\n\n  text('.absolute-f', F)\n\n  text('.self-referencing', isSelfReference)\n\n  function text(sel, text) {\n    document.querySelector(sel).textContent = text\n  }\n</script>\n"
  },
  {
    "path": "playground/nested-deps/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-deps\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-package-a\": \"link:./test-package-a\",\n    \"@vitejs/test-package-b\": \"link:./test-package-b\",\n    \"@vitejs/test-package-c\": \"link:./test-package-c\",\n    \"@vitejs/test-package-d\": \"link:./test-package-d\",\n    \"@vitejs/test-package-e\": \"link:./test-package-e\",\n    \"@vitejs/test-package-f\": \"link:./test-package-f\",\n    \"@vitejs/self-referencing\": \"link:../self-referencing\"\n  }\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-a/index.js",
    "content": "export default 'A@2.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-a/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-a\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-b/index.js",
    "content": "export { default as A } from 'test-package-a'\n\nexport default 'B@1.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-b/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-b\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-c/index-es.js",
    "content": "export default 'es-C@1.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-c/index.js",
    "content": "// this module should not be resolved\nexport default 'C@1.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-c/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-c\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"module\": \"index-es.js\"\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-c/side.js",
    "content": "export { default as C } from '@vitejs/test-package-c'\n"
  },
  {
    "path": "playground/nested-deps/test-package-d/index.js",
    "content": "export { default as nestedD } from '@vitejs/test-package-d-nested'\n\nexport default 'D@1.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-d/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-d\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-package-d-nested\": \"link:./test-package-d-nested\"\n  }\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-d/test-package-d-nested/index.js",
    "content": "export default 'D-nested@1.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-d/test-package-d-nested/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-d-nested\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-e/index.js",
    "content": "export { testIncluded } from '@vitejs/test-package-e-included'\nexport { testExcluded } from '@vitejs/test-package-e-excluded'\n"
  },
  {
    "path": "playground/nested-deps/test-package-e/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-e\",\n  \"private\": true,\n  \"version\": \"0.1.0\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-package-e-excluded\": \"link:./test-package-e-excluded\",\n    \"@vitejs/test-package-e-included\": \"link:./test-package-e-included\"\n  }\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-e/test-package-e-excluded/index.js",
    "content": "const key = '$$excludedDependencyInstanceCount'\n\nif (!(key in window)) {\n  window[key] = 0\n}\n\n++window[key]\n\nexport function testExcluded() {\n  return window[key]\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-e/test-package-e-excluded/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-e-excluded\",\n  \"private\": true,\n  \"version\": \"0.1.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-e/test-package-e-included/index.js",
    "content": "import { testExcluded } from '@vitejs/test-package-e-excluded'\n\nexport function testIncluded() {\n  return testExcluded()\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-e/test-package-e-included/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-e-included\",\n  \"private\": true,\n  \"version\": \"0.1.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-package-e-excluded\": \"link:../test-package-e-excluded\"\n  }\n}\n"
  },
  {
    "path": "playground/nested-deps/test-package-f/index.js",
    "content": "export default 'F@2.0.0'\n"
  },
  {
    "path": "playground/nested-deps/test-package-f/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-package-f\",\n  \"private\": true,\n  \"version\": \"2.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/nested-deps/vite.config.js",
    "content": "import path from 'node:path'\nimport { defineConfig } from 'vite'\n\nconst packageFPath = path.resolve(import.meta.dirname, 'test-package-f')\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      __F_ABSOLUTE_PACKAGE_PATH__: packageFPath,\n    },\n  },\n  optimizeDeps: {\n    include: [\n      '@vitejs/test-package-a',\n      '@vitejs/test-package-b',\n      '@vitejs/test-package-c',\n      '@vitejs/test-package-c/side',\n      '@vitejs/test-package-d    > @vitejs/test-package-d-nested',\n      '@vitejs/test-package-e > @vitejs/test-package-e-included',\n      '@vitejs/test-package-f',\n    ],\n    exclude: ['@vitejs/test-package-d', '@vitejs/test-package-e-excluded'],\n  },\n})\n"
  },
  {
    "path": "playground/object-hooks/__tests__/object-hooks.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from '~utils'\n\ntest('object hooks', async () => {\n  expect(await page.textContent('#transform')).toMatch('ok')\n})\n"
  },
  {
    "path": "playground/object-hooks/index.html",
    "content": "<h3>Transform Hook order</h3>\n<div id=\"transform\"></div>\n\n<script type=\"module\" src=\"./main.ts\"></script>\n"
  },
  {
    "path": "playground/object-hooks/main.ts",
    "content": "const app = document.getElementById('transform')\napp.innerText = '__TRANSFORM__'\n"
  },
  {
    "path": "playground/object-hooks/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-object-hooks\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/object-hooks/vite.config.ts",
    "content": "/* eslint-disable n/prefer-node-protocol */\nimport assert from 'assert'\nimport { defineConfig } from 'vite'\n\nlet count = 0\nexport default defineConfig({\n  plugins: [\n    {\n      name: 'plugin1',\n      buildStart: {\n        async handler() {\n          await new Promise((r) => setTimeout(r, 100))\n          count += 1\n        },\n      },\n      transform: {\n        order: 'post',\n        handler(code) {\n          return code.replace('__TRANSFORM3__', 'ok')\n        },\n      },\n    },\n    {\n      name: 'plugin2',\n      buildStart: {\n        sequential: true,\n        async handler() {\n          assert(count === 1)\n          await new Promise((r) => setTimeout(r, 100))\n          count += 1\n        },\n      },\n      transform: {\n        handler(code) {\n          return code.replace('__TRANSFORM1__', '__TRANSFORM2__')\n        },\n      },\n    },\n    {\n      name: 'plugin3',\n      buildStart: {\n        async handler() {\n          assert(count === 2)\n          await new Promise((r) => setTimeout(r, 100))\n          count += 1\n        },\n      },\n      transform: {\n        order: 'pre',\n        handler(code) {\n          return code.replace('__TRANSFORM__', '__TRANSFORM1__')\n        },\n      },\n    },\n    {\n      name: 'plugin4',\n      buildStart: {\n        async handler() {\n          assert(count === 2)\n        },\n      },\n      transform: {\n        handler(code) {\n          return code.replace('__TRANSFORM2__', '__TRANSFORM3__')\n        },\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/optimize-deps/.hidden-dir/foo.js",
    "content": "export const greeting = 'hello!'\n"
  },
  {
    "path": "playground/optimize-deps/__tests__/optimize-deps.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport {\n  browserErrors,\n  browserLogs,\n  getColor,\n  isBuild,\n  isServe,\n  page,\n  readDepOptimizationMetadata,\n  serverLogs,\n  viteTestUrl,\n} from '~utils'\n\ntest('default + named imports from cjs dep (react)', async () => {\n  await expect.poll(() => page.textContent('.cjs button')).toBe('count is 0')\n  await page.click('.cjs button')\n  await expect.poll(() => page.textContent('.cjs button')).toBe('count is 1')\n})\n\ntest('named imports from webpacked cjs (phoenix)', async () => {\n  await expect.poll(() => page.textContent('.cjs-phoenix')).toBe('ok')\n})\n\ntest('default import from webpacked cjs (clipboard)', async () => {\n  await expect.poll(() => page.textContent('.cjs-clipboard')).toBe('ok')\n})\n\ntest('default import from cjs with es-module-flag (dep-cjs-with-es-module-flag)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-with-es-module-flag'))\n    .toBe('ok')\n})\n\ntest('default import from cjs (cjs-dep-cjs-compiled-from-esm)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-dep-cjs-compiled-from-esm'))\n    .toBe('ok')\n})\n\ntest('default import from cjs (cjs-dep-cjs-compiled-from-cjs)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-dep-cjs-compiled-from-cjs'))\n    .toBe('ok')\n})\n\ntest('dynamic imports from cjs dep (react)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-dynamic button'))\n    .toBe('count is 0')\n  await page.click('.cjs-dynamic button')\n  await expect\n    .poll(() => page.textContent('.cjs-dynamic button'))\n    .toBe('count is 1')\n})\n\ntest('dynamic named imports from webpacked cjs (phoenix)', async () => {\n  await expect.poll(() => page.textContent('.cjs-dynamic-phoenix')).toBe('ok')\n})\n\ntest('dynamic default import from webpacked cjs (clipboard)', async () => {\n  await expect.poll(() => page.textContent('.cjs-dynamic-clipboard')).toBe('ok')\n})\n\ntest('dynamic default import from cjs (cjs-dynamic-dep-cjs-compiled-from-esm)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-dynamic-dep-cjs-compiled-from-esm'))\n    .toBe('ok')\n})\n\ntest('dynamic default import from cjs (cjs-dynamic-dep-cjs-compiled-from-cjs)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-dynamic-dep-cjs-compiled-from-cjs'))\n    .toBe('ok')\n})\n\ntest('dynamic default import from cjs with es-module-flag (cjs-dynamic-dep-cjs-with-es-module-flag)', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-dynamic-dep-cjs-with-es-module-flag'))\n    .toBe('ok')\n})\n\ntest('dedupe', async () => {\n  await expect.poll(() => page.textContent('.dedupe button')).toBe('count is 0')\n  await page.click('.dedupe button')\n  await expect.poll(() => page.textContent('.dedupe button')).toBe('count is 1')\n})\n\ntest('cjs browser field (axios)', async () => {\n  await expect.poll(() => page.textContent('.cjs-browser-field')).toBe('pong')\n})\n\ntest('cjs browser field bare', async () => {\n  await expect\n    .poll(() => page.textContent('.cjs-browser-field-bare'))\n    .toBe('pong')\n})\n\ntest('dep from linked dep (lodash-es)', async () => {\n  await expect.poll(() => page.textContent('.deps-linked')).toBe('fooBarBaz')\n})\n\ntest('forced include', async () => {\n  await expect\n    .poll(() => page.textContent('.force-include'))\n    .toMatch(`[success]`)\n})\n\ntest('import * from optimized dep', async () => {\n  await expect.poll(() => page.textContent('.import-star')).toMatch(`[success]`)\n})\n\ntest('import from dep with process.env.NODE_ENV', async () => {\n  await expect\n    .poll(() => page.textContent('.node-env'))\n    .toMatch(isBuild ? 'prod' : 'dev')\n})\n\ntest('import from dep with .notjs files', async () => {\n  await expect.poll(() => page.textContent('.not-js')).toMatch(`[success]`)\n})\n\ntest('Import from dependency which uses relative path which needs to be resolved by main field', async () => {\n  await expect\n    .poll(() => page.textContent('.relative-to-main'))\n    .toMatch(`[success]`)\n})\n\ntest('dep with dynamic import', async () => {\n  await expect\n    .poll(() => page.textContent('.dep-with-dynamic-import'))\n    .toMatch(`[success]`)\n})\n\ntest('dep with optional peer dep', async () => {\n  await expect\n    .poll(() => page.textContent('.dep-with-optional-peer-dep'))\n    .toMatch(`[success]`)\n  await expect\n    .poll(() => page.textContent('.dep-with-optional-peer-dep-error'))\n    .toMatch(`[success]`)\n})\n\ntest('dep with optional peer dep submodule', async () => {\n  await expect\n    .poll(() => page.textContent('.dep-with-optional-peer-dep-submodule'))\n    .toMatch(`[success]`)\n  await expect\n    .poll(() => page.textContent('.dep-with-optional-peer-dep-submodule-error'))\n    .toMatch(`[success]`)\n})\n\ntest('dep with optional peer dep (cjs)', async () => {\n  await expect\n    .poll(() => page.textContent('.dep-with-optional-peer-dep-cjs'))\n    .toMatch(`[success]`)\n  await expect\n    .poll(() => page.textContent('.dep-with-optional-peer-dep-cjs-error'))\n    .toMatch(`[success]`)\n})\n\ntest('dep with css import', async () => {\n  await expect.poll(() => getColor('.dep-linked-include')).toBe('red')\n})\n\ntest('CJS dep with css import', async () => {\n  await expect.poll(() => getColor('.cjs-with-assets')).toBe('blue')\n})\n\ntest('CJS dep requiring dep with css main field', async () => {\n  await expect.poll(() => getColor('.cjs-require-css-main-field')).toBe('coral')\n})\n\ntest('externalize known non-js files in optimize included dep', async () => {\n  await expect\n    .poll(() => page.textContent('.externalize-known-non-js'))\n    .toMatch(`[success]`)\n})\n\ntest('vue + vuex', async () => {\n  await expect.poll(() => page.textContent('.vue')).toMatch(`[success]`)\n})\n\n// When we use the Rollup CommonJS plugin instead of esbuild prebundling,\n// the esbuild plugins won't apply to dependencies\ntest.runIf(isServe)('esbuild-plugin', async () => {\n  await expect\n    .poll(() => page.textContent('.esbuild-plugin'))\n    .toMatch(`Hello from an esbuild plugin`)\n})\n\ntest('import from hidden dir', async () => {\n  await expect.poll(() => page.textContent('.hidden-dir')).toBe('hello!')\n})\n\ntest('import optimize-excluded package that imports optimized-included package', async () => {\n  await expect\n    .poll(() => page.textContent('.nested-include'))\n    .toBe('nested-include')\n})\n\ntest('import aliased package with colon', async () => {\n  await expect.poll(() => page.textContent('.url')).toBe('vite.dev')\n})\n\ntest('import aliased package using absolute path', async () => {\n  await expect\n    .poll(() => page.textContent('.alias-using-absolute-path'))\n    .toBe('From dep-alias-using-absolute-path')\n})\n\ntest('variable names are reused in different scripts', async () => {\n  await expect\n    .poll(() => page.textContent('.reused-variable-names'))\n    .toBe('reused')\n})\n\ntest('flatten id should generate correctly', async () => {\n  await expect\n    .poll(() => page.textContent('.clonedeep-slash'))\n    .toBe('clonedeep-slash')\n  await expect\n    .poll(() => page.textContent('.clonedeep-dot'))\n    .toBe('clonedeep-dot')\n  await expect\n    .poll(() => page.textContent('.dep-with-plus-subpath'))\n    .toBe('plus-subpath')\n})\n\ntest('non optimized module is not duplicated', async () => {\n  await expect\n    .poll(() => page.textContent('.non-optimized-module-is-not-duplicated'))\n    .toBe('from-absolute-path, from-relative-path')\n})\n\ntest.runIf(isServe)('error on builtin modules usage', () => {\n  expect(browserLogs).toEqual(\n    expect.arrayContaining([\n      // from dep-with-builtin-module-esm\n      expect.stringMatching(/dep-with-builtin-module-esm.*is not a function/),\n      // dep-with-builtin-module-esm warnings\n      expect.stringContaining(\n        'Module \"fs\" has been externalized for browser compatibility. Cannot access \"fs.readFileSync\" in client code.',\n      ),\n      expect.stringContaining(\n        'Module \"path\" has been externalized for browser compatibility. Cannot access \"path.join\" in client code.',\n      ),\n      // from dep-with-builtin-module-cjs\n      expect.stringMatching(/dep-with-builtin-module-cjs.*is not a function/),\n      // dep-with-builtin-module-cjs warnings\n      expect.stringContaining(\n        'Module \"fs\" has been externalized for browser compatibility. Cannot access \"fs.readFileSync\" in client code.',\n      ),\n      expect.stringContaining(\n        'Module \"path\" has been externalized for browser compatibility. Cannot access \"path.join\" in client code.',\n      ),\n    ]),\n  )\n\n  expect(browserErrors.map((error) => error.message)).toEqual(\n    expect.arrayContaining([\n      // from user source code\n      expect.stringContaining(\n        'Module \"buffer\" has been externalized for browser compatibility. Cannot access \"buffer.Buffer\" in client code.',\n      ),\n      expect.stringContaining(\n        'Module \"child_process\" has been externalized for browser compatibility. Cannot access \"child_process.execSync\" in client code.',\n      ),\n    ]),\n  )\n})\n\ntest('pre bundle css require', async () => {\n  if (isServe) {\n    const response = page.waitForResponse(/@vitejs_test-dep-css-require\\.js/)\n    await page.goto(viteTestUrl)\n    const content = await (await response).text()\n    expect(content).toMatch(\n      /import\\s\"\\/@fs.+@vitejs\\/test-dep-css-require\\/style\\.css\"/,\n    )\n  }\n\n  await expect.poll(() => getColor('.css-require')).toBe('red')\n  await expect.poll(() => getColor('.css-module-require')).toBe('red')\n})\n\ntest.runIf(isBuild)('no missing deps during build', async () => {\n  serverLogs.forEach((log) => {\n    // no warning from esbuild css minifier\n    expect(log).not.toMatch('Missing dependency found after crawling ended')\n  })\n})\n\ntest('name file limit is 170 characters', async () => {\n  if (isServe) {\n    const response = page.waitForResponse(\n      /@vitejs_longfilename-\\w+_[a-zA-Z\\d]+\\.js\\?v=[a-zA-Z\\d]+/,\n    )\n    await page.goto(viteTestUrl)\n    const content = await response\n\n    const fromUrl = content.url()\n    const stripFolderPart = fromUrl.split('/').at(-1)\n    const onlyTheFilePart = stripFolderPart.split('.')[0]\n    expect(onlyTheFilePart).toHaveLength(170)\n  }\n})\n\ndescribe.runIf(isServe)('optimizeDeps config', () => {\n  test('supports include glob syntax', () => {\n    const metadata = readDepOptimizationMetadata()\n    expect(Object.keys(metadata.optimized)).to.include.members([\n      '@vitejs/test-dep-optimize-exports-with-glob',\n      '@vitejs/test-dep-optimize-exports-with-glob/named',\n      '@vitejs/test-dep-optimize-exports-with-glob/glob-dir/foo',\n      '@vitejs/test-dep-optimize-exports-with-glob/glob-dir/bar',\n      '@vitejs/test-dep-optimize-exports-with-glob/glob-dir/nested/baz',\n      '@vitejs/test-dep-optimize-exports-with-root-glob',\n      '@vitejs/test-dep-optimize-exports-with-root-glob/file1.js',\n      '@vitejs/test-dep-optimize-exports-with-root-glob/index.js',\n      '@vitejs/test-dep-optimize-exports-with-root-glob/dir/file2.js',\n      '@vitejs/test-dep-optimize-with-glob',\n      '@vitejs/test-dep-optimize-with-glob/index.js',\n      '@vitejs/test-dep-optimize-with-glob/named.js',\n      '@vitejs/test-dep-optimize-with-glob/glob/foo.js',\n      '@vitejs/test-dep-optimize-with-glob/glob/bar.js',\n      '@vitejs/test-dep-optimize-with-glob/glob/nested/baz.js',\n    ])\n  })\n})\n\ntest('long file name should work', async () => {\n  await expect\n    .poll(() => page.textContent('.long-file-name'))\n    .toMatch(`hello world`)\n})\n\ntest.runIf(isServe)('warn on incompatible dependency', () => {\n  expect(serverLogs).toContainEqual(\n    expect.stringContaining(\n      'The dependency might be incompatible with the dep optimizer.',\n    ),\n  )\n})\n\ntest('import the CommonJS external package that omits the js suffix', async () => {\n  await expect.poll(() => page.textContent('.external-package-js')).toBe('okay')\n  await expect\n    .poll(() => page.textContent('.external-package-scss-js'))\n    .toBe('scss')\n  await expect\n    .poll(() => page.textContent('.external-package-astro-js'))\n    .toBe('astro')\n  await expect\n    .poll(() => page.textContent('.external-package-tsx-js'))\n    .toBe('tsx')\n})\n\ntest('external package name with asset extension', async () => {\n  await expect\n    .poll(() => page.textContent('.dep-with-asset-ext-no-dual-package'))\n    .toBe('true')\n  await expect\n    .poll(() => page.textContent('.dep-with-asset-ext-prebundled'))\n    .toBe(String(isServe))\n})\n\ntest('dependency with external sub-dependencies', async () => {\n  await expect\n    .poll(() => page.textContent('.dep-cjs-with-external-deps-object'))\n    .toBe('ok')\n  await expect\n    .poll(() => page.textContent('.dep-cjs-with-external-deps-node-builtin'))\n    .toBe('foo bar')\n})\n\ntest('virtual module with .vue extension does not error during scan', async () => {\n  await expect.poll(() => page.textContent('.virtual-module-vue')).toBe('ok')\n})\n\ntest.runIf(isServe)(\n  'no dep scan error for virtual modules with html-like extensions',\n  () => {\n    // Check that there are no errors related to virtual modules during dep scan\n    const scanErrors = serverLogs.filter(\n      (log) =>\n        log.includes('Failed to scan for dependencies') &&\n        log.includes('virtual:'),\n    )\n    expect(scanErrors).toHaveLength(0)\n  },\n)\n\ntest('should fix relative worker paths in optimized dependencies', async () => {\n  await expect\n    .poll(() => page.textContent('.worker-lib'))\n    .toBe('worker-success')\n  await expect\n    .poll(() => page.textContent('.worker-nested'))\n    .toBe('worker-success')\n\n  const assetMatcher = isBuild\n    ? /assets\\/logo-[-\\w]+\\.png/\n    : /\\/node_modules\\/@vitejs\\/test-dep-with-assets\\/logo\\.png/\n  await expect.poll(() => page.textContent('.asset-url')).toMatch(assetMatcher)\n\n  const url = await page.textContent('.asset-url')\n  const res = await page.request.get(url)\n  expect(res.status()).toBe(200)\n})\n"
  },
  {
    "path": "playground/optimize-deps/added-in-entries/index.js",
    "content": "// written in cjs, optimization should convert this to esm\nmodule.exports = 'added-in-entries'\n"
  },
  {
    "path": "playground/optimize-deps/added-in-entries/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-added-in-entries\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/cjs-dynamic.js",
    "content": "// test dynamic import to cjs deps\n// mostly ensuring consistency between dev server behavior and build behavior\n// of @rollup/plugin-commonjs\n;(async () => {\n  const { useState } = await import('react')\n  const React = (await import('react')).default\n  const ReactDOM = await import('react-dom/client')\n\n  const clip = await import('clipboard')\n  if (typeof clip.default === 'function') {\n    text('.cjs-dynamic-clipboard', 'ok')\n  }\n\n  const { Socket } = await import('phoenix')\n  if (typeof Socket === 'function') {\n    text('.cjs-dynamic-phoenix', 'ok')\n  }\n\n  const cjsFromESM = await import('@vitejs/test-dep-cjs-compiled-from-esm')\n  if (typeof cjsFromESM.default.default === 'function') {\n    text('.cjs-dynamic-dep-cjs-compiled-from-esm', 'ok')\n  }\n\n  const cjsFromCJS = await import('@vitejs/test-dep-cjs-compiled-from-cjs')\n  if (\n    typeof cjsFromCJS.default === 'function' &&\n    typeof cjsFromCJS !== 'function' &&\n    cjsFromCJS.bar === 'bar'\n  ) {\n    text('.cjs-dynamic-dep-cjs-compiled-from-cjs', 'ok')\n  }\n\n  const cjsWithEsModuleFlag =\n    await import('@vitejs/test-dep-cjs-with-es-module-flag')\n  text(\n    '.cjs-dynamic-dep-cjs-with-es-module-flag',\n    cjsWithEsModuleFlag.default.info,\n  )\n\n  function App() {\n    const [count, setCount] = useState(0)\n\n    return React.createElement(\n      'button',\n      {\n        onClick() {\n          setCount(count + 1)\n        },\n      },\n      `count is ${count}`,\n    )\n  }\n\n  ReactDOM.createRoot(document.querySelector('.cjs-dynamic')).render(\n    React.createElement(App),\n  )\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n})()\n"
  },
  {
    "path": "playground/optimize-deps/cjs.js",
    "content": "// test importing both default and named exports from a CommonJS module\n// React is the ultimate test of this because its dynamic exports assignments\n// are not statically detectable by @rollup/plugin-commonjs.\nimport React, { useState } from 'react'\nimport ReactDOM from 'react-dom/client'\nimport { Socket } from 'phoenix'\nimport clip from 'clipboard'\nimport m from '@vitejs/test-dep-cjs-with-es-module-flag'\nimport cjsFromESM from '@vitejs/test-dep-cjs-compiled-from-esm'\nimport cjsFromCJS from '@vitejs/test-dep-cjs-compiled-from-cjs'\nimport * as cjsFromCJSNamespace from '@vitejs/test-dep-cjs-compiled-from-cjs'\n\n// Test exporting a name that was already imported\nexport { useState } from 'react'\nexport { useState as anotherNameForUseState } from 'react'\nexport { default as React } from 'react'\n\nif (typeof clip === 'function') {\n  text('.cjs-clipboard', 'ok')\n}\n\nif (typeof Socket === 'function') {\n  text('.cjs-phoenix', 'ok')\n}\n\ntext('.cjs-with-es-module-flag', m.info)\n\nif (typeof cjsFromESM.default === 'function') {\n  text('.cjs-dep-cjs-compiled-from-esm', 'ok')\n}\n\nif (\n  typeof cjsFromCJS === 'function' &&\n  typeof cjsFromCJSNamespace !== 'function' &&\n  cjsFromCJSNamespace.bar === 'bar'\n) {\n  text('.cjs-dep-cjs-compiled-from-cjs', 'ok')\n}\n\nfunction App() {\n  const [count, setCount] = useState(0)\n\n  return React.createElement(\n    'button',\n    {\n      onClick() {\n        setCount(count + 1)\n      },\n    },\n    `count is ${count}`,\n  )\n}\n\nReactDOM.createRoot(document.querySelector('.cjs')).render(\n  React.createElement(App),\n)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n"
  },
  {
    "path": "playground/optimize-deps/dedupe.js",
    "content": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\n\n// #1302: The linked package has a different version of React in its deps\n// and is itself optimized. Without `dedupe`, the linked package is optimized\n// with a separate copy of React included, and results in runtime errors.\nimport { useCount } from '@vitejs/test-dep-linked-include/index.mjs'\n\nfunction App() {\n  const [count, setCount] = useCount()\n\n  return React.createElement(\n    'button',\n    {\n      onClick() {\n        setCount(count + 1)\n      },\n    },\n    `count is ${count}`,\n  )\n}\n\nReactDOM.createRoot(document.querySelector('.dedupe')).render(\n  React.createElement(App),\n)\n"
  },
  {
    "path": "playground/optimize-deps/dep-alias-using-absolute-path/index.js",
    "content": "// Importing a shared dependency used by other modules,\n// so dependency optimizer creates a common chunk.\n// This is used to setup a test scenario, where dep scanner\n// could not determine all of the used dependencies on first\n// pass, e.g., a dependency that is aliased using an absolute\n// path, in which case it used to trigger unnecessary \"full\n// reloads\" invalidating all modules in a module graph.\nconst cloneDeep = require('lodash/cloneDeep')\n\n// no-op, using imported module for sake of completeness\nmodule.exports = cloneDeep({\n  message: 'From dep-alias-using-absolute-path',\n}).message\n"
  },
  {
    "path": "playground/optimize-deps/dep-alias-using-absolute-path/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-alias-using-absolute-path\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"lodash\": \"^4.17.23\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field/index.js",
    "content": "module.exports = require('./lib/axios')\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field/lib/adapters/http.js",
    "content": "'use strict'\n\n// This is the Node.js adapter - should not be used in browser\nmodule.exports = function httpAdapter(config) {\n  throw new Error('Node.js adapter should not be used in browser')\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field/lib/adapters/xhr.js",
    "content": "'use strict'\n\nmodule.exports = function xhrAdapter(config) {\n  return Promise.resolve({ data: 'pong' })\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field/lib/axios.js",
    "content": "'use strict'\n\nvar adapter = require('./adapters/http.js')\n\nmodule.exports = {\n  get: function (url) {\n    return adapter({ method: 'GET', url: url })\n  },\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-browser-field\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"//\": \"real world example: https://github.com/axios/axios/blob/a64050a6cfbcc708a55a7dc8030d85b1c78cdf38/package.json#L71-L73\",\n  \"main\": \"index.js\",\n  \"browser\": {\n    \"./lib/adapters/http.js\": \"./lib/adapters/xhr.js\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field-bare/events-shim.js",
    "content": "module.exports = {\n  foo: 'foo',\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field-bare/index.js",
    "content": "'use strict'\n\nconst internal = require('./internal')\n\nmodule.exports = internal\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field-bare/internal.js",
    "content": "'use strict'\n\n// eslint-disable-next-line n/prefer-node-protocol\nconst events = require('events')\n\nmodule.exports = 'foo' in events ? 'pong' : ''\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-browser-field-bare/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-browser-field-bare\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"browser\": {\n    \"events\": \"./events-shim.js\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-compiled-from-cjs/index.js",
    "content": "'use strict'\nfunction foo() {\n  return 'foo'\n}\nfoo.bar = 'bar'\nmodule.exports = foo\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-compiled-from-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-compiled-from-cjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-compiled-from-esm/index.js",
    "content": "'use strict'\nObject.defineProperty(exports, '__esModule', { value: true })\nfunction foo() {\n  return 'foo'\n}\nexports.default = foo\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-compiled-from-esm/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-compiled-from-esm\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-css-main-field/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-css-main-field\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"style.css\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-css-main-field/style.css",
    "content": ".cjs-require-css-main-field {\n  color: coral;\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-external-package-omit-js-suffix/index.js",
    "content": "const { okay } = require('./test.okay')\nconst { scss } = require('./test.scss')\nconst { astro } = require('./test.astro')\nconst { tsx } = require('./test.tsx')\n\nmodule.exports = { okay, scss, astro, tsx }\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-external-package-omit-js-suffix/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-external-package-omit-js-suffix\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-external-package-omit-js-suffix/test.astro.js",
    "content": "function astro() {\n  return 'astro'\n}\n\nmodule.exports = { astro }\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-external-package-omit-js-suffix/test.okay.js",
    "content": "function okay() {\n  return 'okay'\n}\n\nmodule.exports = { okay }\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-external-package-omit-js-suffix/test.scss.js",
    "content": "function scss() {\n  return 'scss'\n}\n\nmodule.exports = { scss }\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-external-package-omit-js-suffix/test.tsx.js",
    "content": "function tsx() {\n  return 'tsx'\n}\n\nmodule.exports = { tsx }\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-require-css-main-field/index.js",
    "content": "require('@vitejs/test-dep-cjs-css-main-field')\nexports.a = 1\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-require-css-main-field/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-require-css-main-field\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-dep-cjs-css-main-field\": \"file:../dep-cjs-css-main-field\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-assets/foo.css",
    "content": ".cjs-with-assets {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-assets/index.js",
    "content": "require('./foo.css')\n\nexports.a = 11\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-assets/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-with-assets\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-es-module-flag/index.js",
    "content": "// Test dependency for CJS with __esModule flag\nmodule.exports = {\n  __esModule: true,\n  info: 'ok',\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-es-module-flag/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-with-es-module-flag\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-external-deps/index.js",
    "content": "// `stream` is used as the package name for `@vitejs/test-dep-esm-dummy-node-builtin` so that it is treated like a Node builtin\n// eslint-disable-next-line n/prefer-node-protocol\nlet externalDummyNodeBuiltin = require('stream')\n// NOTE: plugin-commonjs adds some compat code (`requireReturnsDefault`), but rolldown doesn't\nif (process.env.NODE_ENV === 'production') {\n  const mod = externalDummyNodeBuiltin\n  externalDummyNodeBuiltin = mod.default\n  for (const key in mod) {\n    externalDummyNodeBuiltin[key] = mod[key]\n  }\n}\nconst external = require('@vitejs/test-dep-esm-external')\n// eslint-disable-next-line no-prototype-builtins\nconst externalResult = external.hasOwnProperty('foo') ? 'ok' : 'error'\nconst externalDummyNodeBuiltinResult = `${externalDummyNodeBuiltin()} ${externalDummyNodeBuiltin.bar}`\nmodule.exports = { externalResult, externalDummyNodeBuiltinResult }\n"
  },
  {
    "path": "playground/optimize-deps/dep-cjs-with-external-deps/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-cjs-with-external-deps\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-dep-esm-external\": \"file:../dep-esm-external\",\n    \"stream\": \"file:../dep-esm-dummy-node-builtin\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-css-require/index.cjs",
    "content": "require('./style.css')\n"
  },
  {
    "path": "playground/optimize-deps/dep-css-require/mod.cjs",
    "content": "const style = require('./mod.module.css')\nmodule.exports = style\n"
  },
  {
    "path": "playground/optimize-deps/dep-css-require/mod.module.css",
    "content": ".cssModuleRequire {\n  color: red;\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-css-require/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-css-require\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.cjs\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-css-require/style.css",
    "content": ".css-require {\n  color: red;\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-esbuild-plugin-transform/index.js",
    "content": "// will be replaced by an esbuild plugin\n\nexport const hello = () => `Hello from a package`\n"
  },
  {
    "path": "playground/optimize-deps/dep-esbuild-plugin-transform/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-esbuild-plugin-transform\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-esm-dummy-node-builtin/index.js",
    "content": "function foo() {\n  return 'foo'\n}\n\nfoo.bar = 'bar'\n\nexport const bar = 'bar'\n\nexport default foo\n"
  },
  {
    "path": "playground/optimize-deps/dep-esm-dummy-node-builtin/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-esm-dummy-node-builtin\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-esm-external/index.js",
    "content": "export function foo() {\n  return 'foo'\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-esm-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-esm-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-incompatible/index.js",
    "content": "const target = './sub.js'\nconst subUrl = new URL(target, import.meta.url)\n\nexport default () => import(subUrl)\n"
  },
  {
    "path": "playground/optimize-deps/dep-incompatible/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-incompatible\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-incompatible/sub.js",
    "content": "export default 'sub'\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked/index.js",
    "content": "export * from 'lodash-es'\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-linked\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"lodash-es\": \"^4.17.23\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked-include/Test.vue",
    "content": "<template>[success] rendered from Vue</template>\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked-include/foo.js",
    "content": "export const msg = '[success] linked force include'\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked-include/index.mjs",
    "content": "export { msg } from './foo.js'\n\n// test importing node built-ins\nimport fs from 'node:fs'\n\nimport { useState } from 'react'\n\nexport function useCount() {\n  return useState(0)\n}\n\n// test dep with css/asset imports\nimport './test.css'\n\nif (false) {\n  fs.readFileSync()\n} else {\n  console.log('ok')\n}\n\nexport { default as VueSFC } from './Test.vue'\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked-include/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-linked-include\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.mjs\",\n  \"dependencies\": {\n    \"react\": \"19.2.4\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-linked-include/test.css",
    "content": ".dep-linked-include {\n  color: red;\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-node-env/index.js",
    "content": "export const env = process.env.NODE_ENV === 'production' ? 'prod' : 'dev'\n"
  },
  {
    "path": "playground/optimize-deps/dep-node-env/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-node-env\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-non-optimized/index.js",
    "content": "// Scheme check that imports from different paths are resolved to the same module\nconst messages = []\nexport const add = (message) => {\n  messages.push(message)\n}\nexport const get = () => messages\n"
  },
  {
    "path": "playground/optimize-deps/dep-non-optimized/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-non-optimized\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-not-js/foo.js",
    "content": "export const foo = '[success] imported from .notjs file'\n"
  },
  {
    "path": "playground/optimize-deps/dep-not-js/index.notjs",
    "content": "<notjs>\nimport { foo } from './foo'\nexport const notjsValue = foo\n</notjs>\n"
  },
  {
    "path": "playground/optimize-deps/dep-not-js/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-not-js\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.notjs\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-glob/glob/bar.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-glob/glob/foo.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-glob/glob/nested/baz.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-glob/index.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-glob/named.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-glob/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-optimize-exports-with-glob\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./named\": \"./named.js\",\n    \"./glob-dir/*\": \"./glob/*.js\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-root-glob/dir/file2.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-root-glob/file1.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-root-glob/index.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-exports-with-root-glob/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-optimize-exports-with-root-glob\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./*\": \"./*\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-optimize-with-glob/glob/bar.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-with-glob/glob/foo.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-with-glob/glob/nested/baz.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-with-glob/index.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-with-glob/named.js",
    "content": ""
  },
  {
    "path": "playground/optimize-deps/dep-optimize-with-glob/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-optimize-with-glob\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-relative-to-main/entry.js",
    "content": "module.exports = require('./')\n"
  },
  {
    "path": "playground/optimize-deps/dep-relative-to-main/lib/main.js",
    "content": "module.exports = '[success] imported from main'\n"
  },
  {
    "path": "playground/optimize-deps/dep-relative-to-main/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-relative-to-main\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"lib/main.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-source-map-no-sources/all.js",
    "content": "export const all = 'all'\nexport { sub } from './sub.js'\n"
  },
  {
    "path": "playground/optimize-deps/dep-source-map-no-sources/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-source-map-no-sources\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./*\": \"./*\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-source-map-no-sources/sub.js",
    "content": "export const sub = 'sub'\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-asset-ext/dep1/index.mjs",
    "content": "export default { random: Math.random() }\n\nexport const isPreBundled = import.meta.url.includes('/.vite/deps/')\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-asset-ext/dep1/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-asset-ext1.pdf\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"exports\": \"./index.mjs\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-asset-ext/dep2/index.js",
    "content": "export { default } from '@vitejs/test-dep-with-asset-ext1.pdf'\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-asset-ext/dep2/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-asset-ext2.pdf\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"exports\": \"./index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-dep-with-asset-ext1.pdf\": \"file:../dep1\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-assets/index.js",
    "content": "export function urlImportWorker() {\n  const worker = new Worker(new URL('./worker.js', import.meta.url), {\n    type: 'module',\n  })\n  return new Promise((res) => {\n    worker.onmessage = (e) => res(e.data)\n  })\n}\n\nexport function getAssetUrl() {\n  return new URL('./logo.png', import.meta.url).href\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-assets/nested/index.js",
    "content": "export function urlImportWorker() {\n  // Testing the ../ path traversal\n  const worker = new Worker(new URL('../worker.js', import.meta.url), {\n    type: 'module',\n  })\n  return new Promise((res) => {\n    worker.onmessage = (e) => res(e.data)\n  })\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-assets/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-assets\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./nested\": \"./nested/index.js\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-assets/worker.js",
    "content": "self.postMessage('worker-success')\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-builtin-module-cjs/index.js",
    "content": "// no node: protocol intentionally\n// eslint-disable-next-line n/prefer-node-protocol\nconst fs = require('fs')\n// eslint-disable-next-line n/prefer-node-protocol\nconst path = require('path')\n\n// NOTE: require destructure would error immediately because of how esbuild\n// compiles it. There's no way around it as it's direct property access, which\n// triggers the Proxy get trap.\n\n// access from default import\ntry {\n  path.join()\n} catch (e) {\n  console.log('dep-with-builtin-module-cjs', e)\n}\n\n// access from function\nmodule.exports.read = () => {\n  return fs.readFileSync('test')\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-builtin-module-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-builtin-module-cjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-builtin-module-esm/index.js",
    "content": "// no node: protocol intentionally\n// eslint-disable-next-line n/prefer-node-protocol\nimport { readFileSync } from 'fs'\n// eslint-disable-next-line n/prefer-node-protocol\nimport path from 'path'\n\n// access from named import\ntry {\n  readFileSync()\n} catch (e) {\n  console.log('dep-with-builtin-module-esm', e)\n}\n\n// access from default import\ntry {\n  path.join()\n} catch (e) {\n  console.log('dep-with-builtin-module-esm', e)\n}\n\n// access from function\nexport function read() {\n  return readFileSync('test')\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-builtin-module-esm/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-builtin-module-esm\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-dynamic-import/dynamic.js",
    "content": "export const foo = '[success] dependency with dynamic import'\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-dynamic-import/index.js",
    "content": "export const lazyFoo = async function () {\n  const { foo } = await import('./dynamic.js')\n  return foo\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-dynamic-import/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-dynamic-import\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-optional-peer-dep/index.js",
    "content": "export function callItself() {\n  return '[success]'\n}\n\nexport async function callPeerDep() {\n  return await import('foobar')\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-optional-peer-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-optional-peer-dep\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\",\n  \"peerDependencies\": {\n    \"foobar\": \"0.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"foobar\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-optional-peer-dep-cjs/index.js",
    "content": "exports.callItself = function () {\n  return '[success]'\n}\n\nexports.callPeerDep = function () {\n  try {\n    return require('foobar')\n  } catch {\n    return 'fallback'\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-optional-peer-dep-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-optional-peer-dep-cjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"peerDependencies\": {\n    \"foobar\": \"0.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"foobar\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-optional-peer-dep-submodule/index.js",
    "content": "export function callItself() {\n  return '[success]'\n}\n\nexport async function callPeerDepSubmodule() {\n  return await import('foobar/baz')\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-optional-peer-dep-submodule/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-optional-peer-dep-submodule\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\",\n  \"peerDependencies\": {\n    \"foobar\": \"0.0.0\"\n  },\n  \"peerDependenciesMeta\": {\n    \"foobar\": {\n      \"optional\": true\n    }\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-plus-subpath/core+feature.js",
    "content": "export const msg = 'plus-subpath'\n"
  },
  {
    "path": "playground/optimize-deps/dep-with-plus-subpath/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-with-plus-subpath\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \"./core+feature\": \"./core+feature.js\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/dynamic-use-dep-alias-using-absolute-path.js",
    "content": "// This is used to setup a test scenario, where dep scanner\n// could not determine all of the used dependencies on first\n// pass, e.g., a dependency that is aliased using an absolute\n// path, in which case it used to trigger unnecessary \"full\n// reloads\" invalidating all modules in a module graph.\nexport { default } from '@vitejs/test-dep-alias-using-absolute-path'\n"
  },
  {
    "path": "playground/optimize-deps/generics.vue",
    "content": "<!--\nhttps://github.com/vuejs/core/issues/8171\nhttps://github.com/vitejs/vite-plugin-vue/issues/162\ngeneric attribute includes angle brackets which breaks scanning\nThis file only verifies that the scanner can work with such usage and nothing\nelse.\n-->\n\n<script lang=\"ts\">\nexport class Item<TValue> {\n  value: TValue\n}\n</script>\n\n<script setup lang=\"ts\" generic=\"TItem extends Item<TValue>, TValue\">\ndefineProps<{\n  items: TItem[]\n  modelValue: TItem[]\n}>()\n</script>\n\n<template>{{ items }}</template>\n"
  },
  {
    "path": "playground/optimize-deps/glob/foo.js",
    "content": "import axios from '@vitejs/test-dep-cjs-browser-field'\n\naxios.get('/ping').then((res) => {\n  document.querySelector('.cjs-browser-field').textContent = res.data\n})\n"
  },
  {
    "path": "playground/optimize-deps/index.astro",
    "content": "<script>\n  type Foo = 'bar';\n  console.log(\"stuff\");\n\n  import.meta.glob('./dedupe.*', { eager: true })\n</script>\n"
  },
  {
    "path": "playground/optimize-deps/index.html",
    "content": "<h1>Optimize Deps</h1>\n\n<h2>CommonJS w/ named imports (react)</h2>\n<div class=\"cjs\"></div>\n<h2>CommonJS w/ named imports (phoenix)</h2>\n<div class=\"cjs-phoenix\">fail</div>\n<h2>CommonJS w/ default export (clipboard)</h2>\n<div class=\"cjs-clipboard\">fail</div>\n<h2>CommonJS w/ default export (dep-cjs-with-es-module-flag)</h2>\n<div class=\"cjs-with-es-module-flag\">fail</div>\n<h2>CommonJS import default (dep-cjs-compiled-from-esm)</h2>\n<div class=\"cjs-dep-cjs-compiled-from-esm\"></div>\n<h2>CommonJS import default (dep-cjs-compiled-from-cjs)</h2>\n<div class=\"cjs-dep-cjs-compiled-from-cjs\"></div>\n\n<script type=\"module\" src=\"./cjs.js\"></script>\n\n<h2>CommonJS dynamic import default + named (react)</h2>\n<div class=\"cjs-dynamic\"></div>\n<h2>CommonJS dynamic import named (phoenix)</h2>\n<div class=\"cjs-dynamic-phoenix\"></div>\n<h2>CommonJS dynamic import default (clipboard)</h2>\n<div class=\"cjs-dynamic-clipboard\"></div>\n<h2>CommonJS dynamic import default (dep-cjs-compiled-from-esm)</h2>\n<div class=\"cjs-dynamic-dep-cjs-compiled-from-esm\"></div>\n<h2>CommonJS dynamic import default (dep-cjs-compiled-from-cjs)</h2>\n<div class=\"cjs-dynamic-dep-cjs-compiled-from-cjs\"></div>\n<h2>CommonJS dynamic import default (dep-cjs-with-es-module-flag)</h2>\n<div class=\"cjs-dynamic-dep-cjs-with-es-module-flag\"></div>\n\n<script type=\"module\" src=\"./cjs-dynamic.js\"></script>\n\n<h2>Dedupe (dep in linked & optimized package)</h2>\n<div class=\"dedupe\"></div>\n<script type=\"module\" src=\"./dedupe.js\"></script>\n\n<h2>CommonJS w/ browser field mapping (axios)</h2>\n<div>This should show pong: <span class=\"cjs-browser-field\"></span></div>\n\n<h2>CommonJS w/ bare id browser field mapping</h2>\n<div>This should show pong: <span class=\"cjs-browser-field-bare\"></span></div>\n\n<h2>Detecting linked src package and optimizing its deps (lodash-es)</h2>\n<div>This should show fooBarBaz: <span class=\"deps-linked\"></span></div>\n\n<h2>Optimizing force included dep even when it's linked</h2>\n<div class=\"force-include\"></div>\n\n<h2>Dep with CSS</h2>\n<div class=\"dep-linked-include\">This should be red</div>\n\n<h2>CJS Dep with CSS</h2>\n<div class=\"cjs-with-assets\">This should be blue</div>\n\n<h2>CJS Dep requiring dep with CSS main field</h2>\n<div class=\"cjs-require-css-main-field\">This should be coral</div>\n\n<h2>import * as ...</h2>\n<div class=\"import-star\"></div>\n\n<h2>Import from dependency with process.env.NODE_ENV</h2>\n<div class=\"node-env\"></div>\n\n<h2>Import from dependency with .notjs files</h2>\n<div class=\"not-js\"></div>\n\n<h2>\n  Import from dependency which uses relative path which needs to be resolved by\n  main field\n</h2>\n<div class=\"relative-to-main\"></div>\n\n<h2>Import from dependency with dynamic import</h2>\n<div class=\"dep-with-dynamic-import\"></div>\n\n<h2>Import from dependency with optional peer dep</h2>\n<div class=\"dep-with-optional-peer-dep\"></div>\n<div class=\"dep-with-optional-peer-dep-error\"></div>\n\n<h2>Import from dependency with optional peer dep submodule</h2>\n<div class=\"dep-with-optional-peer-dep-submodule\"></div>\n<div class=\"dep-with-optional-peer-dep-submodule-error\"></div>\n\n<h2>Import from dependency with optional peer dep (cjs)</h2>\n<div class=\"dep-with-optional-peer-dep-cjs\"></div>\n<div class=\"dep-with-optional-peer-dep-cjs-error\"></div>\n\n<h2>Externalize known non-js files in optimize included dep</h2>\n<div class=\"externalize-known-non-js\"></div>\n\n<h2>Vue & Vuex</h2>\n<div class=\"vue\"></div>\n\n<h2>Dep with changes from esbuild plugin</h2>\n<div>This should show a greeting: <span class=\"esbuild-plugin\"></span></div>\n\n<h2>Dep from hidden dir</h2>\n<div>This should show hello!: <span class=\"hidden-dir\"></span></div>\n\n<h2>Nested include</h2>\n<div>Module path: <span class=\"nested-include\"></span></div>\n\n<h2>Alias with colon</h2>\n<div>URL: <span class=\"url\"></span></div>\n\n<h2>Alias using absolute path</h2>\n<div class=\"alias-using-absolute-path\"></div>\n\n<h2>Reused variable names</h2>\n<div>This should show reused: <span class=\"reused-variable-names\"></span></div>\n\n<h2>Flatten Id</h2>\n<div class=\"clonedeep-slash\"></div>\n<div class=\"clonedeep-dot\"></div>\n<div class=\"dep-with-plus-subpath\"></div>\n\n<h2>Non Optimized Module isn't duplicated</h2>\n<div class=\"non-optimized-module-is-not-duplicated\"></div>\n\n<h2>Pre bundle css require</h2>\n<div class=\"css-require\">css require</div>\n\n<h2>Pre bundle css modules require</h2>\n<div class=\"css-module-require\">This should be red</div>\n\n<h2>Long file name import works</h2>\n<div class=\"long-file-name\"></div>\n\n<script type=\"module\" src=\"./long-file-name.js\"></script>\n\n<h2>Import the CommonJS external package that omits the js suffix</h2>\n<div class=\"external-package-js\"></div>\n<div class=\"external-package-scss-js\"></div>\n<div class=\"external-package-astro-js\"></div>\n<div class=\"external-package-tsx-js\"></div>\n<script type=\"module\">\n  import {\n    astro,\n    okay,\n    scss,\n    tsx,\n  } from '@vitejs/test-dep-cjs-external-package-omit-js-suffix'\n\n  text('.external-package-js', okay())\n  text('.external-package-scss-js', scss())\n  text('.external-package-astro-js', astro())\n  text('.external-package-tsx-js', tsx())\n</script>\n\n<script>\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n\n<script type=\"module\">\n  // test dep detection in globbed files\n  const globbed = import.meta.glob('./glob/*.js', { eager: true })\n\n  import cjsBrowserFieldBare from '@vitejs/test-dep-cjs-browser-field-bare'\n  text('.cjs-browser-field-bare', cjsBrowserFieldBare)\n\n  import { camelCase } from '@vitejs/test-dep-linked'\n  text('.deps-linked', camelCase('foo-bar-baz'))\n\n  import { msg, VueSFC } from '@vitejs/test-dep-linked-include'\n  text('.force-include', msg)\n  text('.externalize-known-non-js', VueSFC.render())\n\n  import * as linked from '@vitejs/test-dep-linked-include'\n  const keys = Object.keys(linked)\n  if (keys.length) {\n    text('.import-star', `[success] ${keys.join(', ')}`)\n  }\n\n  import '@vitejs/test-dep-cjs-with-assets'\n  import '@vitejs/test-dep-cjs-require-css-main-field'\n  import '@vitejs/test-dep-css-require'\n  import cssModuleRequire from '@vitejs/test-dep-css-require/mod.cjs'\n  document\n    .querySelector('.css-module-require')\n    .classList.add(cssModuleRequire.cssModuleRequire)\n\n  import { env } from '@vitejs/test-dep-node-env'\n  text('.node-env', env)\n\n  import { notjsValue } from '@vitejs/test-dep-not-js'\n  text('.not-js', notjsValue)\n\n  import foo from '@vitejs/test-dep-relative-to-main/entry'\n  text('.relative-to-main', foo)\n\n  import { lazyFoo } from '@vitejs/test-dep-with-dynamic-import'\n  lazyFoo().then((foo) => {\n    text('.dep-with-dynamic-import', foo)\n  })\n\n  import { createApp } from 'vue'\n  import { createStore } from 'vuex'\n  if (typeof createApp === 'function' && typeof createStore === 'function') {\n    text('.vue', '[success]')\n  }\n\n  import { hello } from '@vitejs/test-dep-esbuild-plugin-transform'\n  text('.esbuild-plugin', hello())\n\n  import { greeting } from './.hidden-dir/foo.js'\n  text('.hidden-dir', greeting)\n\n  import { nestedInclude } from '@vitejs/test-nested-exclude'\n  text('.nested-include', nestedInclude)\n\n  import { parse } from 'node:url'\n  text('.url', parse('https://vite.dev').hostname)\n\n  import('./dynamic-use-dep-alias-using-absolute-path.js').then((mod) =>\n    text('.alias-using-absolute-path', mod.default),\n  )\n\n  import './index.astro'\n  import './generics.vue'\n\n  // All these imports should end up resolved to the same URL (same ?v= injected on them)\n  import { add as addFromDirectAbsolutePath } from '/node_modules/@vitejs/test-dep-non-optimized/index.js'\n  import { add as addFromDirectRelativePath } from './node_modules/@vitejs/test-dep-non-optimized/index.js'\n  import { get as getFromBareImport } from '@vitejs/test-dep-non-optimized'\n\n  addFromDirectAbsolutePath('from-absolute-path')\n  addFromDirectRelativePath('from-relative-path')\n  text(\n    '.non-optimized-module-is-not-duplicated',\n    getFromBareImport().join(', '),\n  )\n</script>\n\n<script type=\"module\">\n  const reusedName = 1\n</script>\n<script type=\"module\">\n  const reusedName = 'reused'\n  text('.reused-variable-names', reusedName)\n</script>\n\n<script type=\"module\">\n  import {\n    callItself,\n    callPeerDep,\n  } from '@vitejs/test-dep-with-optional-peer-dep'\n  text('.dep-with-optional-peer-dep', callItself())\n\n  // expect error as optional peer dep not installed\n  callPeerDep().catch((e) => {\n    text(\n      '.dep-with-optional-peer-dep-error',\n      e &&\n        typeof e.message === 'string' &&\n        e.message.includes(\n          'Could not resolve \"foobar\" imported by \"@vitejs/test-dep-with-optional-peer-dep\".',\n        )\n        ? '[success]'\n        : `[failed]: ${e.message}`,\n    )\n  })\n</script>\n\n<script type=\"module\">\n  import {\n    callItself,\n    callPeerDepSubmodule,\n  } from '@vitejs/test-dep-with-optional-peer-dep-submodule'\n  text('.dep-with-optional-peer-dep-submodule', callItself())\n\n  // expect error as optional peer dep not installed\n  callPeerDepSubmodule().catch((e) => {\n    text(\n      '.dep-with-optional-peer-dep-submodule-error',\n      e &&\n        typeof e.message === 'string' &&\n        e.message.includes(\n          'Could not resolve \"foobar/baz\" imported by \"@vitejs/test-dep-with-optional-peer-dep-submodule\".',\n        )\n        ? '[success]'\n        : `[failed]: ${e.message}`,\n    )\n  })\n</script>\n\n<script type=\"module\">\n  import {\n    callItself,\n    callPeerDep,\n  } from '@vitejs/test-dep-with-optional-peer-dep-cjs'\n  text('.dep-with-optional-peer-dep-cjs', callItself())\n\n  // expect fallback as optional peer dep not installed\n  text(\n    '.dep-with-optional-peer-dep-cjs-error',\n    callPeerDep() === 'fallback' ? '[success]' : `[failed]: did not fallback`,\n  )\n</script>\n\n<script type=\"module\">\n  // should error on builtin modules (named import)\n  // no node: protocol intentionally\n  import { Buffer } from 'buffer'\n  // named imports error immediately\n</script>\n\n<script type=\"module\">\n  // should error on builtin modules (default import)\n  // no node: protocol intentionally\n  import cp from 'child_process'\n  // must access property to error\n  if (import.meta.env.DEV) {\n    cp.execSync()\n  }\n</script>\n\n<script type=\"module\">\n  // should error on builtin modules from dep\n  import { read } from '@vitejs/test-dep-with-builtin-module-esm'\n  if (import.meta.env.DEV) {\n    read()\n  }\n</script>\n\n<script type=\"module\">\n  // should error on builtin modules from dep\n  import { read } from '@vitejs/test-dep-with-builtin-module-cjs'\n  if (import.meta.env.DEV) {\n    read()\n  }\n</script>\n\n<script type=\"module\">\n  import cloneDeepSlash from 'lodash/cloneDeep'\n  import cloneDeepDot from 'lodash.clonedeep'\n  import { msg as plusSubpath } from '@vitejs/test-dep-with-plus-subpath/core+feature'\n\n  text('.clonedeep-slash', cloneDeepSlash({ name: 'clonedeep-slash' }).name)\n  text('.clonedeep-dot', cloneDeepDot({ name: 'clonedeep-dot' }).name)\n  text('.dep-with-plus-subpath', plusSubpath)\n</script>\n\n<script type=\"module\">\n  import loadSub from '@vitejs/test-dep-incompatible'\n  loadSub() // should show an error that tells there's an incompatible dep\n</script>\n\n<h2>Pre-bundle transitive dependency 'some-package.pdf'</h2>\n<div>prebundled: <span class=\"dep-with-asset-ext-prebundled\">???</span></div>\n<div>\n  no dual package: <span class=\"dep-with-asset-ext-no-dual-package\">???</span>\n</div>\n<script type=\"module\">\n  import original, { isPreBundled } from '@vitejs/test-dep-with-asset-ext1.pdf'\n  import reexport from '@vitejs/test-dep-with-asset-ext2.pdf'\n  text('.dep-with-asset-ext-prebundled', isPreBundled)\n  text('.dep-with-asset-ext-no-dual-package', original === reexport)\n</script>\n\n<script type=\"module\">\n  // manually check Firefox doesn't show warning in devtool debugger\n  import * as sub from '@vitejs/test-dep-source-map-no-sources/sub.js'\n  import * as all from '@vitejs/test-dep-source-map-no-sources/all.js'\n</script>\n\n<h2>Pre-bundle dependency with external sub-dependencies</h2>\n<div>\n  require('some-external-sub-dependency') returns a plain object rather than a\n  module namespace object:\n  <span class=\"dep-cjs-with-external-deps-object\">???</span>\n</div>\n<div>\n  require('some-external-sub-dependency') returns the default export if the\n  dependency is a Node builtin:\n  <span class=\"dep-cjs-with-external-deps-node-builtin\">???</span>\n</div>\n<script type=\"module\">\n  import * as optimized from '@vitejs/test-dep-cjs-with-external-deps'\n  text('.dep-cjs-with-external-deps-object', optimized.externalResult)\n  text(\n    '.dep-cjs-with-external-deps-node-builtin',\n    optimized.externalDummyNodeBuiltinResult,\n  )\n</script>\n\n<h2>Virtual module with .vue extension</h2>\n<div>\n  This should not error during dep scan:\n  <span class=\"virtual-module-vue\"></span>\n</div>\n<script type=\"module\">\n  import VirtualComponent from 'virtual:test-virtual-file/Foo.vue'\n  text(\n    '.virtual-module-vue',\n    `${VirtualComponent.name === 'VirtualComponent' ? 'ok' : 'ng'}`,\n  )\n</script>\n\n<h2>Relative asset URLs in optimized dependencies</h2>\n<div>\n  Message from lib worker:\n  <span class=\"worker-lib\"></span>\n</div>\n<div>\n  Message from nested worker:\n  <span class=\"worker-nested\"></span>\n</div>\n<h2>Non-worker asset from optimized dep</h2>\n<div>\n  Asset URL from lib:\n  <span class=\"asset-url\"></span>\n</div>\n<script type=\"module\">\n  import * as lib from '@vitejs/test-dep-with-assets'\n  import * as nested from '@vitejs/test-dep-with-assets/nested'\n  lib.urlImportWorker().then((m) => text('.worker-lib', m))\n  nested.urlImportWorker().then((m) => text('.worker-nested', m))\n  text('.asset-url', lib.getAssetUrl())\n</script>\n"
  },
  {
    "path": "playground/optimize-deps/long-file-name.js",
    "content": "import test from '@vitejs/longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/index'\n\nconst main = document.querySelector('.long-file-name')\nmain.innerHTML = test ?? 'failed to import'\n"
  },
  {
    "path": "playground/optimize-deps/longfilename/index.js",
    "content": "const test = 'hello world'\n\nexport default test\n"
  },
  {
    "path": "playground/optimize-deps/longfilename/package.json",
    "content": "{\n  \"name\": \"@vitejs/longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/nested-exclude/index.js",
    "content": "export { default as nestedInclude } from '@vitejs/test-nested-include'\n\nexport default 'nested-exclude'\n"
  },
  {
    "path": "playground/optimize-deps/nested-exclude/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-exclude\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-nested-include\": \"file:../nested-include\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/nested-include/index.js",
    "content": "// written in cjs, optimization should convert this to esm\nmodule.exports = 'nested-include'\n"
  },
  {
    "path": "playground/optimize-deps/nested-include/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-include\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps/non-optimizable-include/index.css",
    "content": "@font-face {\n  font-family: 'Not Real Sans';\n  src: url('./i-throw-if-you-optimize-this-file.woff') format('woff');\n}\n"
  },
  {
    "path": "playground/optimize-deps/non-optimizable-include/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-non-optimizable-include\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": \"./index.css\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-optimize-deps\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"clipboard\": \"^2.0.11\",\n    \"@vitejs/test-dep-cjs-browser-field\": \"file:./dep-cjs-browser-field\",\n    \"@vitejs/longfilename-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": \"file:./longfilename\",\n    \"@vitejs/test-dep-alias-using-absolute-path\": \"file:./dep-alias-using-absolute-path\",\n    \"@vitejs/test-dep-cjs-browser-field-bare\": \"file:./dep-cjs-browser-field-bare\",\n    \"@vitejs/test-dep-cjs-compiled-from-cjs\": \"file:./dep-cjs-compiled-from-cjs\",\n    \"@vitejs/test-dep-cjs-compiled-from-esm\": \"file:./dep-cjs-compiled-from-esm\",\n    \"@vitejs/test-dep-cjs-with-assets\": \"file:./dep-cjs-with-assets\",\n    \"@vitejs/test-dep-cjs-with-es-module-flag\": \"file:./dep-cjs-with-es-module-flag\",\n    \"@vitejs/test-dep-cjs-with-external-deps\": \"file:./dep-cjs-with-external-deps\",\n    \"@vitejs/test-dep-cjs-css-main-field\": \"file:./dep-cjs-css-main-field\",\n    \"@vitejs/test-dep-cjs-require-css-main-field\": \"file:./dep-cjs-require-css-main-field\",\n    \"@vitejs/test-dep-css-require\": \"file:./dep-css-require\",\n    \"@vitejs/test-dep-esbuild-plugin-transform\": \"file:./dep-esbuild-plugin-transform\",\n    \"@vitejs/test-dep-incompatible\": \"file:./dep-incompatible\",\n    \"@vitejs/test-dep-linked\": \"link:./dep-linked\",\n    \"@vitejs/test-dep-linked-include\": \"link:./dep-linked-include\",\n    \"@vitejs/test-dep-node-env\": \"file:./dep-node-env\",\n    \"@vitejs/test-dep-not-js\": \"file:./dep-not-js\",\n    \"@vitejs/test-dep-optimize-exports-with-glob\": \"file:./dep-optimize-exports-with-glob\",\n    \"@vitejs/test-dep-optimize-exports-with-root-glob\": \"file:./dep-optimize-exports-with-root-glob\",\n    \"@vitejs/test-dep-optimize-with-glob\": \"file:./dep-optimize-with-glob\",\n    \"@vitejs/test-dep-relative-to-main\": \"file:./dep-relative-to-main\",\n    \"@vitejs/test-dep-source-map-no-sources\": \"file:./dep-source-map-no-sources\",\n    \"@vitejs/test-dep-with-asset-ext1.pdf\": \"file:./dep-with-asset-ext/dep1\",\n    \"@vitejs/test-dep-with-asset-ext2.pdf\": \"file:./dep-with-asset-ext/dep2\",\n    \"@vitejs/test-dep-with-builtin-module-cjs\": \"file:./dep-with-builtin-module-cjs\",\n    \"@vitejs/test-dep-with-builtin-module-esm\": \"file:./dep-with-builtin-module-esm\",\n    \"@vitejs/test-dep-with-dynamic-import\": \"file:./dep-with-dynamic-import\",\n    \"@vitejs/test-dep-with-optional-peer-dep\": \"file:./dep-with-optional-peer-dep\",\n    \"@vitejs/test-dep-with-optional-peer-dep-cjs\": \"file:./dep-with-optional-peer-dep-cjs\",\n    \"@vitejs/test-dep-with-optional-peer-dep-submodule\": \"file:./dep-with-optional-peer-dep-submodule\",\n    \"@vitejs/test-dep-with-plus-subpath\": \"file:./dep-with-plus-subpath\",\n    \"@vitejs/test-dep-non-optimized\": \"file:./dep-non-optimized\",\n    \"@vitejs/test-added-in-entries\": \"file:./added-in-entries\",\n    \"@vitejs/test-dep-cjs-external-package-omit-js-suffix\": \"file:./dep-cjs-external-package-omit-js-suffix\",\n    \"@vitejs/test-dep-with-assets\": \"file:./dep-with-assets\",\n    \"lodash-es\": \"^4.17.23\",\n    \"@vitejs/test-nested-exclude\": \"file:./nested-exclude\",\n    \"phoenix\": \"^1.8.5\",\n    \"react\": \"^19.2.4\",\n    \"react-dom\": \"^19.2.4\",\n    \"@vitejs/test-resolve-linked\": \"workspace:0.0.0\",\n    \"url\": \"^0.11.4\",\n    \"vue\": \"^3.5.30\",\n    \"vuex\": \"^4.1.0\",\n    \"lodash\": \"^4.17.23\",\n    \"lodash.clonedeep\": \"^4.5.0\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps/unused-split-entry.js",
    "content": "import msg from '@vitejs/test-added-in-entries'\n\n// This is an entry file that is added to optimizeDeps.entries\n// When the deps aren't cached, these entries are also processed\n// to discover dependencies in them. This should only be needed\n// for code split sections that are commonly visited after\n// first load where a full-reload wants to be avoided at the expense\n// of extra processing on cold start. Another option is to add\n// the missing dependencies to optimizeDeps.include directly\n\nconsole.log(msg)\n"
  },
  {
    "path": "playground/optimize-deps/vite.config.js",
    "content": "import fs from 'node:fs'\nimport module from 'node:module'\nimport { defineConfig } from 'vite'\nconst require = module.createRequire(import.meta.url)\n\nexport default defineConfig({\n  define: {\n    __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,\n  },\n  resolve: {\n    dedupe: ['react'],\n    alias: {\n      'node:url': 'url',\n      '@vitejs/test-dep-alias-using-absolute-path':\n        require.resolve('@vitejs/test-dep-alias-using-absolute-path'),\n    },\n  },\n  optimizeDeps: {\n    include: [\n      '@vitejs/test-dep-linked-include',\n      '@vitejs/test-nested-exclude > @vitejs/test-nested-include',\n      '@vitejs/test-dep-cjs-external-package-omit-js-suffix',\n      // will throw if optimized (should log warning instead)\n      '@vitejs/test-non-optimizable-include',\n      '@vitejs/test-dep-optimize-exports-with-glob/**/*',\n      '@vitejs/test-dep-optimize-exports-with-root-glob/**/*.js',\n      '@vitejs/test-dep-optimize-with-glob/**/*.js',\n      '@vitejs/test-dep-cjs-with-external-deps',\n      '@vitejs/test-dep-cjs-with-es-module-flag',\n    ],\n    exclude: [\n      '@vitejs/test-nested-exclude',\n      '@vitejs/test-dep-non-optimized',\n      '@vitejs/test-dep-esm-external',\n      'stream',\n    ],\n    rolldownOptions: {\n      plugins: [\n        {\n          name: 'replace-a-file',\n          load(id) {\n            if (/dep-esbuild-plugin-transform(?:\\\\|\\/)index\\.js$/.test(id)) {\n              return `export const hello = () => 'Hello from an esbuild plugin'`\n            }\n          },\n        },\n      ],\n    },\n    entries: ['index.html', 'unused-split-entry.js'],\n  },\n\n  build: {\n    // to make tests faster\n    minify: false,\n  },\n\n  plugins: [\n    testVue(),\n    notjs(),\n    virtualModulePlugin(),\n    {\n      name: 'test-astro',\n      transform(code, id) {\n        if (id.endsWith('.astro')) {\n          code = `export default {}`\n          return { code }\n        }\n      },\n    },\n  ],\n})\n\n// Handles Test.vue in dep-linked-include package\nfunction testVue() {\n  return {\n    name: 'testvue',\n    transform(code, id) {\n      if (id.includes('dep-linked-include/Test.vue')) {\n        return {\n          code: `\nimport { defineComponent } from 'vue'\n\nexport default defineComponent({\n  name: 'Test',\n  render() {\n    return '[success] rendered from Vue'\n  }\n})\n`.trim(),\n        }\n      }\n\n      // fallback to empty module for other vue files\n      if (!id.startsWith('\\0') && id.endsWith('.vue')) {\n        return { code: `export default {}` }\n      }\n    },\n  }\n}\n\n// Handles .notjs file, basically remove wrapping <notjs> and </notjs> tags\nfunction notjs() {\n  return {\n    name: 'notjs',\n    config() {\n      return {\n        optimizeDeps: {\n          extensions: ['.notjs'],\n          rolldownOptions: {\n            plugins: [\n              {\n                name: 'esbuild-notjs',\n                load: {\n                  filter: { id: /\\.notjs$/ },\n                  handler(id) {\n                    let contents = fs.readFileSync(id, 'utf-8')\n                    contents = contents\n                      .replace('<notjs>', '')\n                      .replace('</notjs>', '')\n                    return contents\n                  },\n                },\n              },\n            ],\n          },\n        },\n      }\n    },\n    transform(code, id) {\n      if (id.endsWith('.notjs')) {\n        code = code.replace('<notjs>', '').replace('</notjs>', '')\n        return { code }\n      }\n    },\n  }\n}\n\nfunction virtualModulePlugin() {\n  const virtualModuleId = 'virtual:test-virtual-file/Foo.vue'\n  const resolvedVirtualModuleId = '\\0' + virtualModuleId\n\n  return {\n    name: 'test-virtual-module',\n    resolveId(id) {\n      if (id === virtualModuleId) {\n        return resolvedVirtualModuleId\n      }\n    },\n    load(id) {\n      if (id === resolvedVirtualModuleId) {\n        return `export default { name: 'VirtualComponent' }`\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps-no-discovery/__tests__/optimize-deps-no-discovery.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page, readDepOptimizationMetadata } from '~utils'\n\ntest('optimized dep', async () => {\n  expect(await page.textContent('.optimized-dep')).toBe('[success]')\n})\n\ntest('vue + vuex', async () => {\n  expect(await page.textContent('.vue')).toMatch(`[success]`)\n})\n\ntest.runIf(!isBuild)('metadata', async () => {\n  const meta = readDepOptimizationMetadata()\n  expect(Object.keys(meta.optimized)).toContain('@vitejs/test-dep-no-discovery')\n  expect(Object.keys(meta.optimized)).not.toContain('vue')\n  expect(Object.keys(meta.optimized)).not.toContain('vuex')\n})\n"
  },
  {
    "path": "playground/optimize-deps-no-discovery/dep-no-discovery/index.js",
    "content": "// written in cjs, optimization should convert this to esm\nmodule.exports = '[success]'\n"
  },
  {
    "path": "playground/optimize-deps-no-discovery/dep-no-discovery/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-no-discovery\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/optimize-deps-no-discovery/index.html",
    "content": "<h1>Optimize Deps</h1>\n\n<h2>Optimized Dep</h2>\n<div class=\"optimized-dep\"></div>\n\n<h2>Vue & Vuex</h2>\n<div class=\"vue\"></div>\n\n<script>\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n</script>\n\n<script type=\"module\">\n  import msg from '@vitejs/test-dep-no-discovery'\n  text('.optimized-dep', msg)\n\n  import { createApp } from 'vue'\n  import { createStore } from 'vuex'\n  if (typeof createApp === 'function' && typeof createStore === 'function') {\n    text('.vue', '[success]')\n  }\n</script>\n"
  },
  {
    "path": "playground/optimize-deps-no-discovery/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-optimize-deps-no-discovery\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-dep-no-discovery\": \"file:./dep-no-discovery\",\n    \"vue\": \"^3.5.30\",\n    \"vuex\": \"^4.1.0\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-deps-no-discovery/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\n// Overriding the NODE_ENV set by vitest\nprocess.env.NODE_ENV = ''\n\nexport default defineConfig({\n  define: {\n    __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,\n  },\n  optimizeDeps: {\n    noDiscovery: true,\n    include: ['@vitejs/test-dep-no-discovery'],\n  },\n\n  build: {\n    // to make tests faster\n    minify: false,\n  },\n})\n"
  },
  {
    "path": "playground/optimize-missing-deps/__test__/optimize-missing-deps.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port } from './serve'\nimport { isBuild, page } from '~utils'\n\nconst url = `http://localhost:${port}/`\n\ntest.runIf(!isBuild)('optimize', async () => {\n  await page.goto(url)\n  // reload page to get optimized missing deps\n  await page.reload()\n  await expect.poll(() => page.textContent('div')).toMatch('Client')\n\n  // raw http request\n  const aboutHtml = await (await fetch(url)).text()\n  expect(aboutHtml).toContain('Server')\n})\n"
  },
  {
    "path": "playground/optimize-missing-deps/__test__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport { hmrPorts, ports, rootDir } from '~utils'\n\nexport const port = ports['optimize-missing-deps']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(\n    rootDir,\n    hmrPorts['optimize-missing-deps'],\n  )\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/optimize-missing-deps/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite App</title>\n  </head>\n  <body>\n    <!--app-html-->\n  </body>\n</html>\n"
  },
  {
    "path": "playground/optimize-missing-deps/main.js",
    "content": "import { sayName } from '@vitejs/test-missing-dep'\n\nexport const name = sayName()\n"
  },
  {
    "path": "playground/optimize-missing-deps/missing-dep/index.js",
    "content": "import { name } from '@vitejs/test-multi-entry-dep'\n\nexport function sayName() {\n  return name\n}\n"
  },
  {
    "path": "playground/optimize-missing-deps/missing-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-missing-dep\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-multi-entry-dep\": \"file:../multi-entry-dep\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-missing-deps/multi-entry-dep/index.browser.js",
    "content": "exports.name = 'Client'\n"
  },
  {
    "path": "playground/optimize-missing-deps/multi-entry-dep/index.js",
    "content": "const path = require('node:path')\n\nexports.name = path.normalize('./Server')\n"
  },
  {
    "path": "playground/optimize-missing-deps/multi-entry-dep/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-multi-entry-dep\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"browser\": {\n    \"./index.js\": \"./index.browser.js\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-missing-deps/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-optimize-missing-deps\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-missing-dep\": \"file:./missing-dep\"\n  },\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/optimize-missing-deps/server.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nexport async function createServer(root = process.cwd(), hmrPort) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  const vite = await (\n    await import('vite')\n  ).createServer({\n    root,\n    logLevel: isTest ? 'error' : 'info',\n    server: {\n      middlewareMode: true,\n      hmr: {\n        port: hmrPort,\n      },\n    },\n    appType: 'custom',\n  })\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res) => {\n    try {\n      let template = fs.readFileSync(resolve('index.html'), 'utf-8')\n      template = await vite.transformIndexHtml(req.originalUrl, template)\n\n      // `main.js` imports dependencies that are yet to be discovered and optimized, aka \"missing\" deps.\n      // Loading `main.js` in SSR should not trigger optimizing the \"missing\" deps\n      const { name } = await vite.ssrLoadModule('./main.js')\n\n      // Loading `main.js` in the client should trigger optimizing the \"missing\" deps\n      const appHtml = `<div id=\"app\">${name}</div>\n<script type='module'>\n  import { name } from './main.js'\n  document.getElementById('app').innerText = name\n</script>`\n\n      const html = template.replace(`<!--app-html-->`, appHtml)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/package.json",
    "content": "{\n  \"name\": \"@vitejs/vite-playground\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"1.0.0\",\n  \"scripts\": {\n    \"typecheck\": \"tsc\"\n  },\n  \"devDependencies\": {\n    \"convert-source-map\": \"^2.0.0\",\n    \"css-color-names\": \"^1.0.1\",\n    \"kill-port\": \"^1.6.1\",\n    \"rolldown\": \"1.0.0-rc.10\"\n  }\n}\n"
  },
  {
    "path": "playground/preload/__tests__/preload-disabled/preload-disabled.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { browserLogs, isBuild, page } from '~utils'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('dynamic import', async () => {\n    await page.waitForSelector('#done')\n    expect(await page.textContent('#done')).toBe('ran js')\n  })\n\n  test('dynamic import with comments', async () => {\n    await page.click('#hello .load')\n    await page.waitForSelector('#hello output')\n\n    const html = await page.content()\n    expect(html).not.toMatch(/link rel=\"modulepreload\"/)\n\n    expect(html).toMatch(\n      /link rel=\"stylesheet\".*?href=\".*?\\/assets\\/hello-[-\\w]{8}\\.css\"/,\n    )\n  })\n})\n"
  },
  {
    "path": "playground/preload/__tests__/preload.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { browserLogs, isBuild, page } from '~utils'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('dynamic import', async () => {\n    await page.waitForSelector('#done')\n    expect(await page.textContent('#done')).toBe('ran js')\n  })\n\n  test('dynamic import with comments', async () => {\n    await page.click('#hello .load')\n    await page.waitForSelector('#hello output')\n\n    const html = await page.content()\n    expect(html).toMatch(\n      /link rel=\"modulepreload\".*?href=\".*?\\/assets\\/hello-[-\\w]{8}\\.js\"/,\n    )\n    expect(html).toMatch(\n      /link rel=\"stylesheet\".*?href=\".*?\\/assets\\/hello-[-\\w]{8}\\.css\"/,\n    )\n  })\n})\n"
  },
  {
    "path": "playground/preload/__tests__/resolve-deps/preload-resolve-deps.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { browserLogs, isBuild, page } from '~utils'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  test('dynamic import', async () => {\n    await page.waitForSelector('#done')\n    expect(await page.textContent('#done')).toBe('ran js')\n  })\n\n  test('dynamic import with comments', async () => {\n    await page.click('#hello .load')\n    await page.waitForSelector('#hello output')\n\n    const html = await page.content()\n    expect(html).toMatch(\n      /link rel=\"modulepreload\".*?href=\"http.*?\\/hello-[-\\w]{8}\\.js\"/,\n    )\n    expect(html).toMatch(\n      /link rel=\"modulepreload\".*?href=\"http.*?\\/preloaded.js\"/,\n    )\n    expect(html).toMatch(\n      /link rel=\"stylesheet\".*?href=\"http.*?\\/hello-[-\\w]{8}\\.css\"/,\n    )\n  })\n})\n"
  },
  {
    "path": "playground/preload/dep-a/index.js",
    "content": "export const msgFromA = 'From dep-a'\n"
  },
  {
    "path": "playground/preload/dep-a/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-a\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/preload/dep-including-a/index.js",
    "content": "export { msgFromA } from '@vitejs/test-dep-a'\n\nexport const msg = 'From dep-including-a'\n"
  },
  {
    "path": "playground/preload/dep-including-a/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-including-a\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-dep-a\": \"file:../dep-a\"\n  }\n}\n"
  },
  {
    "path": "playground/preload/index.html",
    "content": "<h1>preload</h1>\n<div class=\"chunk\"></div>\n<div id=\"hello\">\n  <button class=\"load\">Load hello</button>\n  <div class=\"msg\"></div>\n</div>\n<div id=\"about\">\n  <button class=\"load\">Load about</button>\n  <div class=\"msg\"></div>\n</div>\n\n<script type=\"module\">\n  import { msgFromA } from '@vitejs/test-dep-a'\n  console.log(msgFromA)\n\n  import './src/main.js'\n  document\n    .querySelector('h1')\n    .insertAdjacentHTML('afterEnd', '<div id=\"done\">ran js</div>')\n</script>\n"
  },
  {
    "path": "playground/preload/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-preload\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\",\n    \"dev:resolve-deps\": \"vite --config vite.config-resolve-deps.js\",\n    \"build:resolve-deps\": \"vite build --config vite.config-resolve-deps.js\",\n    \"debug:resolve-deps\": \"node --inspect-brk ../../packages/vite/bin/vite --config vite.config-resolve-deps.js\",\n    \"preview:resolve-deps\": \"vite preview --config vite.config-resolve-deps.js\",\n    \"dev:preload-disabled\": \"vite --config vite.config-preload-disabled.js\",\n    \"build:preload-disabled\": \"vite build --config vite.config-preload-disabled.js\",\n    \"debug:preload-disabled\": \"node --inspect-brk ../../packages/vite/bin/vite --config vite.config-preload-disabled.js\",\n    \"preview:preload-disabled\": \"vite preview --config vite.config-preload-disabled.js\"\n  },\n  \"devDependencies\": {\n    \"terser\": \"^5.46.0\",\n    \"@vitejs/test-dep-a\": \"file:./dep-a\",\n    \"@vitejs/test-dep-including-a\": \"file:./dep-including-a\"\n  }\n}\n"
  },
  {
    "path": "playground/preload/public/preloaded.js",
    "content": "console.log('preloaded')\n"
  },
  {
    "path": "playground/preload/src/about.js",
    "content": "import { msg } from '@vitejs/test-dep-including-a'\n\ndocument.querySelector('#about .msg').textContent = msg\n"
  },
  {
    "path": "playground/preload/src/chunk.js",
    "content": "export default '[success] message from chunk.js'\n"
  },
  {
    "path": "playground/preload/src/hello.js",
    "content": "import style from './hello.module.css'\n\nconst msg = document.querySelector('#hello .msg')\nmsg.textContent = 'hello'\nmsg.classList.add(style.h1)\n"
  },
  {
    "path": "playground/preload/src/hello.module.css",
    "content": ".h1 {\n  color: red;\n}\n"
  },
  {
    "path": "playground/preload/src/main.js",
    "content": "import chunkMsg from './chunk'\n\ndocument.querySelector('.chunk').textContent = chunkMsg\n\nconst ids = {\n  hello: async () => {\n    await import(/* a comment */ './hello.js')\n  },\n  about: async () => {\n    await import('./about.js') // lazy load\n  },\n}\n\nfor (const [id, loader] of Object.entries(ids)) {\n  const loadButton = document.querySelector(`#${id} .load`)\n  loadButton.addEventListener('click', async () => {\n    await loader()\n    loadButton.insertAdjacentHTML('afterend', '<output>loaded</output>')\n  })\n}\n"
  },
  {
    "path": "playground/preload/vite.config-preload-disabled.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    outDir: 'dist/preload-disabled',\n    minify: 'terser',\n    terserOptions: {\n      format: {\n        beautify: true,\n      },\n      compress: {\n        passes: 3,\n      },\n    },\n    rollupOptions: {\n      output: {\n        // manualChunks(id) {\n        //   if (id.includes('chunk.js')) {\n        //     return 'chunk'\n        //   }\n        // },\n      },\n    },\n    modulePreload: false,\n  },\n  cacheDir: 'node_modules/.vite-preload-disabled',\n})\n"
  },
  {
    "path": "playground/preload/vite.config-resolve-deps.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    outDir: 'dist/resolve-deps',\n    minify: 'terser',\n    terserOptions: {\n      format: {\n        beautify: true,\n      },\n      compress: {\n        passes: 3,\n      },\n    },\n    rollupOptions: {\n      output: {\n        // manualChunks(id) {\n        //   if (id.includes('chunk.js')) {\n        //     return 'chunk'\n        //   }\n        // },\n      },\n    },\n    modulePreload: {\n      resolveDependencies(filename, deps, { hostId, hostType }) {\n        if (filename.includes('hello')) {\n          return [...deps, 'preloaded.js']\n        }\n        return deps\n      },\n    },\n  },\n  experimental: {\n    renderBuiltUrl(filename, { hostId, hostType }) {\n      if (filename.includes('preloaded')) {\n        return { runtime: `\"\"+${JSON.stringify('/' + filename)}` }\n      }\n      return { relative: true }\n    },\n  },\n  cacheDir: 'node_modules/.vite-resolve-deps',\n})\n"
  },
  {
    "path": "playground/preload/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    outDir: 'dist/normal',\n    minify: 'terser',\n    terserOptions: {\n      format: {\n        beautify: true,\n      },\n      compress: {\n        passes: 3,\n      },\n    },\n    rollupOptions: {\n      output: {\n        // manualChunks(id) {\n        //   if (id.includes('chunk.js')) {\n        //     return 'chunk'\n        //   }\n        // },\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/preserve-symlinks/__tests__/preserve-symlinks.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { browserLogs, page } from '~utils'\n\ntest('should have no 404s', () => {\n  browserLogs.forEach((msg) => {\n    expect(msg).not.toMatch('404')\n  })\n})\n\ntest('not-preserve-symlinks', async () => {\n  expect(await page.textContent('#root')).toBe('hello vite')\n})\n"
  },
  {
    "path": "playground/preserve-symlinks/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"src/favicon.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite App</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/preserve-symlinks/module-a/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-module-a\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"linked.js\"\n}\n"
  },
  {
    "path": "playground/preserve-symlinks/module-a/src/data.js",
    "content": "export const data = {\n  msg: 'hello vite',\n}\n"
  },
  {
    "path": "playground/preserve-symlinks/module-a/src/index.js",
    "content": "import { data } from './data'\n\nexport function sayHi() {\n  return data\n}\n"
  },
  {
    "path": "playground/preserve-symlinks/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-preserve-symlinks\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite --force\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-module-a\": \"link:./module-a\"\n  }\n}\n"
  },
  {
    "path": "playground/preserve-symlinks/src/main.js",
    "content": "import { sayHi } from '@vitejs/test-module-a'\n\ndocument.getElementById('root').innerText = sayHi().msg\n"
  },
  {
    "path": "playground/proxy-bypass/__tests__/proxy-bypass.spec.ts",
    "content": "import { expect, test, vi } from 'vitest'\nimport { browserLogs, isServe, page, serverLogs, viteTestUrl } from '~utils'\n\ntest('proxy-bypass', async () => {\n  await vi.waitFor(() => {\n    expect(browserLogs.join('\\n')).toContain('status of 404 (Not Found)')\n  })\n})\n\ntest('async-proxy-bypass', async () => {\n  const content = await page.frame('async-response').content()\n  expect(content).toContain('Hello after 4 ms (async timeout)')\n})\n\ntest('async-proxy-bypass-with-error', async () => {\n  await vi.waitFor(() => {\n    expect(serverLogs.join('\\n')).toContain('bypass error')\n  })\n})\n\ntest.runIf(isServe)('proxy error returns 502', async () => {\n  const res = await fetch(viteTestUrl + '/proxyError')\n  expect(res.status).toBe(502)\n})\n"
  },
  {
    "path": "playground/proxy-bypass/index.html",
    "content": "root app<br />\n<iframe src=\"/nonExistentApp\" style=\"border: 0\"></iframe>\n<iframe src=\"/asyncResponse\" name=\"async-response\"></iframe>\n<iframe src=\"/asyncThrowingError\"></iframe>\n"
  },
  {
    "path": "playground/proxy-bypass/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-proxy-bypass\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/proxy-bypass/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nconst timeout = (ms) => new Promise((r) => setTimeout(r, ms))\n\nexport default defineConfig({\n  server: {\n    port: 9606,\n    proxy: {\n      '/nonExistentApp': {\n        target: 'http://localhost:9607',\n        bypass: () => {\n          return false\n        },\n      },\n      '/proxyError': {\n        target: 'http://foo.invalid',\n      },\n      '/asyncResponse': {\n        bypass: async (_, res) => {\n          await timeout(4)\n          res.writeHead(200, {\n            'Content-Type': 'text/plain',\n          })\n          res.end('Hello after 4 ms (async timeout)')\n          return '/asyncResponse'\n        },\n      },\n      '/asyncThrowingError': {\n        bypass: async () => {\n          await timeout(4)\n          throw new Error('bypass error')\n        },\n      },\n    },\n  },\n  plugins: [\n    {\n      name: 'handle-error-in-preview',\n      configurePreviewServer({ config, middlewares }) {\n        return () => {\n          middlewares.use((err, _req, res, _next) => {\n            config.logger.error(err.message, { error: err })\n            res.statusCode = 500\n            res.end()\n          })\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/proxy-hmr/__tests__/proxy-hmr.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport {\n  editFile,\n  isBuild,\n  page,\n  untilBrowserLogAfter,\n  viteTestUrl,\n} from '~utils'\n\ntest.runIf(!isBuild)('proxy-hmr', async () => {\n  await untilBrowserLogAfter(\n    () => page.goto(viteTestUrl),\n    // wait for both main and sub app HMR connection\n    [/connected/, /connected/],\n  )\n\n  const otherAppTextLocator = page.frameLocator('iframe').locator('.content')\n  await expect\n    .poll(() => otherAppTextLocator.textContent())\n    .toMatch('other app')\n  editFile('other-app/index.html', (code) =>\n    code.replace('app', 'modified app'),\n  )\n  await expect\n    .poll(() => otherAppTextLocator.textContent())\n    .toMatch('other modified app')\n})\n"
  },
  {
    "path": "playground/proxy-hmr/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport { rootDir, setViteUrl } from '~utils'\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  const vite = await import('vite')\n  const rootServer = await vite.createServer({\n    root: rootDir,\n    logLevel: 'silent',\n  })\n  const otherServer = await vite.createServer({\n    root: path.join(rootDir, 'other-app'),\n    logLevel: 'silent',\n  })\n\n  await Promise.all([rootServer.listen(), otherServer.listen()])\n  const viteUrl = rootServer.resolvedUrls.local[0]\n  setViteUrl(viteUrl)\n\n  return {\n    async close() {\n      await Promise.all([rootServer.close(), otherServer.close()])\n    },\n  }\n}\n"
  },
  {
    "path": "playground/proxy-hmr/index.html",
    "content": "root app<br />\n<iframe src=\"/anotherApp\" style=\"border: 0\"></iframe>\n"
  },
  {
    "path": "playground/proxy-hmr/other-app/index.html",
    "content": "<span class=\"content\">other app</span>\n"
  },
  {
    "path": "playground/proxy-hmr/other-app/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-other-app\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/proxy-hmr/other-app/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  base: '/anotherApp',\n  server: {\n    port: 9617,\n    strictPort: true,\n  },\n})\n"
  },
  {
    "path": "playground/proxy-hmr/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-proxy-hmr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/proxy-hmr/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  server: {\n    port: 9616,\n    proxy: {\n      '/anotherApp': {\n        target: 'http://localhost:9617',\n        ws: true,\n      },\n    },\n  },\n})\n"
  },
  {
    "path": "playground/resolve/__tests__/mainfields-custom-first/resolve-mainfields-custom-first.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from '~utils'\n\ntest('resolve.mainFields.custom-first', async () => {\n  expect(await page.textContent('.custom-browser-main-field')).toBe(\n    'resolved custom field',\n  )\n})\n"
  },
  {
    "path": "playground/resolve/__tests__/resolve.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { describe, expect, test } from 'vitest'\nimport { isBuild, isServe, isWindows, page, testDir, viteTestUrl } from '~utils'\n\ntest('bom import', async () => {\n  expect(await page.textContent('.utf8-bom')).toMatch('[success]')\n})\n\ntest('deep import', async () => {\n  expect(await page.textContent('.deep-import')).toMatch('[2,4]')\n})\n\ntest('exports and a nested package scope with a different type', async () => {\n  expect(await page.textContent('.exports-and-nested-scope')).toMatch(\n    '[success]',\n  )\n})\n\ntest('entry with exports field', async () => {\n  expect(await page.textContent('.exports-entry')).toMatch('[success]')\n})\n\ntest('deep import with exports field', async () => {\n  expect(await page.textContent('.exports-deep')).toMatch('[success]')\n})\n\ntest('deep import with query with exports field', async () => {\n  // since it is imported with `?url` it should return a URL\n  expect(await page.textContent('.exports-deep-query')).toMatch(\n    isBuild ? /base64/ : '/exports-path/deep.json',\n  )\n})\n\ntest('deep import with exports field + exposed dir', async () => {\n  expect(await page.textContent('.exports-deep-exposed-dir')).toMatch(\n    '[success]',\n  )\n})\n\ntest('deep import with exports field + mapped dir', async () => {\n  expect(await page.textContent('.exports-deep-mapped-dir')).toMatch(\n    '[success]',\n  )\n})\n\ntest('exports read from the root package.json', async () => {\n  expect(await page.textContent('.exports-from-root')).toMatch('[success]')\n})\n\n// this is how Svelte 3 is packaged\ntest('deep import with exports and legacy fallback', async () => {\n  expect(await page.textContent('.exports-legacy-fallback')).toMatch(\n    '[success]',\n  )\n})\n\ntest('Respect exports field env key priority', async () => {\n  expect(await page.textContent('.exports-env')).toMatch('[success]')\n})\n\ntest('Respect production/development conditionals', async () => {\n  expect(await page.textContent('.exports-env')).toMatch(\n    isBuild ? `browser.prod.mjs` : `browser.mjs`,\n  )\n})\n\ntest('Respect exports to take precedence over mainFields', async () => {\n  expect(await page.textContent('.exports-with-module')).toMatch('[success]')\n})\n\ntest('import and require resolve using module condition', async () => {\n  expect(await page.textContent('.exports-with-module-condition')).toMatch(\n    '[success]',\n  )\n  expect(\n    await page.textContent('.exports-with-module-condition-required'),\n  ).toMatch('[success]')\n})\n\ntest('implicit dir/index.js', async () => {\n  expect(await page.textContent('.index')).toMatch('[success]')\n})\n\ntest('implicit dir/index.js vs explicit file', async () => {\n  expect(await page.textContent('.dir-vs-file')).toMatch('[success]')\n})\n\ntest('nested extension', async () => {\n  expect(await page.textContent('.nested-extension')).toMatch(\n    '[success] file.json.js',\n  )\n})\n\ntest('exact extension vs. duplicated (.js.js)', async () => {\n  expect(await page.textContent('.exact-extension')).toMatch('[success]')\n})\n\ntest(\"don't add extension to directory name (./dir-with-ext.js/index.js)\", async () => {\n  expect(await page.textContent('.dir-with-ext')).toMatch('[success]')\n})\n\ntest('a ts module can import another ts module using its corresponding js file name', async () => {\n  expect(await page.textContent('.ts-extension')).toMatch('[success]')\n})\n\ntest('a js module can import another ts module using its corresponding js file name', async () => {\n  expect(await page.textContent('.js-ts-extension')).toMatch('[success]')\n})\n\ntest('filename with dot', async () => {\n  expect(await page.textContent('.dot')).toMatch('[success]')\n})\n\ntest.runIf(isWindows)('drive-relative path', async () => {\n  expect(await page.textContent('.drive-relative')).toMatch('[success]')\n})\n\ntest('absolute path', async () => {\n  expect(await page.textContent('.absolute')).toMatch('[success]')\n})\n\ntest('file url', async () => {\n  expect(await page.textContent('.file-url')).toMatch('[success]')\n})\n\ntest('browser field', async () => {\n  expect(await page.textContent('.browser')).toMatch('[success]')\n})\n\ntest('Resolve browser field even if module field exists', async () => {\n  expect(await page.textContent('.browser-module1')).toMatch('[success]')\n})\n\ntest('css entry', async () => {\n  expect(await page.textContent('.css')).toMatch('[success]')\n})\n\ntest('monorepo linked dep', async () => {\n  expect(await page.textContent('.monorepo')).toMatch('[success]')\n})\n\ntest('plugin resolved virtual file', async () => {\n  expect(await page.textContent('.virtual')).toMatch('[success]')\n})\n\ntest('plugin resolved virtual file that has import', async () => {\n  expect(await page.textContent('.virtual-has-import')).toMatch('[success]')\n})\n\ntest('plugin resolved custom virtual file', async () => {\n  expect(await page.textContent('.custom-virtual')).toMatch('[success]')\n})\n\ntest('virtual file with URL scheme should not be rewritten (#20803)', async () => {\n  expect(await page.textContent('.virtual-url-scheme')).toMatch('[success]')\n})\n\ntest('resolve inline package', async () => {\n  expect(await page.textContent('.inline-pkg')).toMatch('[success]')\n})\n\ntest('resolve.extensions', async () => {\n  expect(await page.textContent('.custom-ext')).toMatch('[success]')\n})\n\ntest('resolve.mainFields', async () => {\n  expect(await page.textContent('.custom-main-fields')).toMatch('[success]')\n})\n\ntest('resolve.mainFields.browser-first', async () => {\n  expect(await page.textContent('.custom-browser-main-field')).toBe(\n    'resolved browser field',\n  )\n})\n\ntest('resolve.conditions', async () => {\n  expect(await page.textContent('.custom-condition')).toMatch('[success]')\n})\n\ntest('resolve package that contains # in path', async () => {\n  expect(await page.textContent('.path-contains-sharp-symbol')).toMatch(\n    '[success] ok ok ok',\n  )\n})\n\ntest('Resolving top level with imports field', async () => {\n  expect(await page.textContent('.imports-top-level')).toMatch('[success]')\n})\n\ntest('Resolving same level with imports field', async () => {\n  expect(await page.textContent('.imports-same-level')).toMatch(\n    await page.textContent('.imports-top-level'),\n  )\n})\n\ntest('Resolving nested path with imports field', async () => {\n  expect(await page.textContent('.imports-nested')).toMatch('[success]')\n})\n\ntest('Resolving star with imports filed', async () => {\n  expect(await page.textContent('.imports-star')).toMatch('[success]')\n})\n\ntest('Resolving slash with imports filed', async () => {\n  expect(await page.textContent('.imports-slash')).toMatch('[success]')\n})\n\ntest('Resolving from other package with imports field', async () => {\n  expect(await page.textContent('.imports-pkg-slash')).toMatch('[success]')\n})\n\ntest('Resolving with query with imports field', async () => {\n  // since it is imported with `?url` it should return a URL\n  expect(await page.textContent('.imports-query')).toMatch(\n    isBuild ? /base64/ : '/imports-path/query.json',\n  )\n})\n\ntest('Resolving dot-prefixed directory with imports field', async () => {\n  expect(await page.textContent('.imports-dot-prefixed')).toMatch('[success]')\n})\n\ntest('Resolving #/ root alias pattern with imports field', async () => {\n  // This tests the new Node.js behavior from https://github.com/nodejs/node/pull/60864\n  // which allows \"#/*\" patterns (slash immediately after #) in package.json imports\n  expect(await page.textContent('.imports-root-slash')).toMatch('[success]')\n})\n\ntest(\"Resolve doesn't interrupt page request with trailing query and .css\", async () => {\n  await page.goto(viteTestUrl + '/?test.css')\n  expect(await page.locator('vite-error-overlay').count()).toBe(0)\n  expect(await page.textContent('h1')).toBe('Resolve')\n})\n\ntest('resolve non-normalized absolute path', async () => {\n  expect(await page.textContent('.non-normalized')).toMatch('[success]')\n})\n\ntest.runIf(!isWindows)(\n  \"Resolve doesn't interrupt page request that clashes with local project package.json\",\n  async () => {\n    // Sometimes request path may point to a different project's package.json, but for testing\n    // we point to Vite's own monorepo which always exists, and the package.json is not a library\n    const pathToViteMonorepoRoot = new URL('../../../', import.meta.url)\n    const urlPath = fileURLToPath(pathToViteMonorepoRoot).replace(/\\/$/, '')\n    await page.goto(viteTestUrl + urlPath)\n    expect(await page.locator('vite-error-overlay').count()).toBe(0)\n    expect(await page.textContent('h1')).toBe('Resolve')\n  },\n)\n\ntest.runIf(isBuild)('public dir is not copied', async () => {\n  expect(\n    fs.existsSync(path.resolve(testDir, 'dist/should-not-be-copied')),\n  ).toBe(false)\n})\n\ntest('import utf8-bom package', async () => {\n  expect(await page.textContent('.utf8-bom-package')).toMatch('[success]')\n})\n\ntest.runIf(isBuild)('sideEffects field glob pattern is respected', async () => {\n  const sideEffectValues = await page.evaluate(\n    () => (window as any).__SIDE_EFFECT,\n  )\n  expect(sideEffectValues).toStrictEqual(['success'])\n})\n\ndescribe.runIf(isServe)('HEAD request handling', () => {\n  test('HEAD request to JS file returns correct Content-Type', async () => {\n    const response = await fetch(new URL('/absolute.js', viteTestUrl), {\n      method: 'HEAD',\n    })\n    expect(response.headers.get('content-type')).toBe('text/javascript')\n    expect(response.status).toBe(200)\n    const text = await response.text()\n    expect(text).toBe('')\n  })\n\n  test('HEAD request to CSS file returns correct Content-Type', async () => {\n    const response = await fetch(new URL('/style.css', viteTestUrl), {\n      method: 'HEAD',\n      headers: {\n        Accept: 'text/css',\n      },\n    })\n    expect(response.headers.get('content-type')).toBe('text/css')\n    expect(response.status).toBe(200)\n  })\n})\n"
  },
  {
    "path": "playground/resolve/absolute.js",
    "content": "export default '[success] absolute'\n"
  },
  {
    "path": "playground/resolve/browser-field/bare-import.js",
    "content": "import message from '@vitejs/test-resolve-browser-field-bare-import-fail'\nexport default message\n"
  },
  {
    "path": "playground/resolve/browser-field/multiple.dot.path.js",
    "content": "const fs = require('node:fs')\nconsole.log('this should not run in the browser')\n"
  },
  {
    "path": "playground/resolve/browser-field/no-ext-index/index.js",
    "content": "import jsdom from 'jsdom' // should be redirected to empty module\nexport default ''\n"
  },
  {
    "path": "playground/resolve/browser-field/no-ext.js",
    "content": "import jsdom from 'jsdom' // should be redirected to empty module\nexport default ''\n"
  },
  {
    "path": "playground/resolve/browser-field/not-browser.js",
    "content": "const fs = require('node:fs')\nconsole.log('this should not run in the browser')\n"
  },
  {
    "path": "playground/resolve/browser-field/out/cjs.node.js",
    "content": "export default 'fail'\n"
  },
  {
    "path": "playground/resolve/browser-field/out/esm.browser.js",
    "content": "import jsdom from 'jsdom' // should be redirected to empty module\nexport default '[success] resolve browser field'\n"
  },
  {
    "path": "playground/resolve/browser-field/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-browser-field\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"//\": \"real world example: https://github.com/axios/axios/blob/3f2ef030e001547eb06060499f8a2e3f002b5a14/package.json#L71-L73\",\n  \"main\": \"out/cjs.node.js\",\n  \"browser\": {\n    \"./out/cjs.node.js\": \"./out/esm.browser.js\",\n    \"./no-ext\": \"./out/esm.browser.js\",\n    \"./ext.js\": \"./out/esm.browser.js\",\n    \"./ext-index/index.js\": \"./out/esm.browser.js\",\n    \"./no-ext-index\": \"./out/esm.browser.js\",\n    \"./bare-import\": \"./bare-import.js\",\n    \"./not-browser.js\": false,\n    \"./multiple.dot.path.js\": false,\n    \"jsdom\": false,\n    \"@vitejs/test-resolve-browser-field-bare-import-fail\": \"@vitejs/test-resolve-browser-field-bare-import-success\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-resolve-browser-field-bare-import-fail\": \"link:../browser-field-bare-import-fail\",\n    \"@vitejs/test-resolve-browser-field-bare-import-success\": \"link:../browser-field-bare-import-success\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/browser-field/relative.js",
    "content": "/* eslint-disable import-x/no-duplicates */\nimport ra from './no-ext'\nimport rb from './no-ext.js' // no substitution\nimport rc from './ext'\nimport rd from './ext.js'\nimport re from './ext-index/index.js'\nimport rf from './no-ext-index/index.js' // no substitution\n\nexport { ra, rb, rc, rd, re, rf }\n"
  },
  {
    "path": "playground/resolve/browser-field-bare-import-fail/main.js",
    "content": "export default '[fail]'\n"
  },
  {
    "path": "playground/resolve/browser-field-bare-import-fail/module.js",
    "content": "export default '[fail]'\n"
  },
  {
    "path": "playground/resolve/browser-field-bare-import-fail/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-browser-field-bare-import-fail\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"main.js\",\n  \"module\": \"module.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/resolve/browser-field-bare-import-success/main.js",
    "content": "export default '[fail]'\n"
  },
  {
    "path": "playground/resolve/browser-field-bare-import-success/module.js",
    "content": "export default '[success]'\n"
  },
  {
    "path": "playground/resolve/browser-field-bare-import-success/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-browser-field-bare-import-success\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"main.js\",\n  \"module\": \"module.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/resolve/browser-module-field1/index.js",
    "content": "export default '[fail] this should not run in the browser'\n"
  },
  {
    "path": "playground/resolve/browser-module-field1/index.web.js",
    "content": "export default '[success] this should run in browser'\n"
  },
  {
    "path": "playground/resolve/browser-module-field1/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-browser-module-field1\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"//\": \"real world example: https://github.com/aws/aws-sdk-js-v3/blob/59cdfd81452bce16bb26d07668e5550ed05d9d06/packages/credential-providers/package.json#L6-L7\",\n  \"module\": \"index.js\",\n  \"browser\": \"index.web.js\"\n}\n"
  },
  {
    "path": "playground/resolve/config-dep.cjs",
    "content": "module.exports = {\n  a: 1,\n}\n"
  },
  {
    "path": "playground/resolve/custom-browser-main-field/index.browser.js",
    "content": "export const msg = 'resolved browser field'\n"
  },
  {
    "path": "playground/resolve/custom-browser-main-field/index.custom.js",
    "content": "export const msg = 'resolved custom field'\n"
  },
  {
    "path": "playground/resolve/custom-browser-main-field/index.js",
    "content": "export const msg = '[fail] resolved main field'\n"
  },
  {
    "path": "playground/resolve/custom-browser-main-field/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-custom-browser-main-field\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"browser\": \"index.browser.js\",\n  \"custom\": \"index.custom.js\"\n}\n"
  },
  {
    "path": "playground/resolve/custom-condition/index.custom.js",
    "content": "export const msg = '[success] custom condition'\n"
  },
  {
    "path": "playground/resolve/custom-condition/index.js",
    "content": "export const msg = '[fail]'\n"
  },
  {
    "path": "playground/resolve/custom-condition/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-custom-condition\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"exports\": {\n    \".\": {\n      \"custom\": \"./index.custom.js\",\n      \"import\": \"./index.js\",\n      \"require\": \"./index.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/resolve/custom-ext.es",
    "content": "export const msg = `[success] custom ext`\n"
  },
  {
    "path": "playground/resolve/custom-main-field/index.custom.js",
    "content": "export const msg = '[success] custom main field'\n"
  },
  {
    "path": "playground/resolve/custom-main-field/index.js",
    "content": "export const msg = '[fail]'\n"
  },
  {
    "path": "playground/resolve/custom-main-field/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-custom-main-field\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\",\n  \"custom\": \"index.custom.js\"\n}\n"
  },
  {
    "path": "playground/resolve/dir/index.js",
    "content": "export const file = 'dir/index.js'\n"
  },
  {
    "path": "playground/resolve/dir-with-ext/index.js",
    "content": "export const file = '[success] ./dir-with-ext/index.js'\n"
  },
  {
    "path": "playground/resolve/dir-with-ext.js/empty",
    "content": ""
  },
  {
    "path": "playground/resolve/dir.js",
    "content": "export const file = '[success] dir.js'\n"
  },
  {
    "path": "playground/resolve/drive-relative.js",
    "content": "export default '[success] drive relative'\n"
  },
  {
    "path": "playground/resolve/exact-extension/file.js",
    "content": "export const file = '[success] file.js'\n"
  },
  {
    "path": "playground/resolve/exact-extension/file.js.js",
    "content": "export const file = 'file.js.js'\n"
  },
  {
    "path": "playground/resolve/exact-extension/file.json.js",
    "content": "export const file = '[success] file.json.js'\n"
  },
  {
    "path": "playground/resolve/exports-and-nested-scope/index.js",
    "content": ""
  },
  {
    "path": "playground/resolve/exports-and-nested-scope/nested-scope/file.js",
    "content": "'use strict'\n\n// intentionally use the default export here since default import from CJS has different semantics in node\nexport default '[success] ES .js file within root that has type: commonjs (thanks to a package scope)'\n"
  },
  {
    "path": "playground/resolve/exports-and-nested-scope/nested-scope/package.json",
    "content": "{\n  \"private\": true,\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/resolve/exports-and-nested-scope/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-and-nested-scope\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"commonjs\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./nested\": \"./nested-scope/file.js\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-env/browser.js",
    "content": "export const msg = 'fail (browser.js)'\n"
  },
  {
    "path": "playground/resolve/exports-env/browser.mjs",
    "content": "export const msg = '[success] exports env (browser.mjs)'\n"
  },
  {
    "path": "playground/resolve/exports-env/browser.prod.mjs",
    "content": "export const msg = '[success] exports env (browser.prod.mjs)'\n"
  },
  {
    "path": "playground/resolve/exports-env/fallback.umd.js",
    "content": "export const msg = 'fail (fallback.umd.js)'\n"
  },
  {
    "path": "playground/resolve/exports-env/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-env\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \"import\": {\n      \"browser\": {\n        \"production\": \"./browser.prod.mjs\",\n        \"development\": \"./browser.mjs\"\n      }\n    },\n    \"browser\": \"./browser.js\",\n    \"default\": \"./fallback.umd.js\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-from-root/file.js",
    "content": "export const msg = '[success] exports from root (./file.js)'\n"
  },
  {
    "path": "playground/resolve/exports-from-root/index.js",
    "content": ""
  },
  {
    "path": "playground/resolve/exports-from-root/nested/file.js",
    "content": "export const msg = 'fail exports from root (./nested/file.js)'\n"
  },
  {
    "path": "playground/resolve/exports-from-root/nested/package.json",
    "content": "{\n  \"exports\": {\n    \".\": \"./file.js\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-from-root/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-from-root\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./nested\": \"./file.js\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-legacy-fallback/dir/index.js",
    "content": "export const msg = '[fail] mapped js file'\n"
  },
  {
    "path": "playground/resolve/exports-legacy-fallback/dir/index.mjs",
    "content": "export const msg = '[success] mapped mjs file'\n"
  },
  {
    "path": "playground/resolve/exports-legacy-fallback/dir/package.json",
    "content": "{\n  \"main\": \"index.js\",\n  \"module\": \"index.mjs\"\n}\n"
  },
  {
    "path": "playground/resolve/exports-legacy-fallback/index.js",
    "content": "export default 5\n"
  },
  {
    "path": "playground/resolve/exports-legacy-fallback/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-legacy-fallback\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \"./dir\": {\n      \"import\": \"./dir/index.mjs\",\n      \"require\": \"./dir/index.js\"\n    },\n    \".\": \"index.js\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-path/cjs.js",
    "content": "exports.msg = 'from cjs'\n"
  },
  {
    "path": "playground/resolve/exports-path/deep.js",
    "content": "export const msg = '[success] deep resolve from exports'\n"
  },
  {
    "path": "playground/resolve/exports-path/deep.json",
    "content": "{\n  \"foo\": \"json\"\n}\n"
  },
  {
    "path": "playground/resolve/exports-path/dir/dir.js",
    "content": "export const msg = '[success] mapped directory from exports'\n"
  },
  {
    "path": "playground/resolve/exports-path/main.js",
    "content": "export const msg = '[success] entry resolve from exports'\n"
  },
  {
    "path": "playground/resolve/exports-path/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-path\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \".\": {\n      \"import\": \"./main.js\",\n      \"require\": \"./cjs.js\"\n    },\n    \"./deep.js\": \"./deep.js\",\n    \"./deep.json\": \"./deep.json\",\n    \"./dir/\": \"./dir/\",\n    \"./dir-mapped/*\": {\n      \"import\": \"./dir/*\",\n      \"require\": \"./dir-cjs/*\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-with-module/import.mjs",
    "content": "// import.mjs should take precedence\nexport const msg = '[success] exports with module (import.mjs)'\n"
  },
  {
    "path": "playground/resolve/exports-with-module/module.mjs",
    "content": "// import.mjs should take precedence\nexport const msg = '[fail] exports with module (module.mjs)'\n"
  },
  {
    "path": "playground/resolve/exports-with-module/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-with-module\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"commonjs\",\n  \"module\": \"./module.mjs\",\n  \"exports\": {\n    \"import\": \"./import.mjs\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-with-module-condition/index.esm.js",
    "content": "export const msg = '[success] exports with module condition (index.esm.js)'\n"
  },
  {
    "path": "playground/resolve/exports-with-module-condition/index.js",
    "content": "/* eslint-disable import-x/no-commonjs */\nmodule.exports.msg = '[fail] exports with module condition (index.js)'\n"
  },
  {
    "path": "playground/resolve/exports-with-module-condition/index.mjs",
    "content": "export const msg = '[fail] exports with module condition (index.mjs)'\n"
  },
  {
    "path": "playground/resolve/exports-with-module-condition/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-with-module-condition\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \"module\": \"./index.esm.js\",\n    \"import\": \"./index.mjs\",\n    \"require\": \"./index.js\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/exports-with-module-condition-required/index.cjs",
    "content": "const { msg } = require('@vitejs/test-resolve-exports-with-module-condition')\nmodule.exports = { msg }\n"
  },
  {
    "path": "playground/resolve/exports-with-module-condition-required/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-exports-with-module-condition-required\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.cjs\",\n  \"dependencies\": {\n    \"@vitejs/test-resolve-exports-with-module-condition\": \"link:../exports-with-module-condition\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/file-url.js",
    "content": "export default '[success] file-url'\n"
  },
  {
    "path": "playground/resolve/imports-path/.dot-prefixed/index.js",
    "content": "export const msg = '[success] dot-prefixed subpath imports'\n"
  },
  {
    "path": "playground/resolve/imports-path/importer.js",
    "content": "import { msg } from '#dot-prefixed'\n\nexport { msg }\n"
  },
  {
    "path": "playground/resolve/imports-path/nested-path.js",
    "content": "export const msg = '[success] nested path subpath imports'\n"
  },
  {
    "path": "playground/resolve/imports-path/other-pkg/nest/index.js",
    "content": "export const msg = '[success] subpath imports from other package'\n"
  },
  {
    "path": "playground/resolve/imports-path/other-pkg/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-imports-pkg\",\n  \"private\": true\n}\n"
  },
  {
    "path": "playground/resolve/imports-path/query.json",
    "content": "{\n  \"foo\": \"json\"\n}\n"
  },
  {
    "path": "playground/resolve/imports-path/root-slash/index.js",
    "content": "export const msg = '[success] subpath imports with #/ root alias pattern'\n"
  },
  {
    "path": "playground/resolve/imports-path/same-level.js",
    "content": "export * from '#top-level'\n"
  },
  {
    "path": "playground/resolve/imports-path/slash/index.js",
    "content": "export const msg = '[success] subpath imports with slash'\n"
  },
  {
    "path": "playground/resolve/imports-path/star/index.js",
    "content": "export const msg = '[success] subpath imports with star'\n"
  },
  {
    "path": "playground/resolve/imports-path/top-level.js",
    "content": "export const msg = '[success] top level subpath imports'\n"
  },
  {
    "path": "playground/resolve/index.html",
    "content": "<h1>Resolve</h1>\n\n<h2>Utf8-bom import</h2>\n<p class=\"utf8-bom\">fail</p>\n\n<h2>Deep import</h2>\n<p>Should show [2,4]:<span class=\"pre deep-import\">fail</span></p>\n\n<h2>Exports and a nested package scope with a different type</h2>\n<p class=\"exports-and-nested-scope\">fail</p>\n\n<h2>Entry resolving with exports field</h2>\n<p class=\"exports-entry\">fail</p>\n\n<h2>Deep import with exports field</h2>\n<p class=\"exports-deep\">fail</p>\n\n<h2>Deep import with query with exports field</h2>\n<p class=\"exports-deep-query\">fail</p>\n\n<h2>Deep import with exports field + exposed directory</h2>\n<p class=\"exports-deep-exposed-dir\">fail</p>\n\n<h2>Deep import with exports field + mapped directory</h2>\n<p class=\"exports-deep-mapped-dir\">fail</p>\n\n<h2>Exports field env priority</h2>\n<p class=\"exports-env\">fail</p>\n\n<h2>Exports field read only from the root package.json</h2>\n<p class=\"exports-from-root\">fail</p>\n\n<h2>Exports with legacy fallback</h2>\n<p class=\"exports-legacy-fallback\">fail</p>\n\n<h2>Exports with module</h2>\n<p class=\"exports-with-module\">fail</p>\n\n<h2>\n  Both import and require resolve using module condition (avoids dual package\n  hazard)\n</h2>\n<p class=\"exports-with-module-condition\">fail</p>\n<p class=\"exports-with-module-condition-required\">fail</p>\n\n<h2>Resolving top level with imports field</h2>\n<p class=\"imports-top-level\">fail</p>\n\n<h2>Resolving same level with imports field</h2>\n<p class=\"imports-same-level\">fail</p>\n\n<h2>Resolving nested path with imports field</h2>\n<p class=\"imports-nested\">fail</p>\n\n<h2>Resolving star with imports filed</h2>\n<p class=\"imports-star\">fail</p>\n\n<h2>Resolving slash with imports filed</h2>\n<p class=\"imports-slash\">fail</p>\n\n<h2>Resolving from other package with imports field</h2>\n<p class=\"imports-pkg-slash\">fail</p>\n\n<h2>Resolving with query with imports field</h2>\n<p class=\"imports-query\">fail</p>\n\n<h2>Resolving dot-prefixed directory with imports field</h2>\n<p class=\"imports-dot-prefixed\">fail</p>\n\n<h2>Resolving #/ root alias pattern with imports field</h2>\n<p class=\"imports-root-slash\">fail</p>\n\n<h2>Resolve /index.*</h2>\n<p class=\"index\">fail</p>\n\n<h2>Resolve dir and file of the same name (should prioritize file)</h2>\n<p class=\"dir-vs-file\">fail</p>\n\n<h2>Resolve to non-duplicated file extension</h2>\n<p class=\"exact-extension\">fail</p>\n\n<h2>Resolve nested file extension</h2>\n<p class=\"nested-extension\">fail</p>\n\n<h2>Don't add extensions to directory names</h2>\n<p class=\"dir-with-ext\">fail</p>\n\n<h2>\n  A ts module can import another ts module using its corresponding js file name\n</h2>\n<p class=\"ts-extension\">fail</p>\n\n<h2>\n  A ts module can import another tsx module using its corresponding jsx file\n  name\n</h2>\n<p class=\"jsx-extension\">fail</p>\n\n<h2>\n  A ts module can import another tsx module using its corresponding js file name\n</h2>\n<p class=\"tsx-extension\">fail</p>\n\n<h2>\n  A ts module can import another ESM module using its corresponding mjs file\n  name\n</h2>\n<p class=\"mjs-extension\">fail</p>\n\n<h2>\n  A ts module can import another ESM module using its corresponding mjs file\n  name with query parameters\n</h2>\n<p class=\"mjs-extension-with-query\">fail</p>\n\n<h2>\n  A ts module can import another CommonJS module using its corresponding cjs\n  file name\n</h2>\n<p class=\"cjs-extension\">fail</p>\n\n<h2>A js module can import TS modules using its corresponding js file name</h2>\n<p class=\"js-ts-extension\">fail</p>\n\n<h2>Resolve file name containing dot</h2>\n<p class=\"dot\">fail</p>\n\n<h2>Resolve drive-relative path (Windows only)</h2>\n<p class=\"drive-relative\">fail</p>\n\n<h2>Resolve absolute path</h2>\n<p class=\"absolute\">fail</p>\n\n<h2>Resolve file url</h2>\n<p class=\"file-url\">fail</p>\n\n<h2>Browser Field</h2>\n<p class=\"browser\">fail</p>\n\n<h2>Resolve browser field even if module field exists</h2>\n<p class=\"browser-module1\">fail</p>\n\n<h2>CSS Entry</h2>\n<p class=\"css\"></p>\n\n<h2>Monorepo linked dep</h2>\n<p class=\"monorepo\"></p>\n\n<h2>Plugin resolved virtual file</h2>\n<p class=\"virtual\"></p>\n\n<h2>Plugin resolved virtual file (#9036)</h2>\n<p class=\"virtual-9036\"></p>\n\n<h2>Plugin resolved virtual file that has import</h2>\n<p class=\"virtual-has-import\"></p>\n\n<h2>Plugin resolved custom virtual file</h2>\n<p class=\"custom-virtual\"></p>\n\n<h2>Virtual file with URL scheme</h2>\n<p class=\"virtual-url-scheme\"></p>\n\n<h2>Inline package</h2>\n<p class=\"inline-pkg\"></p>\n\n<h2>resolve.extensions</h2>\n<p class=\"custom-ext\"></p>\n\n<h2>resolve.mainFields</h2>\n<p class=\"custom-main-fields\"></p>\n\n<h2>resolve.mainFields.custom-browser-main</h2>\n<p class=\"custom-browser-main-field\"></p>\n\n<h2>resolve.conditions</h2>\n<p class=\"custom-condition\"></p>\n\n<h2>resolve package that contains # in path</h2>\n<p class=\"path-contains-sharp-symbol\"></p>\n\n<h2>resolve non normalized absolute path</h2>\n<p class=\"non-normalized\"></p>\n\n<h2>utf8-bom-package</h2>\n<p class=\"utf8-bom-package\">fail</p>\n\n<script type=\"module\">\n  import '@generated-content-virtual-file'\n  function text(selector, text) {\n    document.querySelector(selector).textContent = text\n  }\n\n  // import from a utf-8 bom file\n  import { msg as bomMsg } from './utf8-bom/main.js'\n  text('.utf8-bom', bomMsg)\n\n  // deep import\n  import slicedToArray from '@babel/runtime/helpers/esm/slicedToArray'\n\n  const iterable = (function* () {\n    yield 2\n    yield 4\n    yield 6\n    yield 8\n  })()\n\n  text('.deep-import', JSON.stringify(slicedToArray(iterable, 2)))\n\n  import exportsAndNestedScopeMsg from '@vitejs/test-resolve-exports-and-nested-scope/nested'\n  text('.exports-and-nested-scope', exportsAndNestedScopeMsg)\n\n  // exports field\n  import { msg } from '@vitejs/test-resolve-exports-path'\n  text('.exports-entry', msg)\n\n  // deep import w/ exports\n  import { msg as deepMsg } from '@vitejs/test-resolve-exports-path/deep.js'\n  text('.exports-deep', deepMsg)\n\n  // deep import w/ exports w/ query\n  import deepPath from '@vitejs/test-resolve-exports-path/deep.json?url'\n  text('.exports-deep-query', deepPath)\n\n  // deep import w/ exposed dir\n  import { msg as exposedDirMsg } from '@vitejs/test-resolve-exports-path/dir/dir'\n  text('.exports-deep-exposed-dir', exposedDirMsg)\n\n  // deep import w/ mapped dir\n  import { msg as mappedDirMsg } from '@vitejs/test-resolve-exports-path/dir-mapped/dir'\n  text('.exports-deep-mapped-dir', mappedDirMsg)\n\n  import { msg as exportsEnvMsg } from '@vitejs/test-resolve-exports-env'\n  text('.exports-env', exportsEnvMsg)\n\n  import { msg as exportsFromRootMsg } from '@vitejs/test-resolve-exports-from-root/nested'\n  text('.exports-from-root', exportsFromRootMsg)\n\n  import { msg as exportsLegacyFallbackMsg } from '@vitejs/test-resolve-exports-legacy-fallback/dir'\n  text('.exports-legacy-fallback', exportsLegacyFallbackMsg)\n\n  import { msg as exportsWithModule } from '@vitejs/test-resolve-exports-with-module'\n  text('.exports-with-module', exportsWithModule)\n\n  import { msg as exportsWithModuleCondition } from '@vitejs/test-resolve-exports-with-module-condition'\n  import { msg as exportsWithModuleConditionRequired } from '@vitejs/test-resolve-exports-with-module-condition-required'\n  text('.exports-with-module-condition', exportsWithModuleCondition)\n  text(\n    '.exports-with-module-condition-required',\n    exportsWithModuleConditionRequired,\n  )\n\n  // imports field\n  import { msg as importsTopLevel } from '#top-level'\n  text('.imports-top-level', importsTopLevel)\n\n  import { msg as importsSameLevel } from '#same-level'\n  text('.imports-same-level', importsSameLevel)\n\n  import { msg as importsNested } from '#nested/path.js'\n  text('.imports-nested', importsNested)\n\n  import { msg as importsStar } from '#star/index.js'\n  text('.imports-star', importsStar)\n\n  import { msg as importsSlash } from '#slash/index.js'\n  text('.imports-slash', importsSlash)\n\n  import { msg as importsPkgSlash } from '#other-pkg-slash/index.js'\n  text('.imports-pkg-slash', importsPkgSlash)\n\n  import importsQuery from '#query?url'\n  text('.imports-query', importsQuery)\n\n  import { msg as importsDotPrefixed } from './imports-path/importer.js'\n  text('.imports-dot-prefixed', importsDotPrefixed)\n\n  import { msg as importsRootSlash } from '#/index.js'\n  text('.imports-root-slash', importsRootSlash)\n\n  // implicit index resolving\n  import { foo } from './util'\n  text('.index', foo())\n\n  // implicit dir index vs. file\n  import { file } from './dir'\n  text('.dir-vs-file', file)\n\n  // exact extension vs. duplicated (.js.js)\n  import { file as exactExtMsg } from './exact-extension/file.js'\n  text('.exact-extension', exactExtMsg)\n\n  // nested extension\n  import { file as fileJsonMsg } from './exact-extension/file.json'\n  text('.nested-extension', fileJsonMsg)\n\n  // don't add extensions to dir name (./dir-with-ext.js/index.js)\n  import { file as dirWithExtMsg } from './dir-with-ext'\n  text('.dir-with-ext', dirWithExtMsg)\n\n  import { msg as tsExtensionMsg } from './ts-extension'\n  text('.ts-extension', tsExtensionMsg)\n\n  import { msgJsx as tsJsxExtensionMsg } from './ts-extension'\n  text('.jsx-extension', tsJsxExtensionMsg)\n\n  import { msgTsx as tsTsxExtensionMsg } from './ts-extension'\n  text('.tsx-extension', tsTsxExtensionMsg)\n\n  import { msgCjs as tsCjsExtensionMsg } from './ts-extension'\n  text('.cjs-extension', tsCjsExtensionMsg)\n\n  import { msgMjs as tsMjsExtensionMsg } from './ts-extension'\n  text('.mjs-extension', tsMjsExtensionMsg)\n\n  import { msgMjs as tsMjsExtensionWithQueryMsg } from './ts-extension?query=1'\n  text('.mjs-extension-with-query', tsMjsExtensionWithQueryMsg)\n\n  import { msg as jsTsExtensionMsg } from './ts-extension/index-js.js'\n  text('.js-ts-extension', jsTsExtensionMsg)\n\n  // filename with dot\n  import { bar } from './util/bar.util'\n  text('.dot', bar())\n\n  // browser field\n  import main from '@vitejs/test-resolve-browser-field'\n\n  import a from '@vitejs/test-resolve-browser-field/no-ext'\n  import b from '@vitejs/test-resolve-browser-field/no-ext.js' // no substitution\n  import c from '@vitejs/test-resolve-browser-field/ext'\n  import d from '@vitejs/test-resolve-browser-field/ext.js'\n  import e from '@vitejs/test-resolve-browser-field/ext-index/index.js'\n  // webpack does not support this case, so should be fine\n  // import f from '@vitejs/test-resolve-browser-field/ext-index'\n  import g from '@vitejs/test-resolve-browser-field/no-ext-index/index.js' // no substitution\n  import h from '@vitejs/test-resolve-browser-field/no-ext?query'\n  import i from '@vitejs/test-resolve-browser-field/bare-import'\n\n  import {\n    ra,\n    rb,\n    rc,\n    rd,\n    re,\n    rf,\n  } from '@vitejs/test-resolve-browser-field/relative'\n\n  const success = [main, a, c, d, e, h, i, ra, rc, rd, re]\n  const noSuccess = [b, g, rb, rf]\n\n  if (\n    [...success, ...noSuccess].filter((text) => text.includes('[success]'))\n      .length === success.length\n  ) {\n    text('.browser', main)\n  }\n\n  import browserModule1 from '@vitejs/test-resolve-browser-module-field1'\n  text('.browser-module1', browserModule1)\n\n  import { msg as customExtMsg } from './custom-ext'\n  text('.custom-ext', customExtMsg)\n\n  import { msg as customMainMsg } from '@vitejs/test-resolve-custom-main-field'\n  text('.custom-main-fields', customMainMsg)\n\n  import { msg as customBrowserMsg } from '@vitejs/test-resolve-custom-browser-main-field'\n  text('.custom-browser-main-field', customBrowserMsg)\n\n  import { msg as customConditionMsg } from '@vitejs/test-resolve-custom-condition'\n  text('.custom-condition', customConditionMsg)\n\n  // should be ok to import a file marked with browser: false\n  import '@vitejs/test-resolve-browser-field/not-browser'\n  import '@vitejs/test-resolve-browser-field/multiple.dot.path'\n\n  // css entry\n  import css from 'normalize.css?inline'\n  if (typeof css === 'string') {\n    text('.css', '[success] resolve package with css entry file')\n  }\n\n  // monorepo linked dep w/ upper directory import\n  import { msg as linkedMsg } from '@vitejs/test-resolve-linked'\n  text('.monorepo', linkedMsg)\n\n  import { msg as virtualMsg } from '@virtual-file'\n  text('.virtual', virtualMsg)\n\n  import { msg as virtualMsg9036 } from 'virtual:file-9036.js'\n  text('.virtual-9036', virtualMsg9036)\n\n  import { msg as virtualMsgHasImport } from 'virtual:file-has-import.js'\n  text('.virtual-has-import', virtualMsgHasImport)\n\n  import { msg as customVirtualMsg } from '@custom-virtual-file'\n  text('.custom-virtual', customVirtualMsg)\n\n  import { msg as virtualUrlSchemeMsg } from 'virtual-with-scheme'\n  text('.virtual-url-scheme', virtualUrlSchemeMsg)\n\n  import { msg as inlineMsg } from './inline-package'\n  text('.inline-pkg', inlineMsg)\n\n  import { test as sharp1 } from '@vitejs/test-resolve-sharp-dir'\n  import { test as sharp2 } from '@vitejs/test-resolve-sharp-dir-nested'\n  import { test as sharp3 } from '@vitejs/test-resolve-sharp-dir-nested/#/index.cjs'\n\n  text(\n    '.path-contains-sharp-symbol',\n    `[success] ${sharp1('ok')} ${sharp2('ok')} ${sharp3('ok')}`,\n  )\n\n  import nonNormalizedAbsolute from '@non-normalized'\n  text('.non-normalized', nonNormalizedAbsolute)\n\n  import { msg as utf8BomPackage } from '@vitejs/test-utf8-bom-package'\n  text('.utf8-bom-package', utf8BomPackage)\n\n  import '@vitejs/test-resolve-side-effects-glob'\n</script>\n\n<style>\n  .pre {\n    display: block;\n    unicode-bidi: embed;\n    font-family: monospace;\n    white-space: pre;\n  }\n</style>\n"
  },
  {
    "path": "playground/resolve/inline-package/inline.js",
    "content": "export const msg = '[success] from inline package'\n"
  },
  {
    "path": "playground/resolve/inline-package/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-inline-package\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"sideEffects\": false,\n  \"main\": \"./inline\"\n}\n"
  },
  {
    "path": "playground/resolve/non-normalized.js",
    "content": "export default '[success] non normalized absolute path'\n"
  },
  {
    "path": "playground/resolve/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"imports\": {\n    \"#top-level\": \"./imports-path/top-level.js\",\n    \"#same-level\": \"./imports-path/same-level.js\",\n    \"#nested/path.js\": \"./imports-path/nested-path.js\",\n    \"#star/*\": \"./imports-path/star/*\",\n    \"#slash/\": \"./imports-path/slash/\",\n    \"#other-pkg-slash/\": \"@vitejs/test-resolve-imports-pkg/nest/\",\n    \"#query\": \"./imports-path/query.json\",\n    \"#dot-prefixed\": \"./imports-path/.dot-prefixed/index.js\",\n    \"#/*\": \"./imports-path/root-slash/*\"\n  },\n  \"dependencies\": {\n    \"@babel/runtime\": \"^7.28.6\",\n    \"normalize.css\": \"^8.0.1\",\n    \"@vitejs/test-resolve-browser-field\": \"link:./browser-field\",\n    \"@vitejs/test-resolve-browser-module-field1\": \"link:./browser-module-field1\",\n    \"@vitejs/test-resolve-custom-condition\": \"link:./custom-condition\",\n    \"@vitejs/test-resolve-custom-main-field\": \"link:./custom-main-field\",\n    \"@vitejs/test-resolve-custom-browser-main-field\": \"link:./custom-browser-main-field\",\n    \"@vitejs/test-resolve-exports-and-nested-scope\": \"link:./exports-and-nested-scope\",\n    \"@vitejs/test-resolve-exports-env\": \"link:./exports-env\",\n    \"@vitejs/test-resolve-exports-from-root\": \"link:./exports-from-root\",\n    \"@vitejs/test-resolve-exports-legacy-fallback\": \"link:./exports-legacy-fallback\",\n    \"@vitejs/test-resolve-exports-path\": \"link:./exports-path\",\n    \"@vitejs/test-resolve-exports-with-module\": \"link:./exports-with-module\",\n    \"@vitejs/test-resolve-exports-with-module-condition\": \"link:./exports-with-module-condition\",\n    \"@vitejs/test-resolve-exports-with-module-condition-required\": \"link:./exports-with-module-condition-required\",\n    \"@vitejs/test-resolve-linked\": \"workspace:*\",\n    \"@vitejs/test-resolve-imports-pkg\": \"link:./imports-path/other-pkg\",\n    \"@vitejs/test-resolve-sharp-dir\": \"link:./sharp-dir\",\n    \"@vitejs/test-resolve-sharp-dir-nested\": \"file:./sharp-dir-nested\",\n    \"@vitejs/test-resolve-side-effects-glob\": \"link:./side-effects-glob\",\n    \"@vitejs/test-utf8-bom-package\": \"link:./utf8-bom-package\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/public/should-not-be-copied",
    "content": ""
  },
  {
    "path": "playground/resolve/sharp-dir/index.cjs",
    "content": "module.exports = {\n  test: require('@vitejs/test-resolve-sharp-dir-nested/#/index.cjs').test,\n}\n"
  },
  {
    "path": "playground/resolve/sharp-dir/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-sharp-dir\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"./index.cjs\",\n  \"dependencies\": {\n    \"@vitejs/test-resolve-sharp-dir-nested\": \"file:../sharp-dir-nested\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/sharp-dir-nested/#/index.cjs",
    "content": "module.exports = {\n  test: (msg) => msg,\n}\n"
  },
  {
    "path": "playground/resolve/sharp-dir-nested/index.cjs",
    "content": "module.exports = {\n  test: require('./#/index.cjs').test,\n}\n"
  },
  {
    "path": "playground/resolve/sharp-dir-nested/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-sharp-dir-nested\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"./index.cjs\"\n}\n"
  },
  {
    "path": "playground/resolve/side-effects-glob/effects/file.js",
    "content": ";(window.__SIDE_EFFECT ||= []).push('success')\n"
  },
  {
    "path": "playground/resolve/side-effects-glob/index.js",
    "content": "import './effects/file.js'\nimport './no-effect.js'\n"
  },
  {
    "path": "playground/resolve/side-effects-glob/no-effect.js",
    "content": ";(window.__SIDE_EFFECT ||= []).push('failure')\n"
  },
  {
    "path": "playground/resolve/side-effects-glob/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-side-effects-glob\",\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"sideEffects\": [\n    \"index.js\",\n    \"effects/*\"\n  ]\n}\n"
  },
  {
    "path": "playground/resolve/style.css",
    "content": "/* Simple CSS for HEAD request testing */\nbody {\n  margin: 0;\n  padding: 0;\n}\n"
  },
  {
    "path": "playground/resolve/ts-extension/hello.ts",
    "content": "export const msg = '[success] use .js extension to import a ts module'\n"
  },
  {
    "path": "playground/resolve/ts-extension/hellocjs.cts",
    "content": "export const msgCjs = '[success] use .cjs extension to import a CommonJS module'\n"
  },
  {
    "path": "playground/resolve/ts-extension/hellojsx.tsx",
    "content": "export const msgJsx = '[success] use .jsx extension to import a tsx module'\n"
  },
  {
    "path": "playground/resolve/ts-extension/hellomjs.mts",
    "content": "export const msgMjs = '[success] use .mjs extension to import an ESM module'\n"
  },
  {
    "path": "playground/resolve/ts-extension/hellotsx.tsx",
    "content": "export const msgTsx = '[success] use .js extension to import a tsx module'\n"
  },
  {
    "path": "playground/resolve/ts-extension/index-js.js",
    "content": "import { msg as msgJs } from './hello.js'\nimport { msgJsx } from './hellojsx.jsx'\nimport { msgTsx } from './hellotsx.js'\nimport { msgCjs } from './hellocjs.cjs'\nimport { msgMjs } from './hellomjs.mjs'\n\nexport const msg =\n  msgJs && msgJsx && msgTsx && msgCjs && msgMjs\n    ? '[success] use .js / .jsx / .cjs / .mjs extension to import a TS modules'\n    : '[fail]'\n"
  },
  {
    "path": "playground/resolve/ts-extension/index.ts",
    "content": "import { msg } from './hello.js'\nimport { msgJsx } from './hellojsx.jsx'\nimport { msgTsx } from './hellotsx.js'\nimport { msgCjs } from './hellocjs.cjs'\nimport { msgMjs } from './hellomjs.mjs'\n\nexport { msg, msgJsx, msgTsx, msgCjs, msgMjs }\n"
  },
  {
    "path": "playground/resolve/utf8-bom/main.js",
    "content": "﻿import '@babel/runtime/helpers/esm/slicedToArray'\n\nexport const msg = '[success]'\n"
  },
  {
    "path": "playground/resolve/utf8-bom-package/index.mjs",
    "content": "﻿export const msg = '[success]'\n"
  },
  {
    "path": "playground/resolve/utf8-bom-package/package.json",
    "content": "﻿{\n  \"name\": \"@vitejs/test-utf8-bom-package\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"exports\": {\n    \".\": \"./index.mjs\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve/util/bar.util.js",
    "content": "export function bar() {\n  return '[success] resolve filename containing dot and omitting ext'\n}\n"
  },
  {
    "path": "playground/resolve/util/index.js",
    "content": "export function foo() {\n  return '[success] resolve omitted /index.*'\n}\n"
  },
  {
    "path": "playground/resolve/vite.config-mainfields-custom-first.js",
    "content": "import config from './vite.config.js'\nconfig.resolve.mainFields = [\n  'custom',\n  ...config.resolve.mainFields.filter((f) => f !== 'custom'),\n]\nconfig.build.outDir = 'dist-mainfields-custom-first'\nexport default config\n"
  },
  {
    "path": "playground/resolve/vite.config.js",
    "content": "import path from 'node:path'\nimport { defaultClientConditions, defineConfig, normalizePath } from 'vite'\nimport { a } from './config-dep.cjs'\n\nconst virtualFile = '@virtual-file'\nconst virtualId = '\\0' + virtualFile\n\nconst virtualFile9036 = 'virtual:file-9036.js'\nconst virtualId9036 = '\\0' + virtualFile9036\n\nconst virtualFileHasImport = 'virtual:file-has-import.js'\nconst virtualIdHasImport = '/file-has-import.js'\n\nconst customVirtualFile = '@custom-virtual-file'\n\nconst virtualFileWithScheme = 'virtual-with-scheme'\nconst virtualIdWithScheme = '\\0https://example.com/virtual.js'\n\nconst generatedContentVirtualFile = '@generated-content-virtual-file'\nconst generatedContentImports = [\n  {\n    specifier: normalizePath(\n      path\n        .resolve(import.meta.dirname, './drive-relative.js')\n        .replace(/^[a-zA-Z]:/, ''),\n    ),\n    elementQuery: '.drive-relative',\n  },\n  {\n    specifier: normalizePath(\n      path.resolve(import.meta.dirname, './absolute.js'),\n    ),\n    elementQuery: '.absolute',\n  },\n  {\n    specifier: new URL('file-url.js', import.meta.url),\n    elementQuery: '.file-url',\n  },\n]\n\nexport default defineConfig({\n  resolve: {\n    extensions: ['.mjs', '.js', '.es', '.ts'],\n    mainFields: ['browser', 'custom', 'module'],\n    conditions: [...defaultClientConditions, 'custom'],\n  },\n  define: {\n    VITE_CONFIG_DEP_TEST: a,\n  },\n  plugins: [\n    {\n      name: 'virtual-module',\n      resolveId(id) {\n        if (id === virtualFile) {\n          return virtualId\n        }\n      },\n      load(id) {\n        if (id === virtualId) {\n          return `export const msg = \"[success] from conventional virtual file\"`\n        }\n      },\n    },\n    {\n      name: 'virtual-module-9036',\n      resolveId(id) {\n        if (id === virtualFile9036) {\n          return virtualId9036\n        }\n      },\n      load(id) {\n        if (id === virtualId9036) {\n          return `export const msg = \"[success] from virtual file #9036\"`\n        }\n      },\n    },\n    {\n      name: 'virtual-module-has-import',\n      enforce: 'pre',\n      resolveId(id, _importer, opts) {\n        if (id === virtualFileHasImport) {\n          // make scanner happy\n          // @ts-expect-error -- opts.scan is internal\n          if (opts?.scan) {\n            return normalizePath(\n              path.resolve(import.meta.dirname, './exports-path/main.js'),\n            )\n          }\n          return virtualIdHasImport\n        }\n      },\n      load(id) {\n        if (id === virtualIdHasImport) {\n          return (\n            'import { msg as importedMsg } from \"@vitejs/test-resolve-exports-path\"\\n' +\n            'export const msg = importedMsg.includes(\"[success]\") ? \"[success] from virtual file that has import\" : \"[failure]\"'\n          )\n        }\n      },\n    },\n    {\n      name: 'custom-resolve',\n      resolveId(id) {\n        if (id === customVirtualFile) {\n          return id\n        }\n      },\n      load(id) {\n        if (id === customVirtualFile) {\n          return `export const msg = \"[success] from custom virtual file\"`\n        }\n      },\n    },\n    {\n      name: 'virtual-url-scheme-test',\n      resolveId(id) {\n        if (id === virtualFileWithScheme) {\n          return virtualIdWithScheme\n        }\n      },\n      load(id) {\n        if (id === virtualIdWithScheme) {\n          return `export const msg = \"[success] from virtual file with URL scheme\"`\n        }\n      },\n    },\n    {\n      name: 'generated-content',\n      resolveId(id) {\n        if (id === generatedContentVirtualFile) {\n          return id\n        }\n      },\n      load(id) {\n        if (id === generatedContentVirtualFile) {\n          const tests = generatedContentImports\n            .map(\n              ({ specifier, elementQuery }, i) =>\n                `import content${i} from ${JSON.stringify(specifier)}\\n` +\n                `text(${JSON.stringify(elementQuery)}, content${i})`,\n            )\n            .join('\\n')\n\n          return (\n            'function text(selector, text) {\\n' +\n            '  document.querySelector(selector).textContent = text\\n' +\n            '}\\n\\n' +\n            tests\n          )\n        }\n      },\n    },\n    {\n      name: 'resolve to non normalized absolute',\n      async resolveId(id) {\n        if (id !== '@non-normalized') return\n        return this.resolve(import.meta.dirname + '//non-normalized')\n      },\n    },\n  ],\n  optimizeDeps: {\n    include: [\n      '@vitejs/test-resolve-exports-with-module-condition-required',\n      '@vitejs/test-resolve-sharp-dir',\n    ],\n  },\n  build: {\n    copyPublicDir: false,\n  },\n})\n"
  },
  {
    "path": "playground/resolve-linked/dep.js",
    "content": "export const msg = 'dep from upper directory'\n"
  },
  {
    "path": "playground/resolve-linked/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-linked\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"src/index.js\"\n}\n"
  },
  {
    "path": "playground/resolve-linked/src/index.js",
    "content": "import { msg as depMsg } from '../dep'\n\nexport const msg = `[success] out of root monorepo dep with ${depMsg}`\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/__tests__/resolve.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { page } from '~utils'\n\ntest('import from .ts', async () => {\n  await expect.poll(() => page.textContent('.ts')).toMatch('[success]')\n})\n\ntest('import from .js', async () => {\n  await expect.poll(() => page.textContent('.js')).toMatch('[success]')\n})\n\ntest('fallback works', async () => {\n  await expect.poll(() => page.textContent('.fallback')).toMatch('[success]')\n})\n\ntest('nested tsconfig.json & references / include works', async () => {\n  await expect.poll(() => page.textContent('.nested-a')).toMatch('[success]')\n  await expect.poll(() => page.textContent('.nested-b')).toMatch('[success]')\n})\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/fallback/fallback.js",
    "content": "export default '[success] imported from fallback'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/index.html",
    "content": "<h1>Resolve: tsconfig paths</h1>\n\n<h2>Import from .ts</h2>\n<p class=\"ts\"></p>\n\n<h2>Import from .js</h2>\n<p class=\"js\"></p>\n\n<h2>Fallback works</h2>\n<p class=\"fallback\"></p>\n\n<h2>Nested tsconfig.json & references / include works</h2>\n<p class=\"nested-a\"></p>\n<p class=\"nested-b\"></p>\n\n<script type=\"module\">\n  function text(selector, text) {\n    document.querySelector(selector).textContent = text\n  }\n\n  import ts from './src/ts.ts'\n  text('.ts', ts)\n\n  import js from './src/js.js'\n  text('.js', js)\n\n  import fallback from '@fallback/fallback'\n  text('.fallback', fallback)\n\n  import { valueA, valueB } from './src/nested/index.ts'\n  text('.nested-a', valueA)\n  text('.nested-b', valueB)\n</script>\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-tsconfig-paths\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/imported.js",
    "content": "export default '[success] imported'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/js.js",
    "content": "export { default } from '@/imported'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/a-imported.ts",
    "content": "export const value = '[success] a-imported' as const\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/a.ts",
    "content": "export { value } from '@imported'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/b-imported.ts",
    "content": "export const value = '[success] b-imported' as const\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/b.ts",
    "content": "export { value } from '@imported'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/index.ts",
    "content": "export { value as valueA } from './a'\nexport { value as valueB } from './b'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/tsconfig.a.json",
    "content": "{\n  \"include\": [\"./a.ts\"],\n  \"compilerOptions\": {\n    \"paths\": {\n      \"@imported\": [\"./a-imported.ts\"]\n    }\n  }\n}\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/tsconfig.b.json",
    "content": "{\n  \"include\": [\"./b.ts\"],\n  \"compilerOptions\": {\n    \"paths\": {\n      \"@imported\": [\"./b-imported.ts\"]\n    }\n  }\n}\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/nested/tsconfig.json",
    "content": "{\n  \"include\": [],\n  \"references\": [\n    { \"path\": \"./tsconfig.a.json\" },\n    { \"path\": \"./tsconfig.b.json\" }\n  ]\n}\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/src/ts.ts",
    "content": "export { default } from '@/imported'\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"allowJs\": true,\n    \"noEmit\": true,\n    \"paths\": {\n      \"@/*\": [\"./src/*\"],\n      \"@fallback/*\": [\"./src/*\", \"./fallback/*\"]\n    }\n  },\n  \"exclude\": [\"./__tests__\"]\n}\n"
  },
  {
    "path": "playground/resolve-tsconfig-paths/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  resolve: {\n    tsconfigPaths: true,\n  },\n})\n"
  },
  {
    "path": "playground/self-referencing/index.js",
    "content": "export const isSelfReference = true\n"
  },
  {
    "path": "playground/self-referencing/package.json",
    "content": "{\n  \"name\": \"@vitejs/self-referencing\",\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./test\": \"./test/index.js\"\n  }\n}\n"
  },
  {
    "path": "playground/self-referencing/test/index.js",
    "content": "export { isSelfReference } from '@vitejs/self-referencing'\n"
  },
  {
    "path": "playground/shims.d.ts",
    "content": "declare module 'css-color-names' {\n  const colors: Record<string, string>\n  export default colors\n}\n\ndeclare module 'kill-port' {\n  const kill: (port: number) => Promise<void>\n  export default kill\n}\n\ndeclare module '*.vue' {\n  import type { ComponentOptions } from 'vue'\n  const component: ComponentOptions\n  export default component\n}\n"
  },
  {
    "path": "playground/ssr/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { createInMemoryLogger, hmrPorts, ports, rootDir } from '~utils'\n\nexport const port = ports.ssr\n\nexport const serverLogs = []\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(\n    rootDir,\n    hmrPorts.ssr,\n    createInMemoryLogger(serverLogs),\n  )\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr/__tests__/ssr.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port, serverLogs } from './serve'\nimport { browserLogs, editFile, isServe, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ntest(`circular dependencies modules doesn't throw`, async () => {\n  await page.goto(`${url}/circular-dep`)\n\n  expect(await page.textContent('.circ-dep-init')).toMatch(\n    'circ-dep-init-a circ-dep-init-b',\n  )\n})\n\ntest(`circular import doesn't throw (1)`, async () => {\n  await page.goto(`${url}/circular-import`)\n\n  expect(await page.textContent('.circ-import')).toMatchInlineSnapshot(\n    '\"A is: __A__\"',\n  )\n})\n\ntest(`circular import doesn't throw (2)`, async () => {\n  await page.goto(`${url}/circular-import2`)\n\n  expect(await page.textContent('.circ-import')).toMatchInlineSnapshot(\n    '\"A is: __A__\"',\n  )\n})\n\ntest(`deadlock doesn't happen for static imports`, async () => {\n  await page.goto(`${url}/forked-deadlock-static-imports`)\n\n  expect(await page.textContent('.forked-deadlock-static-imports')).toMatch(\n    'rendered',\n  )\n})\n\ntest(`deadlock doesn't happen for dynamic imports`, async () => {\n  await page.goto(`${url}/forked-deadlock-dynamic-imports`)\n\n  expect(await page.textContent('.forked-deadlock-dynamic-imports')).toMatch(\n    'rendered',\n  )\n})\n\ntest(`import.meta.resolve is supported`, async () => {\n  await page.goto(`${url}/import-meta`)\n\n  const metaUrl = await page.textContent('.import-meta-url')\n  expect(metaUrl).not.toBe('')\n  expect(await page.textContent('.import-meta-resolve')).toBe(metaUrl)\n})\n\ntest(`import.meta.main is supported`, async () => {\n  await page.goto(`${url}/import-meta`)\n\n  expect(await page.textContent('.import-meta-main')).toBe('false')\n})\n\ntest.runIf(isServe)('html proxy is encoded', async () => {\n  await page.goto(\n    `${url}?%22%3E%3C/script%3E%3Cscript%3Econsole.log(%27html%20proxy%20is%20not%20encoded%27)%3C/script%3E`,\n  )\n\n  expect(browserLogs).not.toContain('html proxy is not encoded')\n})\n\n// run this at the end to reduce flakiness\ntest.runIf(isServe)('should restart ssr', async () => {\n  editFile('./vite.config.ts', (content) => content)\n  await expect\n    .poll(() => {\n      expect(serverLogs).toEqual(\n        expect.arrayContaining([expect.stringMatching('server restarted')]),\n      )\n      expect(serverLogs).not.toEqual(\n        expect.arrayContaining([expect.stringMatching('error')]),\n      )\n    })\n    .toSatisfy(() => true)\n})\n"
  },
  {
    "path": "playground/ssr/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>SSR</title>\n    <script type=\"module\">\n      // Inline script for testing html-proxy encoding\n      console.log('from inline script')\n    </script>\n  </head>\n  <body>\n    <h1>SSR</h1>\n    <div><!--app-html--></div>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/ssr/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr/server.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nexport async function createServer(\n  root = process.cwd(),\n  hmrPort,\n  customLogger,\n) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  const vite = await (\n    await import('vite')\n  ).createServer({\n    root,\n    logLevel: isTest ? 'error' : 'info',\n    server: {\n      middlewareMode: true,\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n      hmr: {\n        port: hmrPort,\n      },\n    },\n    appType: 'custom',\n    customLogger,\n  })\n  // use vite's connect instance as middleware\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res, next) => {\n    try {\n      const url = req.originalUrl\n\n      let template\n      template = fs.readFileSync(resolve('index.html'), 'utf-8')\n      template = await vite.transformIndexHtml(url, template)\n      const render = (await vite.ssrLoadModule('/src/app.js')).render\n\n      const appHtml = await render(url, import.meta.dirname)\n\n      const html = template.replace(`<!--app-html-->`, appHtml)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite && vite.ssrFixStacktrace(e)\n      if (isTest) throw e\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr/src/app.js",
    "content": "import { escapeHtml } from './utils'\n\nconst pathRenderers = {\n  '/': renderRoot,\n  '/circular-dep': renderCircularDep,\n  '/circular-import': renderCircularImport,\n  '/circular-import2': renderCircularImport2,\n  '/forked-deadlock-static-imports': renderForkedDeadlockStaticImports,\n  '/forked-deadlock-dynamic-imports': renderForkedDeadlockDynamicImports,\n  '/import-meta': renderImportMeta,\n}\n\nexport async function render(url, rootDir) {\n  const pathname = url.replace(/#[^#]*$/, '').replace(/\\?[^?]*$/, '')\n  const renderer = pathRenderers[pathname]\n  if (renderer) {\n    return await renderer(rootDir)\n  }\n  return '404'\n}\n\nasync function renderRoot(rootDir) {\n  const paths = Object.keys(pathRenderers).filter((key) => key !== '/')\n  return `\n    <ul>\n      ${paths\n        .map(\n          (path) =>\n            `<li><a href=\"${escapeHtml(path)}\">${escapeHtml(path)}</a></li>`,\n        )\n        .join('\\n')}\n    </ul>\n  `\n}\n\nasync function renderCircularDep(rootDir) {\n  const { getValueAB } = await import('./circular-dep-init/circular-dep-init')\n  return `<div class=\"circ-dep-init\">${escapeHtml(getValueAB())}</div>`\n}\n\nasync function renderCircularImport(rootDir) {\n  const { logA } = await import('./circular-import/index.js')\n  return `<div class=\"circ-import\">${escapeHtml(logA())}</div>`\n}\n\nasync function renderCircularImport2(rootDir) {\n  const { logA } = await import('./circular-import2/index.js')\n  return `<div class=\"circ-import\">${escapeHtml(logA())}</div>`\n}\n\nasync function renderForkedDeadlockStaticImports(rootDir) {\n  const { commonModuleExport } = await import('./forked-deadlock/common-module')\n  commonModuleExport()\n  return `<div class=\"forked-deadlock-static-imports\">rendered</div>`\n}\n\nasync function renderForkedDeadlockDynamicImports(rootDir) {\n  const { commonModuleExport } =\n    await import('./forked-deadlock/dynamic-imports/common-module')\n  await commonModuleExport()\n  return `<div class=\"forked-deadlock-dynamic-imports\">rendered</div>`\n}\n\nasync function renderImportMeta(rootDir) {\n  const metaUrl = import.meta.url\n  const resolveResult = import.meta.resolve('./app.js')\n  const metaMain = import.meta.main\n  return (\n    `<div class=\"import-meta-url\">${escapeHtml(metaUrl)}</div>` +\n    `<div class=\"import-meta-resolve\">${escapeHtml(resolveResult)}</div>` +\n    `<div class=\"import-meta-main\">${escapeHtml(String(metaMain))}</div>`\n  )\n}\n"
  },
  {
    "path": "playground/ssr/src/circular-dep-init/README.md",
    "content": "This test aim to find out wherever the modules with circular dependencies are correctly initialized\n"
  },
  {
    "path": "playground/ssr/src/circular-dep-init/circular-dep-init.js",
    "content": "export * from './module-a'\nexport { getValueAB } from './module-b'\n"
  },
  {
    "path": "playground/ssr/src/circular-dep-init/module-a.js",
    "content": "export const valueA = 'circ-dep-init-a'\n"
  },
  {
    "path": "playground/ssr/src/circular-dep-init/module-b.js",
    "content": "import { valueA } from './circular-dep-init'\n\nexport const valueB = 'circ-dep-init-b'\nexport const valueAB = valueA.concat(` ${valueB}`)\n\nexport function getValueAB() {\n  return valueAB\n}\n"
  },
  {
    "path": "playground/ssr/src/circular-import/a.js",
    "content": "import { getB } from './b'\n\nexport const A = '__A__'\n\nexport const B = getB()\n"
  },
  {
    "path": "playground/ssr/src/circular-import/b.js",
    "content": "export function getB() {\n  return '__B__'\n}\n\nexport { A } from './a'\n"
  },
  {
    "path": "playground/ssr/src/circular-import/index.js",
    "content": "import { A } from './b'\n\nexport function logA() {\n  return `A is: ${A}`\n}\n"
  },
  {
    "path": "playground/ssr/src/circular-import2/a.js",
    "content": "import { getB } from './b'\n\nexport const A = '__A__'\n\nexport const B = getB()\n"
  },
  {
    "path": "playground/ssr/src/circular-import2/b.js",
    "content": "export { A } from './a'\n\nexport function getB() {\n  return '__B__'\n}\n"
  },
  {
    "path": "playground/ssr/src/circular-import2/index.js",
    "content": "import { A } from './b'\n\nexport function logA() {\n  return `A is: ${A}`\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/README.md",
    "content": "This test aims to check for a particular type of circular dependency that causes tricky deadlocks, **deadlocks with forked imports stack**\n\n```\nA -> B means: B is imported by A and B has A in its stack\nA ... B means: A is waiting for B to ssrLoadModule()\n\nH -> X ... Y\nH -> X -> Y ... B\nH -> A ... B\nH -> A -> B ... X\n```\n\n### Forked deadlock description:\n\n```\n[X] is waiting for [Y] to resolve\n ↑                  ↳ is waiting for [A] to resolve\n │                                    ↳ is waiting for [B] to resolve\n │                                                      ↳ is waiting for [X] to resolve\n └────────────────────────────────────────────────────────────────────────┘\n```\n\nThis may seems a traditional deadlock, but the thing that makes this special is the import stack of each module:\n\n```\n[X] stack:\n\t[H]\n```\n\n```\n[Y] stack:\n\t[X]\n\t[H]\n```\n\n```\n[A] stack:\n\t[H]\n```\n\n```\n[B] stack:\n\t[A]\n\t[H]\n```\n\nEven if `[X]` is imported by `[B]`, `[B]` is not in `[X]`'s stack because it's imported by `[H]` in first place then it's stack is only composed by `[H]`. `[H]` **forks** the imports **stack** and this makes it hard to be found.\n\n### Fix description\n\nVite, when imports `[X]`, should check whether `[X]` is already pending and if it is, it must check that, when it was imported in first place, the stack of `[X]` doesn't have any module in common with the current module; in this case `[B]` has the module `[H]` is common with `[X]` and i can assume that a deadlock is going to happen.\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/common-module.js",
    "content": "import { stuckModuleExport } from './stuck-module'\nimport { deadlockfuseModuleExport } from './deadlock-fuse-module'\n\n/**\n * module H\n */\nexport function commonModuleExport() {\n  stuckModuleExport()\n  deadlockfuseModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/deadlock-fuse-module.js",
    "content": "import { fuseStuckBridgeModuleExport } from './fuse-stuck-bridge-module'\n\n/**\n * module A\n */\nexport function deadlockfuseModuleExport() {\n  fuseStuckBridgeModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/dynamic-imports/common-module.js",
    "content": "/**\n * module H\n */\nexport async function commonModuleExport() {\n  const [{ stuckModuleExport }, { deadlockfuseModuleExport }] =\n    await Promise.all([\n      import('./stuck-module'),\n      import('./deadlock-fuse-module'),\n    ])\n\n  stuckModuleExport()\n  deadlockfuseModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/dynamic-imports/deadlock-fuse-module.js",
    "content": "import { fuseStuckBridgeModuleExport } from './fuse-stuck-bridge-module'\n\n/**\n * module A\n */\nexport function deadlockfuseModuleExport() {\n  fuseStuckBridgeModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/dynamic-imports/fuse-stuck-bridge-module.js",
    "content": "import { stuckModuleExport } from './stuck-module'\n\n/**\n * module C\n */\nexport function fuseStuckBridgeModuleExport() {\n  stuckModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/dynamic-imports/middle-module.js",
    "content": "import { deadlockfuseModuleExport } from './deadlock-fuse-module'\n\n/**\n * module Y\n */\nexport function middleModuleExport() {\n  void deadlockfuseModuleExport\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/dynamic-imports/stuck-module.js",
    "content": "import { middleModuleExport } from './middle-module'\n\n/**\n * module X\n */\nexport function stuckModuleExport() {\n  middleModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/fuse-stuck-bridge-module.js",
    "content": "import { stuckModuleExport } from './stuck-module'\n\n/**\n * module C\n */\nexport function fuseStuckBridgeModuleExport() {\n  stuckModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/middle-module.js",
    "content": "import { deadlockfuseModuleExport } from './deadlock-fuse-module'\n\n/**\n * module Y\n */\nexport function middleModuleExport() {\n  void deadlockfuseModuleExport\n}\n"
  },
  {
    "path": "playground/ssr/src/forked-deadlock/stuck-module.js",
    "content": "import { middleModuleExport } from './middle-module'\n\n/**\n * module X\n */\nexport function stuckModuleExport() {\n  middleModuleExport()\n}\n"
  },
  {
    "path": "playground/ssr/src/utils.js",
    "content": "const escapeHtmlReplaceMap = {\n  '&': '&amp;',\n  \"'\": '&#x27;',\n  '`': '&#x60;',\n  '\"': '&quot;',\n  '<': '&lt;',\n  '>': '&gt;',\n}\n\n/**\n * @param {string} string\n * @returns {string}\n */\nexport function escapeHtml(string) {\n  return string.replace(/[&'`\"<>]/g, (match) => escapeHtmlReplaceMap[match])\n}\n"
  },
  {
    "path": "playground/ssr/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\n\n// in order to trigger ssr server restart\nexport default defineConfig({})\n"
  },
  {
    "path": "playground/ssr-alias/__tests__/ssr-alias.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isServe, testDir, viteServer } from '~utils'\n\ntest.runIf(isServe)('dev', async () => {\n  const mod = await viteServer.ssrLoadModule('/src/main.js')\n  expect(mod.default).toEqual({\n    dep: 'ok',\n    nonDep: 'ok',\n    builtin: 'ok',\n  })\n})\n\ntest.runIf(!isServe)('build', async () => {\n  const mod = await import(`${testDir}/dist/main.js`)\n  expect(mod.default).toEqual({\n    dep: 'ok',\n    nonDep: 'ok',\n    builtin: 'ok',\n  })\n})\n"
  },
  {
    "path": "playground/ssr-alias/alias-original/index.js",
    "content": "export default 'original'\n"
  },
  {
    "path": "playground/ssr-alias/alias-original/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-alias-original\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": \"./index.js\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-alias/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-html\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"vite build\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-alias-original\": \"file:./alias-original\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-alias/src/alias-process.js",
    "content": "export default {\n  env: { __TEST_ALIAS__: 'ok' },\n}\n"
  },
  {
    "path": "playground/ssr-alias/src/alias-replaced.js",
    "content": "export default 'ok'\n"
  },
  {
    "path": "playground/ssr-alias/src/main.js",
    "content": "import process from 'node:process'\nimport dep from '@vitejs/test-alias-original'\nimport nonDep from '@vitejs/test-alias-non-dep'\n\nexport default {\n  dep,\n  nonDep,\n  builtin: process.env['__TEST_ALIAS__'],\n}\n"
  },
  {
    "path": "playground/ssr-alias/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    ssr: './src/main.js',\n  },\n  resolve: {\n    alias: {\n      '@vitejs/test-alias-original': '/src/alias-replaced.js',\n      '@vitejs/test-alias-non-dep': '/src/alias-replaced.js',\n      'node:process': '/src/alias-process.js',\n    },\n  },\n})\n"
  },
  {
    "path": "playground/ssr-conditions/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { hmrPorts, isBuild, ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-conditions']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  if (isBuild) {\n    // build first\n    const { build } = await import('vite')\n    // client build\n    await build({\n      root: rootDir,\n      logLevel: 'silent', // exceptions are logged by Vitest\n      build: {\n        minify: false,\n        outDir: 'dist/client',\n      },\n    })\n    // server build\n    await build({\n      root: rootDir,\n      logLevel: 'silent',\n      build: {\n        ssr: 'src/app.js',\n        outDir: 'dist/server',\n      },\n    })\n  }\n\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(\n    rootDir,\n    isBuild,\n    hmrPorts['ssr-conditions'],\n  )\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr-conditions/__tests__/ssr-conditions.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port } from './serve'\nimport { isServe, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ntest('ssr.resolve.conditions affect non-externalized imports during ssr', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.no-external-react-server')).toMatch(\n    'node.unbundled.js',\n  )\n})\n\n// externalConditions is only used for dev\ntest.runIf(isServe)(\n  'ssr.resolve.externalConditions affect externalized imports during ssr',\n  async () => {\n    await page.goto(url)\n    expect(await page.textContent('.external-react-server')).toMatch('edge.js')\n  },\n)\n\ntest('ssr.resolve settings do not affect non-ssr imports', async () => {\n  await page.goto(url)\n  await expect\n    .poll(() => page.textContent('.browser-no-external-react-server'))\n    .toMatch('default.js')\n  await expect\n    .poll(() => page.textContent('.browser-external-react-server'))\n    .toMatch('default.js')\n})\n"
  },
  {
    "path": "playground/ssr-conditions/external/browser.js",
    "content": "export default 'browser.js'\n"
  },
  {
    "path": "playground/ssr-conditions/external/default.js",
    "content": "export default 'default.js'\n"
  },
  {
    "path": "playground/ssr-conditions/external/edge.js",
    "content": "export default 'edge.js'\n"
  },
  {
    "path": "playground/ssr-conditions/external/node.js",
    "content": "export default 'node.js'\n"
  },
  {
    "path": "playground/ssr-conditions/external/node.unbundled.js",
    "content": "export default 'node.unbundled.js'\n"
  },
  {
    "path": "playground/ssr-conditions/external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-conditions-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./server\": {\n      \"react-server\": {\n        \"workerd\": \"./edge.js\",\n        \"deno\": \"./browser.js\",\n        \"node\": {\n          \"webpack\": \"./node.js\",\n          \"default\": \"./node.unbundled.js\"\n        },\n        \"edge-light\": \"./edge.js\",\n        \"browser\": \"./browser.js\"\n      },\n      \"default\": \"./default.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/ssr-conditions/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>SSR Resolve Conditions</title>\n  </head>\n  <body>\n    <h1>SSR Resolve Conditions</h1>\n    <div id=\"app\"><!--app-html--></div>\n\n    <script type=\"module\">\n      import('@vitejs/test-ssr-conditions-no-external/server').then(\n        ({ default: message }) => {\n          document.querySelector(\n            '.browser-no-external-react-server',\n          ).textContent = message\n        },\n      )\n\n      import('@vitejs/test-ssr-conditions-external/server').then(\n        ({ default: message }) => {\n          document.querySelector('.browser-external-react-server').textContent =\n            message\n        },\n      )\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/ssr-conditions/no-external/browser.js",
    "content": "export default 'browser.js'\n"
  },
  {
    "path": "playground/ssr-conditions/no-external/default.js",
    "content": "export default 'default.js'\n"
  },
  {
    "path": "playground/ssr-conditions/no-external/edge.js",
    "content": "export default 'edge.js'\n"
  },
  {
    "path": "playground/ssr-conditions/no-external/node.js",
    "content": "export default 'node.js'\n"
  },
  {
    "path": "playground/ssr-conditions/no-external/node.unbundled.js",
    "content": "export default 'node.unbundled.js'\n"
  },
  {
    "path": "playground/ssr-conditions/no-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-conditions-no-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./server\": {\n      \"react-server\": {\n        \"workerd\": \"./edge.js\",\n        \"deno\": \"./browser.js\",\n        \"node\": {\n          \"webpack\": \"./node.js\",\n          \"default\": \"./node.unbundled.js\"\n        },\n        \"edge-light\": \"./edge.js\",\n        \"browser\": \"./browser.js\"\n      },\n      \"default\": \"./default.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/ssr-conditions/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-conditions\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"build\": \"npm run build:client && npm run build:server\",\n    \"build:client\": \"vite build --outDir dist/client\",\n    \"build:server\": \"vite build --ssr src/app.js --outDir dist/server\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-ssr-conditions-external\": \"file:./external\",\n    \"@vitejs/test-ssr-conditions-no-external\": \"file:./no-external\"\n  },\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\",\n    \"sirv\": \"^3.0.2\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-conditions/server.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\nimport sirv from 'sirv'\n\nconst isTest = process.env.VITEST\n\nexport async function createServer(\n  root = process.cwd(),\n  isProd = process.env.NODE_ENV === 'production',\n  hmrPort,\n) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const indexProd = isProd\n    ? fs.readFileSync(resolve('dist/client/index.html'), 'utf-8')\n    : ''\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  let vite\n  if (!isProd) {\n    vite = await (\n      await import('vite')\n    ).createServer({\n      root,\n      logLevel: isTest ? 'error' : 'info',\n      server: {\n        middlewareMode: true,\n        watch: {\n          // During tests we edit the files too fast and sometimes chokidar\n          // misses change events, so enforce polling for consistency\n          usePolling: true,\n          interval: 100,\n        },\n        hmr: {\n          port: hmrPort,\n        },\n      },\n      appType: 'custom',\n    })\n    app.use(vite.middlewares)\n  } else {\n    app.use(sirv(resolve('dist/client'), { extensions: [] }))\n  }\n\n  app.use('*all', async (req, res) => {\n    try {\n      const url = req.originalUrl\n\n      let template, render\n      if (!isProd) {\n        template = fs.readFileSync(resolve('index.html'), 'utf-8')\n        template = await vite.transformIndexHtml(url, template)\n        render = (await vite.ssrLoadModule('/src/app.js')).render\n      } else {\n        template = indexProd\n        render = (await import('./dist/server/app.js')).render\n      }\n\n      const appHtml = await render(url, import.meta.dirname)\n\n      const html = template.replace(`<!--app-html-->`, appHtml)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite && vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr-conditions/src/app.js",
    "content": "import noExternalReactServerMessage from '@vitejs/test-ssr-conditions-no-external/server'\nimport externalReactServerMessage from '@vitejs/test-ssr-conditions-external/server'\n\nexport async function render(url) {\n  let html = ''\n\n  html += `\\n<p class=\"no-external-react-server\">${noExternalReactServerMessage}</p>`\n\n  html += `\\n<p class=\"browser-no-external-react-server\"></p>`\n\n  html += `\\n<p class=\"external-react-server\">${externalReactServerMessage}</p>`\n\n  html += `\\n<p class=\"browser-external-react-server\"></p>`\n\n  return html + '\\n'\n}\n"
  },
  {
    "path": "playground/ssr-conditions/vite.config.js",
    "content": "import { defaultServerConditions, defineConfig } from 'vite'\n\nexport default defineConfig({\n  ssr: {\n    external: ['@vitejs/test-ssr-conditions-external'],\n    noExternal: ['@vitejs/test-ssr-conditions-no-external'],\n    resolve: {\n      conditions: [...defaultServerConditions, 'react-server'],\n      externalConditions: ['node', 'workerd', 'react-server'],\n    },\n  },\n})\n"
  },
  {
    "path": "playground/ssr-deps/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { hmrPorts, ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-deps']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(rootDir, hmrPorts['ssr-deps'])\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr-deps/__tests__/ssr-deps.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { port } from './serve'\nimport { editFile, getColor, isServe, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\n/**\n * test for #5809\n */\ntest('msg should be encrypted', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.encrypted-msg')).not.toMatch(\n    'Secret Message!',\n  )\n})\n\ntest('msg read by fs/promises', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.file-message')).toMatch('File Content!')\n})\n\ntest('msg from primitive export', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.primitive-export-message')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from TS transpiled exports', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.ts-default-export-message')).toMatch(\n    'Hello World!',\n  )\n  expect(await page.textContent('.ts-named-export-message')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from Object.assign exports', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.object-assigned-exports-message')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from forwarded exports', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.forwarded-export-message')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from define properties exports', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.define-properties-exports-msg')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from define property exports', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.define-property-exports-msg')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from only object assigned exports', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.only-object-assigned-exports-msg')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from no external cjs', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.no-external-cjs-msg')).toMatch('Hello World!')\n})\n\ntest('msg from optimized with nested external', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.optimized-with-nested-external')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from optimized cjs with nested external', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.optimized-cjs-with-nested-external')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from external using external entry', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.external-using-external-entry')).toMatch(\n    'Hello World!',\n  )\n})\n\ntest('msg from linked no external', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.linked-no-external')).toMatch(\n    `Hello World from ${process.env.NODE_ENV}!`,\n  )\n})\n\ntest('msg from linked no external', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.dep-virtual')).toMatch('[success]')\n})\n\ntest('import css library', async () => {\n  await page.goto(url)\n  expect(await getColor('.css-lib')).toBe('blue')\n})\n\ntest('import css library', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.module-condition')).toMatch('[success]')\n})\n\ntest('optimize-deps-nested-include', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.optimize-deps-nested-include')).toMatch(\n    'nested-include',\n  )\n})\n\ndescribe.runIf(isServe)('hmr', () => {\n  // TODO: the server file is not imported on the client at all\n  // so it's not present in the client moduleGraph anymore\n  // we need to decide if we want to support a usecase when ssr change\n  // affects the client in any way\n  test.skip('handle isomorphic module updates', async () => {\n    await page.goto(url)\n\n    expect(await page.textContent('.isomorphic-module-server')).toMatch(\n      '[server]',\n    )\n    // Allowing additional time for this element to be filled in\n    // by a client script that is loaded using dynamic import\n    await expect\n      .poll(async () => {\n        return page.textContent('.isomorphic-module-browser')\n      })\n      .toMatch('[browser]')\n\n    editFile('src/isomorphic-module-browser.js', (code) =>\n      code.replace('[browser]', '[browser-hmr]'),\n    )\n    await page.waitForNavigation()\n    await expect\n      .poll(async () => {\n        return page.textContent('.isomorphic-module-browser')\n      })\n      .toMatch('[browser-hmr]')\n\n    editFile('src/isomorphic-module-server.js', (code) =>\n      code.replace('[server]', '[server-hmr]'),\n    )\n    await page.waitForNavigation()\n    await expect\n      .poll(async () => {\n        return page.textContent('.isomorphic-module-server')\n      })\n      .toMatch('[server-hmr]')\n  })\n})\n"
  },
  {
    "path": "playground/ssr-deps/css-lib/index.css",
    "content": ".css-lib {\n  color: blue;\n}\n"
  },
  {
    "path": "playground/ssr-deps/css-lib/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-css-lib\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"./index.css\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/define-properties-exports/index.js",
    "content": "// prettier-ignore\nObject.defineProperties    (    exports    , {\n  hello: {\n    value() {\n      return 'Hello World!'\n    }\n  }\n})\n"
  },
  {
    "path": "playground/ssr-deps/define-properties-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-define-properties-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/define-property-exports/index.js",
    "content": "Object.defineProperty(exports, 'hello', {\n  value() {\n    return 'Hello World!'\n  },\n})\n"
  },
  {
    "path": "playground/ssr-deps/define-property-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-define-property-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/external-entry/entry.js",
    "content": "// Module with state, to check that it is properly externalized and\n// not bundled in the optimized deps\nlet msg\nexport function setMessage(externalMsg) {\n  msg = externalMsg\n}\nexport default function getMessage() {\n  return msg\n}\n"
  },
  {
    "path": "playground/ssr-deps/external-entry/index.js",
    "content": "export default undefined\n"
  },
  {
    "path": "playground/ssr-deps/external-entry/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-external-entry\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./entry\": \"./entry.js\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/external-using-external-entry/index.js",
    "content": "import getMessage from 'external-entry/entry'\n\nexport default {\n  hello() {\n    return getMessage()\n  },\n}\n"
  },
  {
    "path": "playground/ssr-deps/external-using-external-entry/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-external-using-external-entry\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"external-entry\": \"file:../external-entry\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/forwarded-export/index.js",
    "content": "const original = require('object-assigned-exports')\nmodule.exports = original\n"
  },
  {
    "path": "playground/ssr-deps/forwarded-export/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-forwarded-export\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"object-assigned-exports\": \"file:../object-assigned-exports\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/import-builtin-cjs/index.js",
    "content": "exports.stream = require('node:stream')\n\nexports.hello = function () {\n  return 'Hello World!'\n}\n"
  },
  {
    "path": "playground/ssr-deps/import-builtin-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-import-builtin\",\n  \"private\": true,\n  \"type\": \"commonjs\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>SSR Dependencies</title>\n  </head>\n  <body>\n    <h1>SSR Dependencies</h1>\n    <div><!--app-html--></div>\n    <script type=\"module\">\n      // hydration scripts\n      import '@vitejs/test-css-lib'\n    </script>\n    <script type=\"module\">\n      // Using dynamic import, so the module is transformed when browser actually\n      // requests it. This essentially disables pre-transform optimization that's\n      // crucial to trigger a race condition, covered by the test case introduced\n      // in https://github.com/vitejs/vite/pull/11973\n      import('virtual:isomorphic-module').then(({ default: message }) => {\n        document.querySelector('.isomorphic-module-browser').textContent =\n          message\n      })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/ssr-deps/linked-no-external/index.js",
    "content": "export const hello = function () {\n  // make sure linked package is not externalized so Vite features like\n  // import.meta.env works (or handling TS files)\n  return `Hello World from ${\n    import.meta.env.DEV ? 'development' : 'production'\n  }!`\n}\n"
  },
  {
    "path": "playground/ssr-deps/linked-no-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-linked-no-external\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/message",
    "content": "File Content!\n"
  },
  {
    "path": "playground/ssr-deps/module-condition/import.mjs",
    "content": "export default '[success]'\n"
  },
  {
    "path": "playground/ssr-deps/module-condition/module.js",
    "content": "// this is written in ESM but the file extension implies this is evaluated as CJS.\n// BUT this doesn't matter in practice as the `module` condition is not used in node.\n// hence SSR should not load this file.\nexport default '[fail] should not load me'\n"
  },
  {
    "path": "playground/ssr-deps/module-condition/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-module-condition\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": {\n      \"module\": \"./module.js\",\n      \"import\": \"./import.mjs\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/nested-exclude/index.js",
    "content": "export { default as nestedInclude } from '@vitejs/test-nested-include'\n\nexport default 'nested-exclude'\n"
  },
  {
    "path": "playground/ssr-deps/nested-exclude/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-exclude\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"@vitejs/test-nested-include\": \"file:../nested-include\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/nested-external/index.js",
    "content": "// Module with state, to check that it is properly externalized and\n// not bundled in the optimized deps\nlet msg\nexport function setMessage(externalMsg) {\n  msg = externalMsg\n}\nexport default function getMessage() {\n  return msg\n}\n"
  },
  {
    "path": "playground/ssr-deps/nested-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/nested-external-cjs/index.js",
    "content": "// Module with state, to check that it is properly externalized and\n// not bundled in the optimized deps\nlet msg\n\nmodule.exports = {\n  setMessage(externalMsg) {\n    msg = externalMsg\n  },\n  getMessage() {\n    return msg\n  },\n}\n"
  },
  {
    "path": "playground/ssr-deps/nested-external-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-external-cjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"index.js\",\n  \"type\": \"commonjs\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/nested-include/index.js",
    "content": "// written in cjs, optimization should convert this to esm\nmodule.exports = 'nested-include'\n"
  },
  {
    "path": "playground/ssr-deps/nested-include/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-nested-include\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/no-external-cjs/index.js",
    "content": "exports.hello = function () {\n  return 'Hello World!'\n}\n"
  },
  {
    "path": "playground/ssr-deps/no-external-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-no-external-cjs\",\n  \"private\": true,\n  \"type\": \"commonjs\",\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/no-external-css/index.css",
    "content": "@font-face {\n  font-family: 'Not Real Sans';\n  src: url('./i-throw-if-you-optimize-this-file.woff') format('woff');\n}\n"
  },
  {
    "path": "playground/ssr-deps/no-external-css/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-no-external-css\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": \"./index.css\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/non-optimized-with-nested-external/index.js",
    "content": "import { setMessage } from 'nested-external'\nimport external from 'nested-external-cjs'\n\nsetMessage('Hello World!')\nexternal.setMessage('Hello World!')\n"
  },
  {
    "path": "playground/ssr-deps/non-optimized-with-nested-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-non-optimized-with-nested-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"nested-external\": \"file:../nested-external\",\n    \"nested-external-cjs\": \"file:../nested-external-cjs\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/object-assigned-exports/index.js",
    "content": "Object.defineProperty(exports, '__esModule', { value: true })\n\nconst obj = {\n  hello() {\n    return 'Hello World!'\n  },\n}\n\nObject.assign(exports, obj)\n"
  },
  {
    "path": "playground/ssr-deps/object-assigned-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-object-assigned-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/only-object-assigned-exports/index.js",
    "content": "Object.assign(exports, {\n  hello() {\n    return 'Hello World!'\n  },\n})\n"
  },
  {
    "path": "playground/ssr-deps/only-object-assigned-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-only-object-assigned-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/optimized-cjs-with-nested-external/index.js",
    "content": "const getMessage = require('nested-external')\n\nmodule.exports = {\n  hello: getMessage,\n}\n"
  },
  {
    "path": "playground/ssr-deps/optimized-cjs-with-nested-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-optimized-cjs-with-nested-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"nested-external\": \"file:../nested-external\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/optimized-with-nested-external/index.js",
    "content": "import getMessage from 'nested-external'\n\nexport function hello() {\n  return getMessage()\n}\n"
  },
  {
    "path": "playground/ssr-deps/optimized-with-nested-external/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-optimized-with-nested-external\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\",\n  \"dependencies\": {\n    \"nested-external\": \"file:../nested-external\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-deps\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\"\n  },\n  \"dependencies\": {\n    \"@node-rs/bcrypt\": \"^1.10.7\",\n    \"@vitejs/test-css-lib\": \"file:./css-lib\",\n    \"@vitejs/test-define-properties-exports\": \"file:./define-properties-exports\",\n    \"@vitejs/test-define-property-exports\": \"file:./define-property-exports\",\n    \"@vitejs/test-external-entry\": \"file:./external-entry\",\n    \"@vitejs/test-external-using-external-entry\": \"file:./external-using-external-entry\",\n    \"@vitejs/test-forwarded-export\": \"file:./forwarded-export\",\n    \"@vitejs/test-import-builtin-cjs\": \"file:./import-builtin-cjs\",\n    \"@vitejs/test-linked-no-external\": \"link:./linked-no-external\",\n    \"@vitejs/test-module-condition\": \"file:./module-condition\",\n    \"@vitejs/test-nested-exclude\": \"file:./nested-exclude\",\n    \"@vitejs/test-no-external-cjs\": \"file:./no-external-cjs\",\n    \"@vitejs/test-no-external-css\": \"file:./no-external-css\",\n    \"@vitejs/test-non-optimized-with-nested-external\": \"workspace:*\",\n    \"@vitejs/test-object-assigned-exports\": \"file:./object-assigned-exports\",\n    \"@vitejs/test-only-object-assigned-exports\": \"file:./only-object-assigned-exports\",\n    \"@vitejs/test-optimized-cjs-with-nested-external\": \"file:./optimized-with-nested-external\",\n    \"@vitejs/test-optimized-with-nested-external\": \"file:./optimized-with-nested-external\",\n    \"@vitejs/test-pkg-exports\": \"file:./pkg-exports\",\n    \"@vitejs/test-primitive-export\": \"file:./primitive-export\",\n    \"@vitejs/test-read-file-content\": \"file:./read-file-content\",\n    \"@vitejs/test-require-absolute\": \"file:./require-absolute\",\n    \"@vitejs/test-ts-transpiled-exports\": \"file:./ts-transpiled-exports\"\n  },\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-deps/pkg-exports/index.js",
    "content": "export default undefined\n"
  },
  {
    "path": "playground/ssr-deps/pkg-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-pkg-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": \"./index.js\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/primitive-export/index.js",
    "content": "module.exports = 'Hello World!'\n"
  },
  {
    "path": "playground/ssr-deps/primitive-export/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-primitive-export\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/read-file-content/index.js",
    "content": "const path = require('node:path')\n\nmodule.exports = async function readFileContent(filePath) {\n  const fs = require('node:fs/promises')\n  return await fs.readFile(path.resolve(filePath), 'utf-8')\n}\n"
  },
  {
    "path": "playground/ssr-deps/read-file-content/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-read-file-content\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/require-absolute/foo.js",
    "content": "module.exports.hello = 'Hello World!'\n"
  },
  {
    "path": "playground/ssr-deps/require-absolute/index.js",
    "content": "const path = require('node:path')\n\nmodule.exports.hello = () => require(path.resolve(__dirname, './foo.js')).hello\n"
  },
  {
    "path": "playground/ssr-deps/require-absolute/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-require-absolute\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-deps/server.js",
    "content": "// @ts-check\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nconst noExternal = [\n  '@vitejs/test-no-external-cjs',\n  '@vitejs/test-import-builtin-cjs',\n  '@vitejs/test-no-external-css',\n  '@vitejs/test-external-entry',\n]\n\nexport async function createServer(root = process.cwd(), hmrPort) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  const vite = await (\n    await import('vite')\n  ).createServer({\n    root,\n    logLevel: isTest ? 'error' : 'info',\n    server: {\n      middlewareMode: true,\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n      hmr: {\n        port: hmrPort,\n      },\n    },\n    appType: 'custom',\n    ssr: {\n      noExternal: [\n        ...noExternal,\n        '@vitejs/test-nested-exclude',\n        '@vitejs/test-nested-include',\n      ],\n      external: [\n        '@vitejs/test-nested-external',\n        '@vitejs/test-external-entry/entry',\n      ],\n      optimizeDeps: {\n        include: [\n          ...noExternal,\n          '@vitejs/test-nested-exclude > @vitejs/test-nested-include',\n        ],\n      },\n    },\n    plugins: [\n      {\n        name: 'dep-virtual',\n        enforce: 'pre',\n        resolveId(id) {\n          if (id === '@vitejs/test-pkg-exports/virtual') {\n            return '@vitejs/test-pkg-exports/virtual'\n          }\n        },\n        load(id) {\n          if (id === '@vitejs/test-pkg-exports/virtual') {\n            return 'export default \"[success]\"'\n          }\n        },\n      },\n      {\n        name: 'virtual-isomorphic-module',\n        resolveId(id) {\n          if (id === 'virtual:isomorphic-module') {\n            return '\\0virtual:isomorphic-module'\n          }\n        },\n        load(id, { ssr }) {\n          if (id === '\\0virtual:isomorphic-module') {\n            if (ssr) {\n              return 'export { default } from \"/src/isomorphic-module-server.js\";'\n            } else {\n              return 'export { default } from \"/src/isomorphic-module-browser.js\";'\n            }\n          }\n        },\n      },\n    ],\n  })\n  // use vite's connect instance as middleware\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res) => {\n    try {\n      const url = req.originalUrl\n\n      let template\n      template = fs.readFileSync(resolve('index.html'), 'utf-8')\n      template = await vite.transformIndexHtml(url, template)\n      const render = (await vite.ssrLoadModule('/src/app.js')).render\n\n      const appHtml = await render(url, import.meta.dirname)\n\n      const html = template.replace(`<!--app-html-->`, appHtml)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite && vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr-deps/src/app.js",
    "content": "import path from 'node:path'\nimport readFileContent from '@vitejs/test-read-file-content'\nimport primitiveExport from '@vitejs/test-primitive-export'\nimport tsDefaultExport, {\n  hello as tsNamedExport,\n} from '@vitejs/test-ts-transpiled-exports'\nimport objectAssignedExports from '@vitejs/test-object-assigned-exports'\nimport forwardedExport from '@vitejs/test-forwarded-export'\nimport bcrypt from '@node-rs/bcrypt'\nimport definePropertiesExports from '@vitejs/test-define-properties-exports'\nimport definePropertyExports from '@vitejs/test-define-property-exports'\nimport onlyObjectAssignedExports from '@vitejs/test-only-object-assigned-exports'\nimport requireAbsolute from '@vitejs/test-require-absolute'\nimport noExternalCjs from '@vitejs/test-no-external-cjs'\nimport importBuiltinCjs from '@vitejs/test-import-builtin-cjs'\nimport { hello as linkedNoExternal } from '@vitejs/test-linked-no-external'\nimport virtualMessage from '@vitejs/test-pkg-exports/virtual'\nimport moduleConditionMessage from '@vitejs/test-module-condition'\nimport '@vitejs/test-css-lib'\n\n// This import will set a 'Hello World!\" message in the nested-external non-entry dependency\nimport '@vitejs/test-non-optimized-with-nested-external'\n\nimport * as optimizedWithNestedExternal from '@vitejs/test-optimized-with-nested-external'\nimport * as optimizedCjsWithNestedExternal from '@vitejs/test-optimized-cjs-with-nested-external'\nimport * as optimizeDepsNestedInclude from '@vitejs/test-nested-exclude'\n\nimport { setMessage } from '@vitejs/test-external-entry/entry'\nsetMessage('Hello World!')\nimport externalUsingExternalEntry from '@vitejs/test-external-using-external-entry'\nimport isomorphicModuleMessage from 'virtual:isomorphic-module'\n\nexport async function render(url, rootDir) {\n  let html = ''\n\n  const encryptedMsg = await bcrypt.hash('Secret Message!', 10)\n  html += `\\n<p class=\"encrypted-msg\">encrypted message: ${encryptedMsg}</p>`\n\n  const fileContent = await readFileContent(path.resolve(rootDir, 'message'))\n  html += `\\n<p class=\"file-message\">msg read via fs/promises: ${fileContent}</p>`\n\n  html += `\\n<p class=\"primitive-export-message\">message from primitive export: ${primitiveExport}</p>`\n\n  // `.default()` as incorrectly packaged\n  const tsDefaultExportMessage = tsDefaultExport.default()\n  html += `\\n<p class=\"ts-default-export-message\">message from ts-default-export: ${tsDefaultExportMessage}</p>`\n\n  const tsNamedExportMessage = tsNamedExport()\n  html += `\\n<p class=\"ts-named-export-message\">message from ts-named-export: ${tsNamedExportMessage}</p>`\n\n  const objectAssignedExportsMessage = objectAssignedExports.hello()\n  html += `\\n<p class=\"object-assigned-exports-message\">message from object-assigned-exports: ${objectAssignedExportsMessage}</p>`\n\n  const forwardedExportMessage = forwardedExport.hello()\n  html += `\\n<p class=\"forwarded-export-message\">message from forwarded-export: ${forwardedExportMessage}</p>`\n\n  const definePropertiesExportsMsg = definePropertiesExports.hello()\n  html += `\\n<p class=\"define-properties-exports-msg\">message from define-properties-exports: ${definePropertiesExportsMsg}</p>`\n\n  const definePropertyExportsMsg = definePropertyExports.hello()\n  html += `\\n<p class=\"define-property-exports-msg\">message from define-property-exports: ${definePropertyExportsMsg}</p>`\n\n  const onlyObjectAssignedExportsMessage = onlyObjectAssignedExports.hello()\n  html += `\\n<p class=\"only-object-assigned-exports-msg\">message from only-object-assigned-exports: ${onlyObjectAssignedExportsMessage}</p>`\n\n  const requireAbsoluteMessage = requireAbsolute.hello()\n  html += `\\n<p class=\"require-absolute-msg\">message from require-absolute: ${requireAbsoluteMessage}</p>`\n\n  const noExternalCjsMessage = noExternalCjs.hello()\n  html += `\\n<p class=\"no-external-cjs-msg\">message from no-external-cjs: ${noExternalCjsMessage}</p>`\n\n  const importBuiltinCjsMessage = importBuiltinCjs.hello()\n  html += `\\n<p class=\"import-builtin-cjs-msg\">message from import-builtin-cjs: ${importBuiltinCjsMessage}</p>`\n\n  const optimizedWithNestedExternalMessage = optimizedWithNestedExternal.hello()\n  html += `\\n<p class=\"optimized-with-nested-external\">message from optimized-with-nested-external: ${optimizedWithNestedExternalMessage}</p>`\n\n  const optimizedCjsWithNestedExternalMessage =\n    optimizedCjsWithNestedExternal.hello()\n  html += `\\n<p class=\"optimized-cjs-with-nested-external\">message from optimized-cjs-with-nested-external: ${optimizedCjsWithNestedExternalMessage}</p>`\n\n  const externalUsingExternalEntryMessage = externalUsingExternalEntry.hello()\n  html += `\\n<p class=\"external-using-external-entry\">message from external-using-external-entry: ${externalUsingExternalEntryMessage}</p>`\n\n  const linkedNoExternalMessage = linkedNoExternal()\n  html += `\\n<p class=\"linked-no-external\">linked-no-external msg: ${linkedNoExternalMessage}</p>`\n\n  html += `\\n<p class=\"dep-virtual\">message from dep-virtual: ${virtualMessage}</p>`\n\n  html += `\\n<p class=\"css-lib\">I should be blue</p>`\n\n  html += `\\n<p class=\"module-condition\">${moduleConditionMessage}</p>`\n\n  html += `\\n<p class=\"isomorphic-module-server\">${isomorphicModuleMessage}</p>`\n\n  html += `\\n<p class=\"isomorphic-module-browser\"></p>`\n\n  html += `\\n<p class=\"optimize-deps-nested-include\">message from optimize-deps-nested-include: ${optimizeDepsNestedInclude.nestedInclude}</p>`\n\n  return html + '\\n'\n}\n"
  },
  {
    "path": "playground/ssr-deps/src/isomorphic-module-browser.js",
    "content": "const message = 'message from isomorphic-module (browser): [browser]'\n\nexport default message\n"
  },
  {
    "path": "playground/ssr-deps/src/isomorphic-module-server.js",
    "content": "const message = 'message from isomorphic-module (server): [server]'\n\nexport default message\n"
  },
  {
    "path": "playground/ssr-deps/ts-transpiled-exports/index.js",
    "content": "'use strict'\nObject.defineProperty(exports, '__esModule', { value: true })\nexports.hello = void 0\nfunction hello() {\n  return 'Hello World!'\n}\nexports.hello = hello\nexports.default = hello\n"
  },
  {
    "path": "playground/ssr-deps/ts-transpiled-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ts-transpiled-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-html/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { hmrPorts, ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-html']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(rootDir, hmrPorts['ssr-html'])\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr-html/__tests__/ssr-html.spec.ts",
    "content": "import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { describe, expect, test } from 'vitest'\nimport { port } from './serve'\nimport { editFile, isServe, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ndescribe.runIf(isServe)('injected inline scripts', () => {\n  test('no injected inline scripts are present', async () => {\n    await page.goto(url)\n    const inlineScripts = await page.$$eval('script', (nodes) =>\n      nodes.filter((n) => !n.getAttribute('src') && n.innerHTML),\n    )\n    expect(inlineScripts).toHaveLength(0)\n  })\n\n  test('injected script proxied correctly', async () => {\n    await page.goto(url)\n    const proxiedScripts = await page.$$eval('script', (nodes) =>\n      nodes\n        .filter((n) => {\n          const src = n.getAttribute('src')\n          if (!src) return false\n          return src.includes('?html-proxy&index')\n        })\n        .map((n) => n.getAttribute('src')),\n    )\n\n    // assert at least 1 proxied script exists\n    expect(proxiedScripts).not.toHaveLength(0)\n\n    const scriptContents = await Promise.all(\n      proxiedScripts.map((src) => fetch(url + src).then((res) => res.text())),\n    )\n\n    // all proxied scripts return code\n    for (const code of scriptContents) {\n      expect(code).toBeTruthy()\n    }\n  })\n})\n\ndescribe.runIf(isServe)('hmr', () => {\n  test('handle virtual module updates', async () => {\n    await page.goto(url)\n    const el = await page.$('.virtual')\n    expect(await el.textContent()).toBe('[success]')\n\n    const loadPromise = page.waitForEvent('load')\n    editFile('src/importedVirtual.js', (code) =>\n      code.replace('[success]', '[wow]'),\n    )\n    await loadPromise\n\n    await expect\n      .poll(async () => {\n        const el = await page.$('.virtual')\n        return await el.textContent()\n      })\n      .toMatch('[wow]')\n  })\n})\n\nconst execFileAsync = promisify(execFile)\n\ndescribe.runIf(isServe)('stacktrace', () => {\n  for (const ext of ['js', 'ts']) {\n    for (const sourcemapsEnabled of [false, true]) {\n      test(`stacktrace of ${ext} is correct when sourcemaps is${\n        sourcemapsEnabled ? '' : ' not'\n      } enabled in Node.js`, async () => {\n        const testStacktraceFile = path.resolve(\n          import.meta.dirname,\n          '../test-stacktrace.js',\n        )\n\n        const p = await execFileAsync('node', [\n          testStacktraceFile,\n          '' + sourcemapsEnabled,\n          ext,\n        ])\n        const lines = p.stdout\n          .split('\\n')\n          .filter((line) => line.includes('Module.error'))\n\n        const reg = new RegExp(\n          path\n            .resolve(import.meta.dirname, '../src', `error-${ext}.${ext}`)\n            .replace(/\\\\/g, '\\\\\\\\') + ':2:9',\n          'i',\n        )\n\n        lines.forEach((line) => {\n          expect(line.trim()).toMatch(reg)\n        })\n      })\n    }\n  }\n\n  test('with Vite runtime', async () => {\n    await execFileAsync('node', ['test-stacktrace-runtime.js'], {\n      cwd: fileURLToPath(new URL('..', import.meta.url)),\n    })\n  })\n})\n\n// --experimental-network-imports is going to be dropped\n// https://github.com/nodejs/node/pull/53822\nconst noNetworkImports = Number(process.version.match(/^v(\\d+)\\./)[1]) >= 22\n\ndescribe.runIf(isServe && !noNetworkImports)('network-imports', () => {\n  test('with Vite SSR', async () => {\n    await execFileAsync(\n      'node',\n      ['--experimental-network-imports', 'test-network-imports.js'],\n      {\n        cwd: fileURLToPath(new URL('..', import.meta.url)),\n      },\n    )\n  })\n\n  test('with Vite runtime', async () => {\n    await execFileAsync(\n      'node',\n      [\n        '--experimental-network-imports',\n        'test-network-imports.js',\n        '--module-runner',\n      ],\n      {\n        cwd: fileURLToPath(new URL('..', import.meta.url)),\n      },\n    )\n  })\n})\n"
  },
  {
    "path": "playground/ssr-html/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>SSR HTML</title>\n    <style>\n      body {\n        background-color: white;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>SSR Dynamic HTML</h1>\n    <div class=\"virtual\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/ssr-html/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-html\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\",\n    \"test-stacktrace:off\": \"node test-stacktrace false\",\n    \"test-stacktrace:on\": \"node test-stacktrace true\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-html/public/slash@3.0.0.js",
    "content": "/* eslint-disable */\n// copied from https://esm.sh/v133/slash@3.0.0/es2022/slash.mjs to reduce network issues in CI\n\n/* esm.sh - esbuild bundle(slash@3.0.0) es2022 production */\nvar a=Object.create;var d=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var g=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var A=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),E=(e,t)=>{for(var r in t)d(e,r,{get:t[r],enumerable:!0})},u=(e,t,r,i)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let n of x(t))!p.call(e,n)&&n!==r&&d(e,n,{get:()=>t[n],enumerable:!(i=m(t,n))||i.enumerable});return e},o=(e,t,r)=>(u(e,t,\"default\"),r&&u(r,t,\"default\")),c=(e,t,r)=>(r=e!=null?a(g(e)):{},u(t||!e||!e.__esModule?d(r,\"default\",{value:e,enumerable:!0}):r,e));var f=A((h,_)=>{\"use strict\";_.exports=e=>{let t=/^\\\\\\\\\\?\\\\/.test(e),r=/[^\\u0000-\\u0080]+/.test(e);return t||r?e:e.replace(/\\\\/g,\"/\")}});var s={};E(s,{default:()=>P});var L=c(f());o(s,c(f()));var{default:l,...N}=L,P=l!==void 0?l:N;export{P as default};\n"
  },
  {
    "path": "playground/ssr-html/server.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nconst DYNAMIC_SCRIPTS = `\n  <script type=\"module\">\n    const p = document.createElement('p');\n    p.innerHTML = '✅ Dynamically injected inline script';\n    document.body.appendChild(p);\n  </script>\n  <script type=\"module\" src=\"/src/app.js\"></script>\n`\n\nconst DYNAMIC_STYLES = `\n  <style>\n  h1 {\n    background-color: blue;\n  }\n  </style>\n`\n\nexport async function createServer(root = process.cwd(), hmrPort) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  const vite = await (\n    await import('vite')\n  ).createServer({\n    root,\n    logLevel: isTest ? 'error' : 'info',\n    server: {\n      middlewareMode: true,\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n      hmr: {\n        port: hmrPort,\n      },\n    },\n    appType: 'custom',\n    plugins: [\n      {\n        name: 'virtual-file',\n        resolveId(id) {\n          if (id === 'virtual:file') {\n            return '\\0virtual:file'\n          }\n        },\n        load(id) {\n          if (id === '\\0virtual:file') {\n            return 'import { virtual } from \"/src/importedVirtual.js\"; export { virtual };'\n          }\n        },\n      },\n    ],\n  })\n  // use vite's connect instance as middleware\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res, next) => {\n    try {\n      let [url] = req.originalUrl.split('?')\n      if (url.endsWith('/')) url += 'index.html'\n\n      if (url.startsWith('/favicon.ico')) {\n        return res.status(404).end('404')\n      }\n      if (url.startsWith('/@id/__x00__')) {\n        return next()\n      }\n\n      const htmlLoc = resolve(`.${url}`)\n      let template = fs.readFileSync(htmlLoc, 'utf-8')\n\n      template = template.replace(\n        '</body>',\n        `${DYNAMIC_SCRIPTS}${DYNAMIC_STYLES}</body>`,\n      )\n\n      // Force calling transformIndexHtml with url === '/', to simulate\n      // usage by ecosystem that was recommended in the SSR documentation\n      // as `const url = req.originalUrl`\n      const html = await vite.transformIndexHtml('/', template)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite && vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr-html/src/app.js",
    "content": "import { virtual } from 'virtual:file'\n\nconst p = document.createElement('p')\np.innerHTML = '✅ Dynamically injected script from file'\ndocument.body.appendChild(p)\n\ntext('.virtual', virtual)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n"
  },
  {
    "path": "playground/ssr-html/src/error-js.js",
    "content": "export function error() {\n  throw new Error('e')\n}\n"
  },
  {
    "path": "playground/ssr-html/src/error-ts.ts",
    "content": "export function error() {\n  throw new Error('e')\n}\n"
  },
  {
    "path": "playground/ssr-html/src/has-error-deep.ts",
    "content": "function crash(message: string) {\n  throw new Error(message)\n}\n\nexport function main(): void {\n  crash('crash')\n}\n"
  },
  {
    "path": "playground/ssr-html/src/importedVirtual.js",
    "content": "export const virtual = '[success]'\n"
  },
  {
    "path": "playground/ssr-html/src/network-imports.js",
    "content": "// same port as `ports[\"ssr-html\"]` in playground/test-utils.ts\nimport slash from 'http://localhost:9602/slash@3.0.0.js'\n\n// or test without local server\n// import slash from 'https://esm.sh/slash@3.0.0'\n\nexport { slash }\n"
  },
  {
    "path": "playground/ssr-html/test-network-imports.js",
    "content": "import assert from 'node:assert'\nimport { fileURLToPath } from 'node:url'\nimport { createServer, createServerModuleRunner } from 'vite'\n\nasync function runTest(userRunner) {\n  const server = await createServer({\n    configFile: false,\n    root: fileURLToPath(new URL('.', import.meta.url)),\n    server: {\n      middlewareMode: true,\n      ws: false,\n    },\n  })\n  let mod\n  if (userRunner) {\n    const runner = await createServerModuleRunner(server.environments.ssr, {\n      hmr: false,\n    })\n    mod = await runner.import('/src/network-imports.js')\n  } else {\n    mod = await server.ssrLoadModule('/src/network-imports.js')\n  }\n  assert.equal(mod.slash('foo\\\\bar'), 'foo/bar')\n  await server.close()\n}\n\nrunTest(process.argv.includes('--module-runner'))\n"
  },
  {
    "path": "playground/ssr-html/test-stacktrace-runtime.js",
    "content": "import { fileURLToPath } from 'node:url'\nimport assert from 'node:assert'\nimport { createServer, createServerModuleRunner } from 'vite'\n\n// same test case as packages/vite/src/node/ssr/runtime/__tests__/server-source-maps.spec.ts\n// implemented for e2e to catch build specific behavior\n\nconst server = await createServer({\n  configFile: false,\n  root: fileURLToPath(new URL('.', import.meta.url)),\n  server: {\n    middlewareMode: true,\n    ws: false,\n  },\n})\n\nconst runner = await createServerModuleRunner(server.environments.ssr, {\n  sourcemapInterceptor: 'prepareStackTrace',\n})\n\nconst mod = await runner.import('/src/has-error-deep.ts')\nlet error\ntry {\n  mod.main()\n} catch (e) {\n  error = e\n} finally {\n  await server.close()\n}\nassert.match(error?.stack, /has-error-deep.ts:6:3/)\n"
  },
  {
    "path": "playground/ssr-html/test-stacktrace.js",
    "content": "import path from 'node:path'\nimport { createServer } from 'vite'\n\nconst isSourceMapEnabled = process.argv[2] === 'true'\nconst ext = process.argv[3]\nprocess.setSourceMapsEnabled(isSourceMapEnabled)\nconsole.log('# sourcemaps enabled:', isSourceMapEnabled)\nconsole.log('# source file extension:', ext)\n\nconst isTest = process.env.VITEST\n\nconst vite = await createServer({\n  root: import.meta.dirname,\n  logLevel: isTest ? 'error' : 'info',\n  server: {\n    middlewareMode: true,\n    ws: false,\n  },\n  appType: 'custom',\n})\n\nconst abs1 = await vite.ssrLoadModule(`/src/error-${ext}.${ext}`)\nconst abs2 = await vite.ssrLoadModule(\n  path.resolve(import.meta.dirname, `./src/error-${ext}.${ext}`),\n)\nconst relative = await vite.ssrLoadModule(`./src/error-${ext}.${ext}`)\n\nfor (const mod of [abs1, abs2, relative]) {\n  try {\n    mod.error()\n  } catch (e) {\n    // this should not be called\n    // when sourcemap support for `new Function` is supported and sourcemap is enabled\n    // because the stacktrace is already rewritten by Node.js\n    if (!isSourceMapEnabled) {\n      vite.ssrFixStacktrace(e)\n    }\n    console.log(e)\n  }\n}\n\nawait vite.close()\n"
  },
  {
    "path": "playground/ssr-noexternal/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { hmrPorts, isBuild, ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-noexternal']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  if (isBuild) {\n    // build first\n    const { build } = await import('vite')\n    // server build\n    await build({\n      root: rootDir,\n      logLevel: 'silent',\n      build: {\n        ssr: 'src/entry-server.js',\n      },\n    })\n  }\n\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(\n    rootDir,\n    isBuild,\n    hmrPorts['ssr-noexternal'],\n  )\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr-noexternal/__tests__/ssr-noexternal.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port } from './serve'\nimport { isBuild, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ntest.runIf(!isBuild)('message from require-external-cjs', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.require-external-cjs')).toMatch('foo')\n})\n"
  },
  {
    "path": "playground/ssr-noexternal/external-cjs/import.mjs",
    "content": "throw new Error('shouldnt be loaded')\n"
  },
  {
    "path": "playground/ssr-noexternal/external-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-external-cjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \"require\": \"./require.cjs\",\n    \"import\": \"./import.mjs\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-noexternal/external-cjs/require.cjs",
    "content": "module.exports = 'foo'\n"
  },
  {
    "path": "playground/ssr-noexternal/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite App</title>\n  </head>\n  <body>\n    <div id=\"app\"><!--app-html--></div>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/ssr-noexternal/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-noexternal\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"build\": \"vite build --ssr src/entry-server.js\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-external-cjs\": \"file:./external-cjs\",\n    \"@vitejs/test-require-external-cjs\": \"file:./require-external-cjs\",\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-noexternal/require-external-cjs/main.js",
    "content": "module.exports = require('@vitejs/test-external-cjs')\n"
  },
  {
    "path": "playground/ssr-noexternal/require-external-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-require-external-cjs\",\n  \"type\": \"commonjs\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"main\": \"main.js\",\n  \"dependencies\": {\n    \"@vitejs/test-external-cjs\": \"file:../external-cjs\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-noexternal/server.js",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nexport async function createServer(\n  root = process.cwd(),\n  isProd = process.env.NODE_ENV === 'production',\n  hmrPort,\n) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const indexProd = isProd\n    ? fs.readFileSync(resolve('index.html'), 'utf-8')\n    : ''\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  let vite\n  if (!isProd) {\n    vite = await (\n      await import('vite')\n    ).createServer({\n      root,\n      logLevel: isTest ? 'error' : 'info',\n      server: {\n        middlewareMode: true,\n        watch: {\n          // During tests we edit the files too fast and sometimes chokidar\n          // misses change events, so enforce polling for consistency\n          usePolling: true,\n          interval: 100,\n        },\n        hmr: {\n          port: hmrPort,\n        },\n      },\n      appType: 'custom',\n    })\n    app.use(vite.middlewares)\n  }\n\n  app.use('*all', async (req, res) => {\n    try {\n      const url = req.originalUrl\n\n      let template, render\n      if (!isProd) {\n        // always read fresh template in dev\n        template = fs.readFileSync(resolve('index.html'), 'utf-8')\n        template = await vite.transformIndexHtml(url, template)\n        render = (await vite.ssrLoadModule('/src/entry-server.js')).render\n      } else {\n        template = indexProd\n        render = (await import('./dist/entry-server.js')).render\n      }\n\n      const appHtml = await render(url)\n\n      const html = template.replace(`<!--app-html-->`, appHtml)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      !isProd && vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr-noexternal/src/entry-server.js",
    "content": "import requireExternalCjs from '@vitejs/test-require-external-cjs'\n\nexport async function render(url) {\n  let html = ''\n\n  html += `\\n<p class=\"require-external-cjs\">message from require-external-cjs: ${requireExternalCjs}</p>`\n\n  return html + '\\n'\n}\n"
  },
  {
    "path": "playground/ssr-noexternal/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nconst noExternal = ['@vitejs/test-require-external-cjs']\nexport default defineConfig({\n  ssr: {\n    noExternal,\n    external: ['@vitejs/test-external-cjs'],\n    optimizeDeps: {\n      include: noExternal,\n    },\n  },\n  build: {\n    target: 'esnext',\n    minify: false,\n    rollupOptions: {\n      external: ['@vitejs/test-external-cjs'],\n    },\n  },\n})\n"
  },
  {
    "path": "playground/ssr-pug/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { hmrPorts, ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-pug']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(rootDir, hmrPorts['ssr-pug'])\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr-pug/__tests__/ssr-pug.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { port } from './serve'\nimport { page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ndescribe('injected inline scripts', () => {\n  test('no injected inline scripts are present', async () => {\n    await page.goto(url)\n    const inlineScripts = await page.$$eval('script', (nodes) =>\n      nodes.filter((n) => !n.getAttribute('src') && n.innerHTML),\n    )\n    expect(inlineScripts).toHaveLength(0)\n  })\n\n  test('injected script proxied correctly', async () => {\n    await page.goto(url)\n    const proxiedScripts = await page.$$eval('script', (nodes) =>\n      nodes\n        .filter((n) => {\n          const src = n.getAttribute('src')\n          if (!src) return false\n          return src.includes('?html-proxy&index')\n        })\n        .map((n) => n.getAttribute('src')),\n    )\n\n    // assert at least 1 proxied script exists\n    expect(proxiedScripts).not.toHaveLength(0)\n\n    const scriptContents = await Promise.all(\n      proxiedScripts.map((src) => fetch(url + src).then((res) => res.text())),\n    )\n\n    // all proxied scripts return code\n    for (const code of scriptContents) {\n      expect(code).toBeTruthy()\n    }\n  })\n})\n"
  },
  {
    "path": "playground/ssr-pug/index.pug",
    "content": "doctype html\nhtml\n  head\n    meta(charset='UTF-8')\n    meta(name='viewport' content='width=device-width, initial-scale=1.0')\n    title SSR Pug\n  body\n    h1 SSR Pug\n"
  },
  {
    "path": "playground/ssr-pug/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-pug\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"serve\": \"NODE_ENV=production node server\",\n    \"debug\": \"node --inspect-brk server\"\n  },\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\",\n    \"pug\": \"^3.0.4\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-pug/server.js",
    "content": "// @ts-check\nimport path from 'node:path'\nimport pug from 'pug'\nimport express from 'express'\n\nconst isTest = process.env.VITEST\n\nconst DYNAMIC_SCRIPTS = `\n  <script type=\"module\">\n    const p = document.createElement('p');\n    p.innerHTML = '✅ Dynamically injected inline script';\n    document.body.appendChild(p);\n  </script>\n  <script type=\"module\" src=\"/src/app.js\"></script>\n`\n\nexport async function createServer(root = process.cwd(), hmrPort) {\n  const resolve = (p) => path.resolve(import.meta.dirname, p)\n\n  const app = express()\n\n  /**\n   * @type {import('vite').ViteDevServer}\n   */\n  const vite = await (\n    await import('vite')\n  ).createServer({\n    root,\n    logLevel: isTest ? 'error' : 'info',\n    server: {\n      middlewareMode: true,\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n      hmr: {\n        port: hmrPort,\n      },\n    },\n    appType: 'custom',\n  })\n  // use vite's connect instance as middleware\n  app.use(vite.middlewares)\n\n  app.use('*all', async (req, res) => {\n    try {\n      let [url] = req.originalUrl.split('?')\n      url = url.replace(/\\.html$/, '.pug')\n      if (url.endsWith('/')) url += 'index.pug'\n\n      const htmlLoc = resolve(`.${url}`)\n      let html = pug.renderFile(htmlLoc)\n      html = html.replace('</body>', `${DYNAMIC_SCRIPTS}</body>`)\n      html = await vite.transformIndexHtml(url, html)\n\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite && vite.ssrFixStacktrace(e)\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr-pug/src/app.js",
    "content": "const p = document.createElement('p')\np.innerHTML = '✅ Dynamically injected script from file'\ndocument.body.appendChild(p)\n"
  },
  {
    "path": "playground/ssr-resolve/__tests__/ssr-resolve.spec.ts",
    "content": "import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport { expect, test } from 'vitest'\nimport { isBuild, readFile, testDir } from '~utils'\n\nconst execFileAsync = promisify(execFile)\n\ntest.runIf(isBuild)('correctly resolve entrypoints', async () => {\n  const contents = readFile('dist/main.mjs')\n\n  const _ = `['\"]`\n  expect(contents).toMatch(\n    new RegExp(`from ${_}@vitejs/test-entries/dir/index.js${_}`),\n  )\n  expect(contents).toMatch(\n    new RegExp(`from ${_}@vitejs/test-entries/file.js${_}`),\n  )\n  expect(contents).toMatch(\n    new RegExp(`from ${_}@vitejs/test-resolve-pkg-exports/entry${_}`),\n  )\n\n  expect(contents).toMatch(\n    new RegExp(`from ${_}@vitejs/test-deep-import/foo/index.js${_}`),\n  )\n\n  // expect(contents).toMatch(\n  //   new RegExp(`from ${_}@vitejs/test-deep-import/utils/bar.js${_}`),\n  // )\n\n  expect(contents).toMatch(new RegExp(`from ${_}@vitejs/test-module-sync${_}`))\n\n  await execFileAsync('node', [`${testDir}/dist/main.mjs`])\n})\n\ntest.runIf(isBuild)(\n  'node builtins should not be bundled if not used',\n  async () => {\n    const contents = readFile('dist/main.mjs')\n    expect(contents).not.include(`node:url`)\n  },\n)\n"
  },
  {
    "path": "playground/ssr-resolve/deep-import/bar/package.json",
    "content": "{\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"main\": \"../utils/bar.js\",\n  \"module\": \"../utils/bar.js\"\n}\n"
  },
  {
    "path": "playground/ssr-resolve/deep-import/foo/index.js",
    "content": "export default 'foo'\n"
  },
  {
    "path": "playground/ssr-resolve/deep-import/foo/package.json",
    "content": "{\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"module\": \"./index.js\"\n}\n"
  },
  {
    "path": "playground/ssr-resolve/deep-import/index.js",
    "content": "export { default as foo } from './foo'\nexport { default as bar } from './bar'\nexport default 'external-nested'\n"
  },
  {
    "path": "playground/ssr-resolve/deep-import/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-deep-import\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"module\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/ssr-resolve/deep-import/utils/bar.js",
    "content": "export default 'bar'\n"
  },
  {
    "path": "playground/ssr-resolve/entries/dir/index.js",
    "content": "module.exports = __filename.slice(__filename.lastIndexOf('entries'))\n"
  },
  {
    "path": "playground/ssr-resolve/entries/file.js",
    "content": "module.exports = __filename.slice(__filename.lastIndexOf('entries'))\n"
  },
  {
    "path": "playground/ssr-resolve/entries/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-entries\",\n  \"private\": true,\n  \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "playground/ssr-resolve/main.js",
    "content": "// no `exports` key, should resolve to entries/dir/index.js\nimport dirEntry from '@vitejs/test-entries/dir'\n// no `exports` key, should resolve to entries/file.js\nimport fileEntry from '@vitejs/test-entries/file'\n// has `exports` key, should resolve to pkg-exports/entry\nimport pkgExportsEntry from '@vitejs/test-resolve-pkg-exports/entry'\nimport deepFoo from '@vitejs/test-deep-import/foo'\n// import deepBar from '@vitejs/test-deep-import/bar'\nimport moduleSync from '@vitejs/test-module-sync'\nimport { used } from './util'\n\nexport default `\n  entries/dir: ${dirEntry}\n  entries/file: ${fileEntry}\n  pkg-exports/entry: ${pkgExportsEntry}\n  deep-import/foo: ${deepFoo}\n  ${/* `deep-import/bar: ${deepBar}` */ ''}\n  module-sync: ${moduleSync}\n  util: ${used(['[success]'])}\n`\n"
  },
  {
    "path": "playground/ssr-resolve/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-resolve\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"commonjs\",\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite build\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-deep-import\": \"file:./deep-import\",\n    \"@vitejs/test-entries\": \"file:./entries\",\n    \"@vitejs/test-module-sync\": \"file:./pkg-module-sync\",\n    \"@vitejs/test-resolve-pkg-exports\": \"file:./pkg-exports\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-resolve/pkg-exports/entry.js",
    "content": "module.exports = 'pkg-exports entry'\n"
  },
  {
    "path": "playground/ssr-resolve/pkg-exports/index.js",
    "content": "module.exports = undefined\n"
  },
  {
    "path": "playground/ssr-resolve/pkg-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-resolve-pkg-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": \"./index.js\",\n    \"./entry\": \"./entry.js\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-resolve/pkg-module-sync/index.js",
    "content": "export default 'module-sync'\n"
  },
  {
    "path": "playground/ssr-resolve/pkg-module-sync/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-module-sync\",\n  \"type\": \"module\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": {\n      \"module-sync\": \"./index.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/ssr-resolve/util.js",
    "content": "import { pathToFileURL } from 'node:url'\n\nexport function used(s) {\n  return s\n}\n\n// This is not used, so `node:url` should not be bundled\nexport function treeshaken(s) {\n  return pathToFileURL(s)\n}\n"
  },
  {
    "path": "playground/ssr-resolve/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    ssr: './main.js',\n  },\n})\n"
  },
  {
    "path": "playground/ssr-wasm/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { build } from 'vite'\nimport { hmrPorts, isBuild, ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-wasm']\n\nexport async function preServe() {\n  if (isBuild) {\n    await build({ root: rootDir, logLevel: 'silent' })\n  }\n}\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  const { createServer } = await import(path.resolve(rootDir, 'server.js'))\n  const { app, vite } = await createServer(rootDir, hmrPorts['ssr-wasm'])\n\n  return new Promise((resolve, reject) => {\n    try {\n      const server = app.listen(port, () => {\n        resolve({\n          // for test teardown\n          async close() {\n            await new Promise((resolve) => {\n              server.close(resolve)\n            })\n            if (vite) {\n              await vite.close()\n            }\n          },\n        })\n      })\n    } catch (e) {\n      reject(e)\n    }\n  })\n}\n"
  },
  {
    "path": "playground/ssr-wasm/__tests__/ssr-wasm.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port } from './serve'\nimport { findAssetFile, isBuild, listAssets, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ntest('should work when inlined', async () => {\n  await page.goto(`${url}/static-light`)\n  expect(await page.textContent('.static-light')).toMatch('42')\n})\n\ntest('should work when output', async () => {\n  await page.goto(`${url}/static-heavy`)\n  expect(await page.textContent('.static-heavy')).toMatch('24')\n})\n\ntest.runIf(isBuild)('should not contain wasm file when inlined', async () => {\n  const assets = await listAssets()\n  const lightWasm = assets.find((f) => /light-.+\\.wasm$/.test(f))\n  expect(lightWasm).toBeUndefined()\n\n  const staticLight = await findAssetFile(/^static-light-.+\\.js$/)\n  expect(staticLight).toContain('data:application/wasm;base64,')\n})\n\ntest.runIf(isBuild)(\n  'should contain and reference wasm file when output',\n  async () => {\n    const assets = await listAssets()\n    const heavyWasm = assets.find((f) => /heavy-.+\\.wasm$/.test(f))\n    expect(heavyWasm).toBeDefined()\n\n    const staticHeavy = await findAssetFile(/^static-heavy-.+\\.js$/)\n    expect(staticHeavy).toContain(heavyWasm)\n    expect(staticHeavy).not.toContain('data:application/wasm;base64,')\n  },\n)\n"
  },
  {
    "path": "playground/ssr-wasm/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-wasm\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"node server\",\n    \"build\": \"vite build\",\n    \"preview\": \"NODE_ENV=production node server\"\n  },\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"express\": \"^5.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-wasm/server.js",
    "content": "import express from 'express'\n\nconst isTest = process.env.VITEST\nconst isProduction = process.env.NODE_ENV === 'production'\n\nexport async function createServer(root = process.cwd(), hmrPort) {\n  const app = express()\n\n  /** @type {import('vite').ViteDevServer} */\n  let vite\n  if (!isProduction) {\n    vite = await (\n      await import('vite')\n    ).createServer({\n      root,\n      logLevel: isTest ? 'error' : 'info',\n      server: {\n        middlewareMode: true,\n        watch: {\n          // During tests we edit the files too fast and sometimes chokidar\n          // misses change events, so enforce polling for consistency\n          usePolling: true,\n          interval: 100,\n        },\n        hmr: {\n          port: hmrPort,\n        },\n      },\n      appType: 'custom',\n    })\n    // use vite's connect instance as middleware\n    app.use(vite.middlewares)\n  }\n\n  app.use('*all', async (req, res, next) => {\n    try {\n      const url = req.originalUrl\n      const render = isProduction\n        ? (await import('./dist/app.js')).render\n        : (await vite.ssrLoadModule('/src/app.js')).render\n      const html = await render(url)\n      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)\n    } catch (e) {\n      vite?.ssrFixStacktrace(e)\n      if (isTest) throw e\n      console.log(e.stack)\n      res.status(500).end(e.stack)\n    }\n  })\n\n  return { app, vite }\n}\n\nif (!isTest) {\n  createServer().then(({ app }) =>\n    app.listen(5173, () => {\n      console.log('http://localhost:5173')\n    }),\n  )\n}\n"
  },
  {
    "path": "playground/ssr-wasm/src/app.js",
    "content": "export async function render(url) {\n  switch (url) {\n    case '/':\n      return `<ul>${['/static-light', '/static-heavy']\n        .map((name) => `<li><a href=\"${name}\">${name}</a></li>`)\n        .join('')}</ul>`\n    case '/static-light':\n      return (await import('./static-light')).render()\n    case '/static-heavy':\n      return (await import('./static-heavy')).render()\n  }\n}\n"
  },
  {
    "path": "playground/ssr-wasm/src/static-heavy.js",
    "content": "import heavy from './heavy.wasm?init'\n\nexport async function render() {\n  let result\n  const { exported_func } = await heavy({\n    imports: {\n      imported_func: (res) => (result = res),\n    },\n  }).then((i) => i.exports)\n  exported_func()\n  return `<div class=\"static-heavy\">${result}</div>`\n}\n"
  },
  {
    "path": "playground/ssr-wasm/src/static-light.js",
    "content": "import light from './light.wasm?init'\n\nexport async function render() {\n  let result\n  const { exported_func } = await light({\n    imports: {\n      imported_func: (res) => (result = res),\n    },\n  }).then((i) => i.exports)\n  exported_func()\n  return `<div class=\"static-light\">${result}</div>`\n}\n"
  },
  {
    "path": "playground/ssr-wasm/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nexport default defineConfig({\n  build: {\n    // make cannot emit light.wasm\n    assetsInlineLimit: 80,\n    ssr: './src/app.js',\n    ssrEmitAssets: true,\n  },\n})\n"
  },
  {
    "path": "playground/ssr-webworker/__tests__/serve.ts",
    "content": "// this is automatically detected by playground/vitestSetup.ts and will replace\n// the default e2e test serve behavior\n\nimport path from 'node:path'\nimport kill from 'kill-port'\nimport { ports, rootDir } from '~utils'\n\nexport const port = ports['ssr-webworker']\n\nexport async function serve(): Promise<{ close(): Promise<void> }> {\n  await kill(port)\n\n  // we build first, regardless of whether it's prod/build mode\n  // because Vite doesn't support the concept of a \"webworker server\"\n  const { build } = await import('vite')\n\n  // worker build\n  await build({\n    root: rootDir,\n    logLevel: 'silent',\n    build: {\n      target: 'esnext',\n      ssr: 'src/entry-worker.jsx',\n      outDir: 'dist/worker',\n    },\n  })\n\n  const { createServer } = await import(path.resolve(rootDir, 'worker.js'))\n  const { mf } = await createServer(port)\n\n  return {\n    // for test teardown\n    async close() {\n      await mf.dispose()\n    },\n  }\n}\n"
  },
  {
    "path": "playground/ssr-webworker/__tests__/ssr-webworker.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { port } from './serve'\nimport { findAssetFile, isBuild, page } from '~utils'\n\nconst url = `http://localhost:${port}`\n\ntest('/', async () => {\n  await page.goto(url + '/')\n  expect(await page.textContent('h1')).toMatch('hello from webworker')\n  expect(await page.textContent('.linked')).toMatch('dep from upper directory')\n  expect(await page.textContent('.external')).toMatch('object')\n})\n\ntest('supports resolve.conditions', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.worker-exports')).toMatch('[success] worker')\n})\n\ntest('respects browser export', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.browser-exports')).toMatch(\n    '[success] browser',\n  )\n})\n\ntest('supports nodejs_compat', async () => {\n  await page.goto(url)\n  expect(await page.textContent('.nodejs-compat')).toMatch(\n    '[success] nodejs compat',\n  )\n})\n\ntest.runIf(isBuild)('codeSplitting: false', () => {\n  const dynamicJsContent = findAssetFile(/dynamic-[-\\w]+\\.js/, 'worker')\n  expect(dynamicJsContent).toBeUndefined()\n})\n"
  },
  {
    "path": "playground/ssr-webworker/browser-exports/browser.js",
    "content": "export default '[success] browser'\n"
  },
  {
    "path": "playground/ssr-webworker/browser-exports/node.js",
    "content": "export default '[fail] should not load me'\n"
  },
  {
    "path": "playground/ssr-webworker/browser-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-browser-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": {\n      \"browser\": \"./browser.js\",\n      \"node\": \"./node.js\",\n      \"default\": \"./node.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/ssr-webworker/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-ssr-webworker\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"DEV=1 node worker\",\n    \"build:worker\": \"vite build --ssr src/entry-worker.jsx --outDir dist/worker\"\n  },\n  \"dependencies\": {\n    \"react\": \"^19.2.4\",\n    \"@vitejs/test-browser-exports\": \"file:./browser-exports\",\n    \"@vitejs/test-worker-exports\": \"file:./worker-exports\"\n  },\n  \"devDependencies\": {\n    \"miniflare\": \"^4.20260312.0\",\n    \"@vitejs/test-resolve-linked\": \"workspace:*\"\n  }\n}\n"
  },
  {
    "path": "playground/ssr-webworker/src/dynamic.js",
    "content": "export const foo = 'foo'\n"
  },
  {
    "path": "playground/ssr-webworker/src/entry-worker.jsx",
    "content": "import { equal } from 'node:assert'\nimport { msg as linkedMsg } from '@vitejs/test-resolve-linked'\nimport browserExportsMessage from '@vitejs/test-browser-exports'\nimport workerExportsMessage from '@vitejs/test-worker-exports'\nimport React from 'react'\n\nlet loaded = false\nimport('./dynamic').then(({ foo }) => {\n  loaded = !!foo\n})\n\naddEventListener('fetch', function (event) {\n  return event.respondWith(\n    new Response(\n      `\n    <h1>hello from webworker</h1>\n    <p class=\"linked\">${linkedMsg}</p>\n    <p class=\"external\">${typeof React}</p>\n    <p>dynamic: ${loaded}</p>\n    <p class=\"browser-exports\">${browserExportsMessage}</p>\n    <p class=\"worker-exports\">${workerExportsMessage}</p>\n    <p class=\"nodejs-compat\">${equal('a', 'a') || '[success] nodejs compat'}</p>\n    `,\n      {\n        headers: {\n          'content-type': 'text/html',\n        },\n      },\n    ),\n  )\n})\n"
  },
  {
    "path": "playground/ssr-webworker/vite.config.js",
    "content": "import { defaultClientConditions, defineConfig } from 'vite'\n\nexport default defineConfig({\n  build: {\n    minify: false,\n  },\n  resolve: {\n    dedupe: ['react'],\n  },\n  ssr: {\n    target: 'webworker',\n    noExternal: ['this-should-be-replaced-by-the-boolean'],\n    // Some webworker builds may choose to externalize node builtins as they may be implemented\n    // in the runtime, and so we can externalize it when bundling.\n    external: ['node:assert'],\n    resolve: {\n      conditions: [...defaultClientConditions, 'worker'],\n    },\n  },\n  plugins: [\n    {\n      name: '@vitejs/test-ssr-webworker/no-external',\n      config() {\n        return {\n          ssr: {\n            noExternal: true,\n          },\n        }\n      },\n    },\n    {\n      name: '@vitejs/test-ssr-webworker/no-external-array',\n      config() {\n        return {\n          ssr: {\n            noExternal: ['this-should-not-replace-the-boolean'],\n          },\n        }\n      },\n    },\n  ],\n})\n"
  },
  {
    "path": "playground/ssr-webworker/worker-exports/browser.js",
    "content": "// conditions are set to worker, and worker is higher up in the exports object in package.json, so should be preferred\nexport default '[fail] should not load me'\n"
  },
  {
    "path": "playground/ssr-webworker/worker-exports/node.js",
    "content": "export default '[fail] should not load me'\n"
  },
  {
    "path": "playground/ssr-webworker/worker-exports/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-worker-exports\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"exports\": {\n    \".\": {\n      \"worker\": \"./worker.js\",\n      \"browser\": \"./browser.js\",\n      \"node\": \"./node.js\",\n      \"default\": \"./node.js\"\n    }\n  }\n}\n"
  },
  {
    "path": "playground/ssr-webworker/worker-exports/worker.js",
    "content": "export default '[success] worker'\n"
  },
  {
    "path": "playground/ssr-webworker/worker.js",
    "content": "import path from 'node:path'\nimport { Miniflare } from 'miniflare'\n\nconst isTest = !!process.env.TEST\n\nexport async function createServer(port) {\n  const mf = new Miniflare({\n    scriptPath: path.resolve(\n      import.meta.dirname,\n      'dist/worker/entry-worker.js',\n    ),\n    port,\n    modules: true,\n    compatibilityFlags: ['nodejs_compat'],\n  })\n  await mf.ready\n  return { mf }\n}\n\nif (!isTest) {\n  createServer(5173).then(() => console.log('http://localhost:5173'))\n}\n"
  },
  {
    "path": "playground/tailwind/__test__/tailwind.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { editFile, getColor, isServe, page, untilBrowserLogAfter } from '~utils'\n\ntest('should render', async () => {\n  expect(await page.textContent('#pagetitle')).toBe('Page title')\n})\n\ntest.runIf(isServe)(\n  'full reload happens when the HTML is changed',\n  async () => {\n    await expect\n      .poll(() => getColor('.html'))\n      .toBe('oklch(0.623 0.214 259.815)')\n\n    editFile('index.html', (code) =>\n      code.replace('\"html text-blue-500\"', '\"html text-green-500\"'),\n    )\n    await expect\n      .poll(() => getColor('.html'))\n      .toBe('oklch(0.723 0.219 149.579)')\n  },\n)\n\ntest.runIf(isServe)('regenerate CSS and HMR (glob pattern)', async () => {\n  const el = page.locator('#view1-text')\n  expect(await getColor(el)).toBe('oklch(0.627 0.194 149.214)')\n\n  await untilBrowserLogAfter(\n    () =>\n      editFile('src/views/view1.js', (code) =>\n        code.replace('|view1|', '|view1 updated|'),\n      ),\n    [\n      '[vite] css hot updated: /index.css',\n      '[vite] hot updated: /src/views/view1.js via /src/main.js',\n    ],\n    false,\n  )\n  await expect.poll(() => el.textContent()).toMatch('|view1 updated|')\n\n  await untilBrowserLogAfter(\n    () =>\n      editFile('src/views/view1.js', (code) =>\n        code.replace('text-green-600', 'text-orange-600'),\n      ),\n    [\n      '[vite] css hot updated: /index.css',\n      '[vite] hot updated: /src/views/view1.js via /src/main.js',\n    ],\n    false,\n  )\n  await expect.poll(() => getColor(el)).toBe('oklch(0.646 0.222 41.116)')\n})\n\ntest.runIf(isServe)(\n  'same file duplicated in module graph (#4267)',\n  async () => {\n    const el = page.locator('#component1')\n    expect(await getColor(el)).toBe('oklch(0.577 0.245 27.325)')\n\n    // when duplicated, page reload happens\n    await untilBrowserLogAfter(\n      () =>\n        editFile('src/components/component1.js', (code) =>\n          code.replace('text-red-600', 'text-blue-600'),\n        ),\n      [\n        '[vite] css hot updated: /index.css',\n        '[vite] hot updated: /src/components/component1.js',\n      ],\n      false,\n    )\n    await expect.poll(() => getColor(el)).toBe('oklch(0.546 0.245 262.881)')\n  },\n)\n\ntest.runIf(isServe)('regenerate CSS and HMR (relative path)', async () => {\n  const el = page.locator('#pagetitle')\n  expect(await getColor(el)).toBe('oklch(0.541 0.281 293.009)')\n\n  await untilBrowserLogAfter(\n    () =>\n      editFile('src/main.js', (code) =>\n        code.replace('text-violet-600', 'text-cyan-600'),\n      ),\n    ['[vite] css hot updated: /index.css', '[vite] hot updated: /src/main.js'],\n    false,\n  )\n  await expect.poll(() => getColor(el)).toBe('oklch(0.609 0.126 221.723)')\n})\n"
  },
  {
    "path": "playground/tailwind/index.css",
    "content": "@import 'tailwindcss';\n@config './tailwind.config.ts';\n"
  },
  {
    "path": "playground/tailwind/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./index.css\" />\n\n<div id=\"app\"></div>\n\n<div class=\"html text-blue-500\">html</div>\n\n<script type=\"module\" src=\"/src/main.js\" defer></script>\n"
  },
  {
    "path": "playground/tailwind/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-tailwind\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tailwindcss/vite\": \"^4.2.1\",\n    \"tailwindcss\": \"^4.2.1\"\n  },\n  \"devDependencies\": {\n    \"tsx\": \"^4.21.0\"\n  }\n}\n"
  },
  {
    "path": "playground/tailwind/src/components/component1.js",
    "content": "export const component1 = /* html */ `\n  <div id=\"component1\" data-id=\"component1\" class=\"text-red-600\">component1</div>\n`\n\nimport.meta.hot?.accept((mod) => {\n  document.querySelectorAll('[data-id=\"component1\"]').forEach((d) => {\n    d.outerHTML = mod.component1\n  })\n})\n"
  },
  {
    "path": "playground/tailwind/src/main.js",
    "content": "import { view1 } from './views/view1'\n\nexport const main = (view1Content) => /* html */ `\n  <h1 id=\"pagetitle\" class=\"text-3xl text-violet-600\">Page title</h1>\n  ${view1Content}\n  <!-- used in postcss-plugins-different-dir -->\n  <div id=\"tailwind-style\" class=\"bg-red-100 text-[#888888]\">style</div>\n`\n\ndocument.getElementById('app').innerHTML = main(view1)\n\nimport.meta.hot?.accept((mod) => {\n  document.getElementById('app').innerHTML = mod.main(view1)\n})\n\nimport.meta.hot?.accept(['./views/view1'], ([mod]) => {\n  document.getElementById('app').innerHTML = main(mod.view1)\n})\n"
  },
  {
    "path": "playground/tailwind/src/views/view1.js",
    "content": "import { component1 } from '../components/component1'\n\nexport const view1 = /* html */ `\n  <div data-id=\"view1\">\n    <div id=\"view1-text\" class=\"text-green-600\">|view1|</div>\n    ${component1}\n  </div>\n`\n"
  },
  {
    "path": "playground/tailwind/tailwind.config.ts",
    "content": "import type { Config } from 'tailwindcss'\n\nexport default {\n  content: [\n    // Before editing this section, make sure no paths are matching with `/src/main.js`\n    // Look https://github.com/vitejs/vite/pull/6959 for more details\n    import.meta.dirname + '/src/{components,views}/**/*.js',\n    import.meta.dirname + '/src/main.js',\n    import.meta.dirname + '/index.html',\n  ],\n  theme: {\n    extend: {},\n  },\n  plugins: [],\n} satisfies Config\n"
  },
  {
    "path": "playground/tailwind/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport type { Plugin } from 'vite'\nimport tailwindcss from '@tailwindcss/vite'\n\nfunction delayIndexCssPlugin(): Plugin {\n  let server\n  return {\n    name: 'delay-index-css',\n    enforce: 'pre',\n    configureServer(_server) {\n      server = _server\n    },\n    async load(id) {\n      if (server && id.includes('index.css')) {\n        await server.waitForRequestsIdle(id)\n      }\n    },\n  }\n}\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '/@': import.meta.dirname,\n    },\n  },\n  build: {\n    // to make tests faster\n    minify: false,\n  },\n  plugins: [\n    {\n      name: 'delay view',\n      enforce: 'pre',\n      async transform(_code, id) {\n        if (id.includes('views/view1.js')) {\n          await new Promise((resolve) => setTimeout(resolve, 100))\n        }\n      },\n    },\n    delayIndexCssPlugin(),\n    tailwindcss(),\n  ],\n})\n"
  },
  {
    "path": "playground/tailwind-sourcemap/__tests__/tailwind-sourcemap.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, serverLogs } from '~utils'\n\ntest.runIf(!isBuild)('should not output missing source file warning', () => {\n  serverLogs.forEach((log) => {\n    expect(log).not.toMatch(/Sourcemap for .+ points to missing source files/)\n  })\n})\n\ntest.runIf(isBuild)('should not output sourcemap warning (#4939)', () => {\n  serverLogs.forEach((log) => {\n    expect(log).not.toMatch('Sourcemap is likely to be incorrect')\n  })\n})\n"
  },
  {
    "path": "playground/tailwind-sourcemap/index.html",
    "content": "<div class=\"wrapper\">\n  <h1>Tailwind Sourcemap</h1>\n\n  <p class=\"text-red-400\">foo</p>\n</div>\n\n<script type=\"module\">\n  import './tailwind.css'\n</script>\n"
  },
  {
    "path": "playground/tailwind-sourcemap/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-tailwind-sourcemap\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@tailwindcss/postcss\": \"^4.2.1\",\n    \"tailwindcss\": \"^4.2.1\"\n  }\n}\n"
  },
  {
    "path": "playground/tailwind-sourcemap/postcss.config.js",
    "content": "export default {\n  plugins: {\n    // using postcss tailwind as we want to test postcss integration\n    '@tailwindcss/postcss': {},\n  },\n}\n"
  },
  {
    "path": "playground/tailwind-sourcemap/tailwind.css",
    "content": "@import 'tailwindcss';\n"
  },
  {
    "path": "playground/tailwind-sourcemap/vite.config.js",
    "content": "import { defineConfig } from 'vite'\n\nexport default defineConfig({\n  css: {\n    devSourcemap: true,\n  },\n  build: {\n    sourcemap: true,\n  },\n})\n"
  },
  {
    "path": "playground/tailwind-v3/__test__/tailwind-v3.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { editFile, getColor, isServe, page, untilBrowserLogAfter } from '~utils'\n\ntest('should render', async () => {\n  expect(await page.textContent('#pagetitle')).toBe('Page title')\n})\n\ntest.runIf(isServe)('regenerate CSS and HMR (glob pattern)', async () => {\n  const el = page.locator('#view1-text')\n  expect(await getColor(el)).toBe('rgb(22, 163, 74)')\n\n  await untilBrowserLogAfter(\n    () =>\n      editFile('src/views/view1.js', (code) =>\n        code.replace('|view1|', '|view1 updated|'),\n      ),\n    [\n      '[vite] css hot updated: /index.css',\n      '[vite] hot updated: /src/views/view1.js via /src/main.js',\n    ],\n    false,\n  )\n  await expect.poll(() => el.textContent()).toMatch('|view1 updated|')\n\n  await untilBrowserLogAfter(\n    () =>\n      editFile('src/views/view1.js', (code) =>\n        code.replace('text-green-600', 'text-orange-600'),\n      ),\n    [\n      '[vite] css hot updated: /index.css',\n      '[vite] hot updated: /src/views/view1.js via /src/main.js',\n    ],\n    false,\n  )\n  await expect.poll(() => getColor(el)).toBe('rgb(234, 88, 12)')\n})\n\ntest.runIf(isServe)(\n  'same file duplicated in module graph (#4267)',\n  async () => {\n    const el = page.locator('#component1')\n    expect(await getColor(el)).toBe('rgb(220, 38, 38)')\n\n    // when duplicated, page reload happens\n    await untilBrowserLogAfter(\n      () =>\n        editFile('src/components/component1.js', (code) =>\n          code.replace('text-red-600', 'text-blue-600'),\n        ),\n      [\n        '[vite] css hot updated: /index.css',\n        '[vite] hot updated: /src/components/component1.js',\n      ],\n      false,\n    )\n    await expect.poll(() => getColor(el)).toBe('rgb(37, 99, 235)')\n  },\n)\n\ntest.runIf(isServe)('regenerate CSS and HMR (relative path)', async () => {\n  const el = page.locator('#pagetitle')\n  expect(await getColor(el)).toBe('rgb(124, 58, 237)')\n\n  await untilBrowserLogAfter(\n    () =>\n      editFile('src/main.js', (code) =>\n        code.replace('text-violet-600', 'text-cyan-600'),\n      ),\n    ['[vite] css hot updated: /index.css', '[vite] hot updated: /src/main.js'],\n    false,\n  )\n  await expect.poll(() => getColor(el)).toBe('rgb(8, 145, 178)')\n})\n"
  },
  {
    "path": "playground/tailwind-v3/index.css",
    "content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
  },
  {
    "path": "playground/tailwind-v3/index.html",
    "content": "<link rel=\"stylesheet\" href=\"./index.css\" />\n\n<div id=\"app\"></div>\n\n<script type=\"module\" src=\"/src/main.js\" defer></script>\n"
  },
  {
    "path": "playground/tailwind-v3/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-tailwind-v3\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"autoprefixer\": \"^10.4.27\",\n    \"tailwindcss\": \"^3.4.19\"\n  },\n  \"devDependencies\": {\n    \"tsx\": \"^4.21.0\"\n  }\n}\n"
  },
  {
    "path": "playground/tailwind-v3/postcss.config.js",
    "content": "// postcss.config.ts\nimport { fileURLToPath } from 'node:url'\n\nexport default {\n  plugins: {\n    tailwindcss: {\n      config: fileURLToPath(new URL('./tailwind.config.ts', import.meta.url)),\n    },\n    autoprefixer: {},\n  },\n}\n"
  },
  {
    "path": "playground/tailwind-v3/src/components/component1.js",
    "content": "export const component1 = /* html */ `\n  <div id=\"component1\" data-id=\"component1\" class=\"text-red-600\">component1</div>\n`\n\nimport.meta.hot?.accept((mod) => {\n  document.querySelectorAll('[data-id=\"component1\"]').forEach((d) => {\n    d.outerHTML = mod.component1\n  })\n})\n"
  },
  {
    "path": "playground/tailwind-v3/src/main.js",
    "content": "import { view1 } from './views/view1'\n\nexport const main = (view1Content) => /* html */ `\n  <h1 id=\"pagetitle\" class=\"text-3xl text-violet-600\">Page title</h1>\n  ${view1Content}\n  <!-- used in postcss-plugins-different-dir -->\n  <div id=\"tailwind-style\" class=\"bg-red-100 text-[#888888]\">style</div>\n`\n\ndocument.getElementById('app').innerHTML = main(view1)\n\nimport.meta.hot?.accept((mod) => {\n  document.getElementById('app').innerHTML = mod.main(view1)\n})\n\nimport.meta.hot?.accept(['./views/view1'], ([mod]) => {\n  document.getElementById('app').innerHTML = main(mod.view1)\n})\n"
  },
  {
    "path": "playground/tailwind-v3/src/views/view1.js",
    "content": "import { component1 } from '../components/component1'\n\nexport const view1 = /* html */ `\n  <div data-id=\"view1\">\n    <div id=\"view1-text\" class=\"text-green-600\">|view1|</div>\n    ${component1}\n  </div>\n`\n"
  },
  {
    "path": "playground/tailwind-v3/tailwind.config.ts",
    "content": "import type { Config } from 'tailwindcss'\n\n// NOTE: tailwind does not seem to support `import.meta.dirname` on Node 20\n\nexport default {\n  content: [\n    // Before editing this section, make sure no paths are matching with `/src/main.js`\n    // Look https://github.com/vitejs/vite/pull/6959 for more details\n    __dirname + '/src/{components,views}/**/*.js',\n    __dirname + '/src/main.js',\n  ],\n  theme: {\n    extend: {},\n  },\n  variants: {\n    extend: {},\n  },\n  plugins: [],\n} satisfies Config\n"
  },
  {
    "path": "playground/tailwind-v3/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport type { Plugin } from 'vite'\n\nfunction delayIndexCssPlugin(): Plugin {\n  let server\n  return {\n    name: 'delay-index-css',\n    enforce: 'pre',\n    configureServer(_server) {\n      server = _server\n    },\n    async load(id) {\n      if (server && id.includes('index.css')) {\n        await server.waitForRequestsIdle(id)\n      }\n    },\n  }\n}\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      '/@': import.meta.dirname,\n    },\n  },\n  build: {\n    // to make tests faster\n    minify: false,\n  },\n  plugins: [\n    {\n      name: 'delay view',\n      enforce: 'pre',\n      async transform(_code, id) {\n        if (id.includes('views/view1.js')) {\n          await new Promise((resolve) => setTimeout(resolve, 100))\n        }\n      },\n    },\n    delayIndexCssPlugin(),\n  ],\n})\n"
  },
  {
    "path": "playground/test-utils.ts",
    "content": "// test utils used in e2e tests for playgrounds.\n// `import { getColor } from '~utils'`\n\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport colors from 'css-color-names'\nimport type {\n  ConsoleMessage,\n  ElementHandle,\n  Locator,\n} from 'playwright-chromium'\nimport type { DepOptimizationMetadata, Manifest } from 'vite'\nimport { normalizePath } from 'vite'\nimport { fromComment, removeComments } from 'convert-source-map'\nimport { expect } from 'vitest'\nimport type { ResultPromise as ExecaResultPromise } from 'execa'\nimport { isWindows, page, sourcemapSnapshot, testDir } from './vitestSetup'\n\nexport * from './vitestSetup'\n\n// make sure these ports are unique\nexport const ports = {\n  cli: 9510,\n  'cli-module': 9511,\n  json: 9512,\n  'legacy/ssr': 9520,\n  lib: 9521,\n  'optimize-missing-deps': 9522,\n  'legacy/client-and-ssr': 9523,\n  'assets/encoded-base': 9554, // not imported but used in `assets/vite.config-encoded-base.js`\n  'assets/url-base': 9525, // not imported but used in `assets/vite.config-url-base.js`\n  ssr: 9600,\n  'ssr-deps': 9601,\n  'ssr-html': 9602,\n  'ssr-noexternal': 9603,\n  'ssr-pug': 9604,\n  'ssr-wasm': 9608,\n  'ssr-webworker': 9605,\n  'proxy-bypass': 9606, // not imported but used in `proxy-hmr/vite.config.js`\n  'proxy-bypass/non-existent-app': 9607, // not imported but used in `proxy-hmr/other-app/vite.config.js`\n  'ssr-hmr': 9609, // not imported but used in `hmr-ssr/__tests__/hmr.spec.ts`\n  'proxy-hmr': 9616, // not imported but used in `proxy-hmr/vite.config.js`\n  'proxy-hmr/other-app': 9617, // not imported but used in `proxy-hmr/other-app/vite.config.js`\n  'ssr-conditions': 9620,\n  'css/postcss-caching': 5005,\n  'css/postcss-plugins-different-dir': 5006,\n  'css/dynamic-import': 5007,\n  'css/lightningcss-proxy': 5008,\n  'backend-integration': 5009,\n  'client-reload': 5010,\n  'client-reload/hmr-port': 5011,\n  'client-reload/cross-origin': 5012,\n}\nexport const hmrPorts = {\n  'optimize-missing-deps': 24680,\n  ssr: 24681,\n  'ssr-deps': 24682,\n  'ssr-html': 24683,\n  'ssr-noexternal': 24684,\n  'ssr-pug': 24685,\n  'ssr-wasm': 24691,\n  'css/lightningcss-proxy': 24686,\n  json: 24687,\n  'ssr-conditions': 24688,\n  'client-reload/hmr-port': 24689,\n  'client-reload/cross-origin': 24690,\n}\n\nconst hexToNameMap: Record<string, string> = {}\nObject.keys(colors).forEach((color) => {\n  hexToNameMap[colors[color]] = color\n})\n\nfunction componentToHex(c: number): string {\n  const hex = c.toString(16)\n  return hex.length === 1 ? '0' + hex : hex\n}\n\nfunction rgbToHex(rgb: string): string | undefined {\n  const match = rgb.match(/rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)/)\n  if (match) {\n    const [_, rs, gs, bs] = match\n    return (\n      '#' +\n      componentToHex(parseInt(rs, 10)) +\n      componentToHex(parseInt(gs, 10)) +\n      componentToHex(parseInt(bs, 10))\n    )\n  }\n  return undefined\n}\n\nasync function toEl(\n  el: string | ElementHandle | Locator,\n): Promise<ElementHandle> {\n  if (typeof el === 'string') {\n    const realEl = await page.$(el)\n    if (realEl == null) {\n      throw new Error(`Cannot find element: \"${el}\"`)\n    }\n    return realEl\n  }\n  if ('elementHandle' in el) {\n    return el.elementHandle()\n  }\n  return el\n}\n\nexport async function getColor(\n  el: string | ElementHandle | Locator,\n): Promise<string> {\n  el = await toEl(el)\n  const rgb = await el.evaluate((el) => getComputedStyle(el as Element).color)\n  return hexToNameMap[rgbToHex(rgb)] ?? rgb\n}\n\nexport async function getBg(\n  el: string | ElementHandle | Locator,\n): Promise<string> {\n  el = await toEl(el)\n  return el.evaluate((el) => getComputedStyle(el as Element).backgroundImage)\n}\n\n/**\n * Unlike `getBg`, this function returns the raw value of the `background-image` CSS property.\n *\n * `getBg` returns the resolved value, which has the hostname and port prepended due to `computedStyle` call.\n */\nexport async function getCssRuleBg(selector: string): Promise<string> {\n  return page.evaluate((sel) => {\n    for (const sheet of document.styleSheets) {\n      try {\n        for (const rule of sheet.cssRules) {\n          if (rule instanceof CSSStyleRule && rule.selectorText === sel) {\n            return rule.style.backgroundImage\n          }\n        }\n      } catch (_e) {}\n    }\n  }, selector)\n}\n\nexport async function getBgColor(\n  el: string | ElementHandle | Locator,\n): Promise<string> {\n  el = await toEl(el)\n  const rgb = await el.evaluate(\n    (el) => getComputedStyle(el as Element).backgroundColor,\n  )\n  return hexToNameMap[rgbToHex(rgb)] ?? rgb\n}\n\nexport function readFile(filename: string, encoding?: BufferEncoding): string\nexport function readFile(filename: string, encoding: null): Buffer\nexport function readFile(\n  filename: string,\n  encoding?: BufferEncoding | null,\n): Buffer | string {\n  if (encoding === undefined) encoding = 'utf-8'\n  return fs.readFileSync(path.resolve(testDir, filename), encoding)\n}\n\nexport function editFile(\n  filename: string,\n  replacer: (content: string) => string,\n): void\nexport function editFile(\n  filename: string,\n  encoding: null,\n  replacer: (content: Buffer) => Buffer,\n): void\nexport function editFile(\n  filename: string,\n  encoding: BufferEncoding | null,\n  replacer: ((content: Buffer) => Buffer) | ((content: string) => string),\n): void\nexport function editFile(\n  filename: string,\n  encodingOrReplacer: BufferEncoding | null | ((content: string) => string),\n  maybeReplacer?: ((content: Buffer) => Buffer) | ((content: string) => string),\n): void {\n  filename = path.resolve(testDir, filename)\n  const [encoding, replacer] = maybeReplacer\n    ? [encodingOrReplacer as BufferEncoding | null, maybeReplacer]\n    : ['utf-8' as const, encodingOrReplacer as (content: string) => string]\n  const content: string | Buffer = fs.readFileSync(filename, encoding)\n  const modified = (replacer as (content: string | Buffer) => string | Buffer)(\n    content,\n  )\n  fs.writeFileSync(filename, modified)\n}\n\nexport function addFile(filename: string, content: string): void {\n  const resolvedFilename = path.resolve(testDir, filename)\n  fs.mkdirSync(path.dirname(resolvedFilename), { recursive: true })\n  fs.writeFileSync(resolvedFilename, content)\n}\n\nexport function removeFile(filename: string): void {\n  fs.unlinkSync(path.resolve(testDir, filename))\n}\n\nexport function listAssets(base = ''): string[] {\n  const assetsDir = path.join(testDir, 'dist', base, 'assets')\n  return fs.readdirSync(assetsDir)\n}\n\nexport function findAssetFile(\n  match: string | RegExp,\n  base = '',\n  assets = 'assets',\n  matchAll = false,\n): string | undefined {\n  const assetsDir = path.join(testDir, 'dist', base, assets)\n  let files: string[]\n  try {\n    files = fs.readdirSync(assetsDir)\n  } catch (e) {\n    if (e.code === 'ENOENT') {\n      return undefined\n    }\n    throw e\n  }\n  if (matchAll) {\n    const matchedFiles = files.filter((file) => file.match(match))\n    return matchedFiles.length\n      ? matchedFiles\n          .map((file) =>\n            fs.readFileSync(path.resolve(assetsDir, file), 'utf-8'),\n          )\n          .join('')\n      : undefined\n  } else {\n    const matchedFile = files.find((file) => file.match(match))\n    return matchedFile\n      ? fs.readFileSync(path.resolve(assetsDir, matchedFile), 'utf-8')\n      : undefined\n  }\n}\n\nexport function readManifest(base = ''): Manifest {\n  return JSON.parse(\n    fs.readFileSync(\n      path.join(testDir, 'dist', base, '.vite/manifest.json'),\n      'utf-8',\n    ),\n  )\n}\n\nexport function readDepOptimizationMetadata(\n  environmentName = 'client',\n): DepOptimizationMetadata {\n  const suffix = environmentName === 'client' ? '' : `_${environmentName}`\n  return JSON.parse(\n    fs.readFileSync(\n      path.join(testDir, `node_modules/.vite/deps${suffix}/_metadata.json`),\n      'utf-8',\n    ),\n  )\n}\n\ntype UntilBrowserLogAfterCallback = (logs: string[]) => PromiseLike<void> | void\n\nexport async function untilBrowserLogAfter(\n  operation: () => any,\n  target: string | RegExp | Array<string | RegExp>,\n  expectOrder?: boolean,\n  callback?: UntilBrowserLogAfterCallback,\n): Promise<string[]>\nexport async function untilBrowserLogAfter(\n  operation: () => any,\n  target: string | RegExp | Array<string | RegExp>,\n  callback?: UntilBrowserLogAfterCallback,\n): Promise<string[]>\nexport async function untilBrowserLogAfter(\n  operation: () => any,\n  target: string | RegExp | Array<string | RegExp>,\n  arg3?: boolean | UntilBrowserLogAfterCallback,\n  arg4?: UntilBrowserLogAfterCallback,\n): Promise<string[]> {\n  const expectOrder = typeof arg3 === 'boolean' ? arg3 : false\n  const callback = typeof arg3 === 'boolean' ? arg4 : arg3\n\n  const promise = untilBrowserLog(target, expectOrder)\n  await operation()\n  const logs = await promise\n  if (callback) {\n    await callback(logs)\n  }\n  return logs\n}\n\nasync function untilBrowserLog(\n  target?: string | RegExp | Array<string | RegExp>,\n  expectOrder = true,\n): Promise<string[]> {\n  const { promise, resolve, reject } = promiseWithResolvers<void>()\n  let timeoutId: ReturnType<typeof setTimeout>\n\n  const logs = []\n\n  try {\n    const isMatch = (matcher: string | RegExp) => (text: string) =>\n      typeof matcher === 'string' ? text === matcher : matcher.test(text)\n\n    let processMsg: (text: string) => boolean\n\n    if (!target) {\n      processMsg = () => true\n    } else if (Array.isArray(target)) {\n      if (expectOrder) {\n        const remainingTargets = [...target]\n        processMsg = (text: string) => {\n          const nextTarget = remainingTargets.shift()\n          expect(text).toMatch(nextTarget)\n          return remainingTargets.length === 0\n        }\n      } else {\n        const remainingMatchers = target.map(isMatch)\n        processMsg = (text: string) => {\n          const nextIndex = remainingMatchers.findIndex((matcher) =>\n            matcher(text),\n          )\n          if (nextIndex >= 0) {\n            remainingMatchers.splice(nextIndex, 1)\n          }\n          return remainingMatchers.length === 0\n        }\n      }\n    } else {\n      processMsg = isMatch(target)\n    }\n\n    const handleMsg = (msg: ConsoleMessage) => {\n      try {\n        const text = msg.text()\n        logs.push(text)\n        const done = processMsg(text)\n        if (done) {\n          resolve()\n        }\n      } catch (err) {\n        reject(err)\n      }\n    }\n\n    timeoutId = setTimeout(() => {\n      const nextTarget = Array.isArray(target)\n        ? expectOrder\n          ? target[0]\n          : target.join(', ')\n        : target\n      reject(\n        new Error(\n          `Timeout waiting for browser logs. Waiting for: ${nextTarget}`,\n        ),\n      )\n      page.off('console', handleMsg)\n    }, 5000)\n\n    page.on('console', handleMsg)\n  } catch (err) {\n    reject(err)\n  }\n\n  await promise\n  clearTimeout(timeoutId)\n\n  return logs\n}\n\nexport const extractSourcemap = (content: string): any => {\n  const lines = content.trim().split('\\n')\n  return fromComment(lines[lines.length - 1]).toObject()\n}\n\nexport const formatSourcemapForSnapshot = (\n  map: any,\n  code: string,\n  withoutContent = false,\n): any => {\n  const root = normalizePath(testDir)\n  const m = { ...map }\n  delete m.file\n  if (m.names && m.names.length === 0) {\n    delete m.names\n  }\n  if (m.debugId) {\n    m.debugId = '00000000-0000-0000-0000-000000000000'\n  }\n  m.sources = m.sources.map((source) => source.replace(root, '/root'))\n  if (m.sourceRoot) {\n    m.sourceRoot = m.sourceRoot.replace(root, '/root')\n  }\n  const c = removeComments(code.replace(/\\?v=[\\da-f]{8}/g, '?v=00000000'))\n  return { map: m, code: c, [sourcemapSnapshot]: { withoutContent } }\n}\n\n// helper function to kill process, uses taskkill on windows to ensure child process is killed too\nexport async function killProcess(\n  serverProcess: ExecaResultPromise,\n): Promise<void> {\n  if (isWindows) {\n    try {\n      const { execaCommandSync } = await import('execa')\n      execaCommandSync(`taskkill /pid ${serverProcess.pid} /T /F`)\n    } catch (e) {\n      console.error('failed to taskkill:', e)\n    }\n  } else {\n    serverProcess.kill('SIGTERM')\n  }\n}\n\nexport interface PromiseWithResolvers<T> {\n  promise: Promise<T>\n  resolve: (value: T | PromiseLike<T>) => void\n  reject: (reason?: any) => void\n}\nexport function promiseWithResolvers<T>(): PromiseWithResolvers<T> {\n  let resolve: any\n  let reject: any\n  const promise = new Promise<T>((_resolve, _reject) => {\n    resolve = _resolve\n    reject = _reject\n  })\n  return { promise, resolve, reject }\n}\n"
  },
  {
    "path": "playground/transform-plugin/__tests__/base/transform-plugin.spec.ts",
    "content": "// NOTE: a separate directory from `playground/transform-plugin` is created by playground/vitestGlobalSetup.ts\nimport { tests } from '../tests'\n\ntests()\n"
  },
  {
    "path": "playground/transform-plugin/__tests__/tests.ts",
    "content": "import { expect, test } from 'vitest'\nimport { editFile, isBuild, page } from '~utils'\n\nexport const tests = () => {\n  test('should re-run transform when dependencies are edited', async () => {\n    expect(await page.textContent('#transform-count')).toBe('1')\n\n    if (isBuild) return\n    editFile('plugin-dep.js', (str) => str)\n    await expect.poll(() => page.textContent('#transform-count')).toBe('2')\n\n    editFile('plugin-dep-load.js', (str) => str)\n    await expect.poll(() => page.textContent('#transform-count')).toBe('3')\n  })\n}\n"
  },
  {
    "path": "playground/transform-plugin/__tests__/transform-plugin.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { tests } from './tests'\nimport { page } from '~utils'\n\ntest('module type should be supported', async () => {\n  expect(await page.textContent('#module-type-json-pre')).toBe('json')\n  expect(await page.textContent('#module-type-json-post')).toBe('js')\n  expect(await page.textContent('#module-type-json-virtual-pre')).toBe('json')\n  expect(await page.textContent('#module-type-json-virtual-post')).toBe('js')\n})\n\ntest('lazy hook filter should be applied', async () => {\n  expect(await page.textContent('#lazy-hook-filter')).toBe('success')\n})\n\ntests()\n"
  },
  {
    "path": "playground/transform-plugin/foo.json",
    "content": "{\n  \"moduleTypePre\": \"MODULE_TYPE_PRE\",\n  \"moduleTypePost\": \"MODULE_TYPE_POST\"\n}\n"
  },
  {
    "path": "playground/transform-plugin/index.html",
    "content": "<h1>Transform Plugin</h1>\n\n<h2>addWatchFile</h2>\n<div id=\"transform-count\"></div>\n\n<h2>Module Type</h2>\n<div id=\"module-type-json-pre\"></div>\n<div id=\"module-type-json-post\"></div>\n<div id=\"module-type-json-virtual-pre\"></div>\n<div id=\"module-type-json-virtual-post\"></div>\n\n<h2>Lazy Hook Filter</h2>\n<div id=\"lazy-hook-filter\"></div>\n\n<script type=\"module\" src=\"./index.js\"></script>\n"
  },
  {
    "path": "playground/transform-plugin/index.js",
    "content": "import barJson from 'virtual:/bar.json'\nimport fooJson from './foo.json'\n\n// 'TRANSFORM_COUNT' is injected by the transform plugin\ndocument.getElementById('transform-count').innerHTML = TRANSFORM_COUNT\n\ndocument.getElementById('module-type-json-pre').innerHTML =\n  fooJson.moduleTypePre\ndocument.getElementById('module-type-json-post').innerHTML =\n  fooJson.moduleTypePost\n\ndocument.getElementById('module-type-json-virtual-pre').innerHTML =\n  barJson.moduleTypePre\ndocument.getElementById('module-type-json-virtual-post').innerHTML =\n  barJson.moduleTypePost\n\n// 'LAZY_HOOK_FILTER_CONTENT' is replaced by lazy-hook-filter plugin\ndocument.getElementById('lazy-hook-filter').innerHTML =\n  'LAZY_HOOK_FILTER_CONTENT'\n"
  },
  {
    "path": "playground/transform-plugin/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-transform-plugin\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/transform-plugin/plugin-dep-load.js",
    "content": "// Empty file for detecting changes in tests\n"
  },
  {
    "path": "playground/transform-plugin/plugin-dep.js",
    "content": "// Empty file for detecting changes in tests\n"
  },
  {
    "path": "playground/transform-plugin/vite.config-base.js",
    "content": "import { defineConfig } from 'vite'\nimport baseConfig from './vite.config.js'\n\nexport default defineConfig({\n  ...baseConfig,\n  base: '/vite/',\n})\n"
  },
  {
    "path": "playground/transform-plugin/vite.config.js",
    "content": "import { resolve } from 'node:path'\nimport { defineConfig, normalizePath } from 'vite'\n\nconst file = normalizePath(resolve(import.meta.dirname, 'index.js'))\nlet transformCount = 1\n\nconst transformPlugin = {\n  name: 'transform',\n  load(id) {\n    if (id === file) {\n      // Ensure `index.js` is reloaded if 'plugin-dep-load.js' is changed\n      this.addWatchFile('./plugin-dep-load.js')\n    }\n  },\n  transform(code, id) {\n    if (id === file) {\n      // Ensure `index.js` is reevaluated if 'plugin-dep.js' is changed\n      this.addWatchFile('./plugin-dep.js')\n\n      return `\n        // Inject TRANSFORM_COUNT\n        let TRANSFORM_COUNT = ${transformCount++};\n\n        ${code}\n      `\n    }\n  },\n}\n\nconst moduleTypePlugins = [\n  /** @type {const} */ ...['pre', 'post'].map((enforce) => ({\n    name: `module-type-${enforce}`,\n    enforce,\n    transform(code, id, opts) {\n      if (id.endsWith('/foo.json') || id.endsWith('\\0/bar.json')) {\n        code = code.replace(\n          `MODULE_TYPE_${enforce.toUpperCase()}`,\n          opts.moduleType,\n        )\n        return code\n      }\n    },\n  })),\n  {\n    name: `module-type-load`,\n    resolveId(id) {\n      if (id === 'virtual:/bar.json') {\n        return '\\0/bar.json'\n      }\n    },\n    load(id) {\n      if (id.endsWith('\\0/bar.json')) {\n        return JSON.stringify({\n          moduleTypePre: 'MODULE_TYPE_PRE',\n          moduleTypePost: 'MODULE_TYPE_POST',\n        })\n      }\n    },\n  },\n]\n\nconst lazyHookFilterPlugin = {\n  name: 'lazy-hook-filter',\n  options() {\n    lazyHookFilterPlugin.transform.filter = { id: '**/index.js' }\n  },\n  transform: {\n    filter: /** @type {import('vite').Rolldown.HookFilter} */ ({\n      id: { exclude: ['**/*.js'] },\n    }),\n    handler(code) {\n      return code.replaceAll('LAZY_HOOK_FILTER_CONTENT', 'success')\n    },\n  },\n}\n\nexport default defineConfig({\n  plugins: [transformPlugin, moduleTypePlugins, lazyHookFilterPlugin],\n})\n"
  },
  {
    "path": "playground/tsconfig-json/__tests__/tsconfig-json.spec.ts",
    "content": "import path from 'node:path'\nimport fs from 'node:fs'\nimport { transformWithEsbuild } from 'vite'\nimport { describe, expect, test } from 'vitest'\nimport { browserLogs, isServe, serverLogs } from '~utils'\n\ntest('should respected each `tsconfig.json`s compilerOptions', () => {\n  // main side effect should be called (because of `\"verbatimModuleSyntax\": true`)\n  expect(browserLogs).toContain('main side effect')\n  // main base setter should not be called (because of `\"useDefineForClassFields\": true\"`)\n  expect(browserLogs).not.toContain('data setter in MainBase')\n\n  // nested side effect should not be called (because \"verbatimModuleSyntax\" is not set, defaults to false)\n  expect(browserLogs).not.toContain('nested side effect')\n  // nested base setter should be called (because of `\"useDefineForClassFields\": false\"`)\n  expect(browserLogs).toContain('data setter in NestedBase')\n\n  // nested-with-extends side effect should be called (because \"verbatimModuleSyntax\" is extended from the main tsconfig.json, which is true)\n  expect(browserLogs).toContain('nested-with-extends side effect')\n  // nested-with-extends base setter should be called (because of `\"useDefineForClassFields\": false\"`)\n  expect(browserLogs).toContain('data setter in NestedWithExtendsBase')\n})\n\ntest.runIf(isServe)('scanner should not error with decorators', () => {\n  expect(serverLogs).not.toStrictEqual(\n    expect.arrayContaining([\n      expect.stringContaining(\n        'Parameter decorators only work when experimental decorators are enabled',\n      ),\n    ]),\n  )\n})\n\ndescribe('transformWithEsbuild', () => {\n  test('merge tsconfigRaw object', async () => {\n    const main = path.resolve(import.meta.dirname, '../src/main.ts')\n    const mainContent = fs.readFileSync(main, 'utf-8')\n    const result = await transformWithEsbuild(mainContent, main, {\n      tsconfigRaw: {\n        compilerOptions: {\n          useDefineForClassFields: false,\n        },\n      },\n    })\n    // \"verbatimModuleSyntax\": true from tsconfig.json should still work\n    expect(result.code).toMatch(/import.*\".\\/not-used-type\";/)\n  })\n\n  test('overwrite tsconfigRaw string', async () => {\n    const main = path.resolve(import.meta.dirname, '../src/main.ts')\n    const mainContent = fs.readFileSync(main, 'utf-8')\n    const result = await transformWithEsbuild(mainContent, main, {\n      tsconfigRaw: `{\n        \"compilerOptions\": {\n          \"useDefineForClassFields\": false\n        }\n      }`,\n    })\n    // \"verbatimModuleSyntax\": true from tsconfig.json should not be read\n    // and defaults to false\n    expect(result.code).not.toMatch(/import.*\".\\/not-used-type\";/)\n  })\n\n  test('verbatimModuleSyntax', async () => {\n    const main = path.resolve(import.meta.dirname, '../src/main.ts')\n    const mainContent = fs.readFileSync(main, 'utf-8')\n    const result = await transformWithEsbuild(mainContent, main, {\n      tsconfigRaw: {\n        compilerOptions: {\n          useDefineForClassFields: false,\n          verbatimModuleSyntax: false,\n        },\n      },\n    })\n    // \"verbatimModuleSyntax\": false from tsconfig.json should still work\n    expect(result.code).not.toMatch(/import.*\".\\/not-used-type\";/)\n  })\n\n  test('experimentalDecorators', async () => {\n    const main = path.resolve(import.meta.dirname, '../src/decorator.ts')\n    const mainContent = fs.readFileSync(main, 'utf-8')\n    // Should not error when transpiling decorators as nearest tsconfig.json\n    // has \"experimentalDecorators\": true\n    const result = await transformWithEsbuild(mainContent, main, {\n      target: 'es2020',\n    })\n    expect(result.code).toContain('__decorateClass')\n  })\n})\n"
  },
  {
    "path": "playground/tsconfig-json/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite App</title>\n  </head>\n  <body>\n    <div id=\"app\"><!--app-html--></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/tsconfig-json/nested/main.ts",
    "content": "// @ts-nocheck\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\nimport { NestedTypeOnlyClass } from './not-used-type'\n\nclass NestedBase {\n  set data(value: string) {\n    console.log('data setter in NestedBase')\n  }\n}\nclass NestedDerived extends NestedBase {\n  // No longer triggers a 'console.log'\n  // when using 'useDefineForClassFields'.\n  data = 10\n\n  foo?: NestedTypeOnlyClass\n}\n\nconst d = new NestedDerived()\n"
  },
  {
    "path": "playground/tsconfig-json/nested/not-used-type.ts",
    "content": "console.log('nested side effect')\n\nexport class NestedTypeOnlyClass {}\n"
  },
  {
    "path": "playground/tsconfig-json/nested/tsconfig.json",
    "content": "// prettier-ignore\n{\n  \"include\": [\"./\"],\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"noEmit\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n\n    /* tsconfig.json should support comments and trailing comma */\n    \"useDefineForClassFields\": false,\n  }\n}\n"
  },
  {
    "path": "playground/tsconfig-json/nested-with-extends/main.ts",
    "content": "// @ts-nocheck\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\nimport { NestedWithExtendsTypeOnlyClass } from './not-used-type'\n\nclass NestedWithExtendsBase {\n  set data(value: string) {\n    console.log('data setter in NestedWithExtendsBase')\n  }\n}\nclass NestedWithExtendsDerived extends NestedWithExtendsBase {\n  // No longer triggers a 'console.log'\n  // when using 'useDefineForClassFields'.\n  data = 10\n\n  foo?: NestedWithExtendsTypeOnlyClass\n}\n\nconst d = new NestedWithExtendsDerived()\n"
  },
  {
    "path": "playground/tsconfig-json/nested-with-extends/not-used-type.ts",
    "content": "console.log('nested-with-extends side effect')\n\nexport class NestedWithExtendsTypeOnlyClass {}\n"
  },
  {
    "path": "playground/tsconfig-json/nested-with-extends/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"include\": [\"./\"],\n  \"compilerOptions\": {\n    \"useDefineForClassFields\": false\n  }\n}\n"
  },
  {
    "path": "playground/tsconfig-json/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-tsconfig-json\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/tsconfig-json/src/decorator.ts",
    "content": "// @ts-nocheck playground/tsconfig.json does not have decorators enabled\nfunction first() {\n  return function (...args: any[]) {}\n}\n\nexport class Foo {\n  @first()\n  method(@first() test: string) {\n    return test\n  }\n}\n"
  },
  {
    "path": "playground/tsconfig-json/src/main.ts",
    "content": "// @ts-nocheck\nimport '../nested/main'\nimport '../nested-with-extends/main'\nimport './decorator'\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\nimport { MainTypeOnlyClass } from './not-used-type'\n\nclass MainBase {\n  set data(value: string) {\n    console.log('data setter in MainBase')\n  }\n}\nclass MainDerived extends MainBase {\n  // No longer triggers a 'console.log'\n  // when using 'useDefineForClassFields'.\n  data = 10\n\n  foo?: MainTypeOnlyClass\n}\n\nconst d = new MainDerived()\n"
  },
  {
    "path": "playground/tsconfig-json/src/not-used-type.ts",
    "content": "console.log('main side effect')\n\nexport class MainTypeOnlyClass {}\n"
  },
  {
    "path": "playground/tsconfig-json/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"noEmit\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n\n    \"useDefineForClassFields\": true,\n    \"verbatimModuleSyntax\": true,\n    \"experimentalDecorators\": true\n  },\n  \"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/__tests__/serve.ts",
    "content": "import { afterAll } from 'vitest'\nimport { startDefaultServe } from '~utils'\n\nexport let serveError: Error | undefined\n\nexport async function serve() {\n  try {\n    await startDefaultServe()\n  } catch (e) {\n    serveError = e\n  }\n}\n\nexport function clearServeError() {\n  serveError = undefined\n}\n\nafterAll(() => {\n  if (serveError) {\n    throw serveError\n  }\n})\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/__tests__/tsconfig-json-load-error.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { clearServeError, serveError } from './serve'\nimport { browserLogs, editFile, isBuild, isServe, page, readFile } from '~utils'\n\nconst unexpectedTokenSyntaxErrorRE =\n  /(\\[TSCONFIG_ERROR\\] )*Failed to load tsconfig .*: JSON parse error|JSONError/\n\ndescribe.runIf(isBuild)('build', () => {\n  test('should throw an error on build', () => {\n    expect(serveError).toBeTruthy()\n    expect(serveError.message).toMatch(unexpectedTokenSyntaxErrorRE)\n    clearServeError() // got expected error, null it here so testsuite does not fail from rethrow in afterAll\n  })\n\n  test('should not output files to dist', () => {\n    let err\n    try {\n      readFile('dist/index.html')\n    } catch (e) {\n      err = e\n    }\n    expect(err).toBeTruthy()\n    expect(err.code).toBe('ENOENT')\n  })\n})\n\ndescribe.runIf(isServe)('server', () => {\n  test('should log 500 error in browser for malformed tsconfig', () => {\n    // don't test for actual complete message as this might be locale dependent. chrome does log 500 consistently though\n    expect(browserLogs.find((x) => x.includes('500'))).toBeTruthy()\n    expect(browserLogs).not.toContain('tsconfig error fixed, file loaded')\n  })\n\n  test('should show error overlay for tsconfig error', async () => {\n    const errorOverlay = await page.waitForSelector('vite-error-overlay')\n    expect(errorOverlay).toBeTruthy()\n    const message = await errorOverlay.$$eval('.message-body', (m) => {\n      return m[0].innerHTML\n    })\n    // use regex with variable filename and position values because they are different on win\n    expect(message).toMatch(unexpectedTokenSyntaxErrorRE)\n  })\n\n  test('should reload when tsconfig is changed', async () => {\n    editFile('has-error/tsconfig.json', (content) => {\n      return content.replace('\"compilerOptions\":', '\"compilerOptions\":{}')\n    })\n    await expect\n      .poll(() => browserLogs)\n      .toContain('tsconfig error fixed, file loaded')\n  })\n})\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/has-error/main.ts",
    "content": "console.log('tsconfig error fixed, file loaded')\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/has-error/tsconfig.json",
    "content": "{\n  // this config is deliberately malformed to test how vite handles broken tsconfig\n  \"compilerOptions\":\n}"
  },
  {
    "path": "playground/tsconfig-json-load-error/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite App</title>\n  </head>\n  <body>\n    <div id=\"app\"><!--app-html--></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-tsconfig-json-load-error\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/src/main.ts",
    "content": "// @ts-nocheck\nimport '../has-error/main'\n"
  },
  {
    "path": "playground/tsconfig-json-load-error/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ESNext\",\n    \"module\": \"ESNext\",\n    \"lib\": [\"ESNext\", \"DOM\"],\n    \"moduleResolution\": \"bundler\",\n    \"strict\": true,\n    \"sourceMap\": true,\n    \"resolveJsonModule\": true,\n    \"esModuleInterop\": true,\n    \"noEmit\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noImplicitReturns\": true,\n\n    \"useDefineForClassFields\": true,\n    \"verbatimModuleSyntax\": true\n  },\n  \"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "playground/tsconfig.json",
    "content": "{\n  \"include\": [\"**/vite*config*\", \"**/*.ts\"],\n  \"exclude\": [\"**/dist/**\", \"./legacy/**\", \"./resolve-tsconfig-paths/**\"],\n  \"compilerOptions\": {\n    \"checkJs\": true,\n    \"target\": \"ES2023\",\n    \"module\": \"Preserve\",\n    \"noEmit\": true,\n    \"allowJs\": true,\n    \"esModuleInterop\": true,\n    \"resolveJsonModule\": true,\n    \"moduleResolution\": \"bundler\",\n    \"erasableSyntaxOnly\": true,\n    \"skipLibCheck\": true,\n    \"noUnusedLocals\": true,\n    \"jsx\": \"preserve\",\n    \"types\": [\"vite/client\", \"node\"],\n    \"paths\": {\n      \"~utils\": [\"./test-utils.ts\"]\n    }\n  }\n}\n"
  },
  {
    "path": "playground/vitestGlobalSetup.ts",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport type { TestProject } from 'vitest/node'\nimport type { BrowserServer } from 'playwright-chromium'\nimport { chromium } from 'playwright-chromium'\n\nlet browserServer: BrowserServer | undefined\n\nexport async function setup({ provide }: TestProject): Promise<void> {\n  browserServer = await chromium.launchServer({\n    headless: !process.env.VITE_DEBUG_SERVE,\n    args: process.env.CI\n      ? ['--no-sandbox', '--disable-setuid-sandbox']\n      : undefined,\n  })\n\n  provide('wsEndpoint', browserServer.wsEndpoint())\n\n  const tempDir = path.resolve(import.meta.dirname, '../playground-temp')\n  await fs.rm(tempDir, { recursive: true, force: true })\n  await fs.mkdir(tempDir, { recursive: true })\n  await fs\n    .cp(path.resolve(import.meta.dirname, '../playground'), tempDir, {\n      recursive: true,\n      dereference: false,\n      filter(file) {\n        file = file.replace(/\\\\/g, '/')\n        return !file.includes('__tests__') && !/dist(?:\\/|$)/.test(file)\n      },\n    })\n    .catch(async (error) => {\n      if (error.code === 'EPERM' && error.syscall === 'symlink') {\n        throw new Error(\n          'Could not create symlinks. On Windows, consider activating Developer Mode to allow non-admin users to create symlinks by following the instructions at https://docs.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development.',\n        )\n      } else {\n        throw error\n      }\n    })\n  // also setup dedicated copy for \"variant\" tests\n  for (const [original, variants] of [\n    ['assets', ['encoded-base', 'relative-base', 'runtime-base', 'url-base']],\n    ['css', ['lightningcss']],\n    ['transform-plugin', ['base']],\n  ] as const) {\n    for (const variant of variants) {\n      await fs.cp(\n        path.resolve(tempDir, original),\n        path.resolve(tempDir, `${original}__${variant}`),\n        { recursive: true },\n      )\n    }\n  }\n}\n\nexport async function teardown(): Promise<void> {\n  await browserServer?.close()\n  if (!process.env.VITE_PRESERVE_BUILD_ARTIFACTS) {\n    await fs.rm(path.resolve(import.meta.dirname, '../playground-temp'), {\n      recursive: true,\n    })\n  }\n}\n"
  },
  {
    "path": "playground/vitestSetup.ts",
    "content": "import type * as http from 'node:http'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { chromium } from 'playwright-chromium'\nimport type {\n  ConfigEnv,\n  InlineConfig,\n  Logger,\n  PluginOption,\n  ResolvedConfig,\n  UserConfig,\n  ViteDevServer,\n} from 'vite'\nimport {\n  build,\n  createBuilder,\n  createServer,\n  loadConfigFromFile,\n  mergeConfig,\n  preview,\n} from 'vite'\nimport type { Browser, Page } from 'playwright-chromium'\nimport type {\n  RolldownWatcher,\n  RolldownWatcherEvent,\n  RollupError,\n} from 'rolldown'\nimport { beforeAll, expect, inject } from 'vitest'\n\n// #region serializer\n\nexport const sourcemapSnapshot = Symbol()\n\nconst generateVisualizationLink = (code: string, map: string) => {\n  const utf16ToUTF8 = (x) => unescape(encodeURIComponent(x))\n  const convertedCode = utf16ToUTF8(code)\n  const convertedMap = utf16ToUTF8(map)\n  const hash = `${convertedCode.length}\\0${convertedCode}${convertedMap.length}\\0${convertedMap}`\n  return `https://evanw.github.io/source-map-visualization/#${btoa(hash)}`\n}\n\nexpect.addSnapshotSerializer({\n  serialize(val, config, indentation, depth, refs, printer) {\n    const options = val[sourcemapSnapshot]\n    const map = { ...val.map }\n    if (options.withoutContent) {\n      delete map.sourcesContent\n    }\n\n    return `${indentation}SourceMap {\n${indentation}${config.indent}content: ${printer(map, config, indentation + config.indent, depth, refs)},\n${indentation}${config.indent}visualization: ${JSON.stringify(generateVisualizationLink(val.code, JSON.stringify(val.map)))}\n${indentation}}`\n  },\n  test(val) {\n    return typeof val === 'object' && val && val[sourcemapSnapshot]\n  },\n})\n\n// #endregion\n\n// #region env\n\nexport const workspaceRoot = path.resolve(import.meta.dirname, '../')\n\nexport const isBuild = !!process.env.VITE_TEST_BUILD\nexport const isServe = !isBuild\nexport const isWindows = process.platform === 'win32'\nexport const viteBinPath = path.posix.join(\n  workspaceRoot,\n  'packages/vite/bin/vite.js',\n)\n\n// #endregion\n\n// #region context\n\nlet server: ViteDevServer | http.Server\n\n/**\n * Vite Dev Server when testing serve\n */\nexport let viteServer: ViteDevServer\n/**\n * Root of the Vite fixture\n */\nexport let rootDir: string\n/**\n * Path to the current test file\n */\nexport let testPath: string\n/**\n * Path to the test folder\n */\nexport let testDir: string\n/**\n * Test folder name\n */\nexport let testName: string\n\nexport const serverLogs: string[] = []\nexport const browserLogs: string[] = []\nexport const browserErrors: Error[] = []\n\nexport let page: Page = undefined!\nexport let browser: Browser = undefined!\nexport let viteTestUrl: string = ''\nexport let watcher: RolldownWatcher | undefined = undefined\n\nexport function setViteUrl(url: string): void {\n  viteTestUrl = url\n}\n\nfunction throwHtmlParseError() {\n  return {\n    name: 'vite-plugin-throw-html-parse-error',\n    configResolved(config: ResolvedConfig) {\n      const warn = config.logger.warn\n      config.logger.warn = (msg, opts) => {\n        // convert HTML parse warnings to make it easier to test\n        if (msg.includes('Unable to parse HTML;')) {\n          throw new Error(msg)\n        }\n        warn.call(config.logger, msg, opts)\n      }\n    },\n  }\n}\n// #endregion\n\n// eslint-disable-next-line no-empty-pattern\nbeforeAll(async ({}, suite) => {\n  testPath = suite.file.filepath!\n  testName = slash(testPath).match(/playground\\/([\\w-]+)\\//)?.[1]\n  testDir = path.dirname(testPath)\n  if (testName) {\n    testDir = path.resolve(workspaceRoot, 'playground-temp', testName)\n  }\n\n  // skip browser setup for hmr-ssr playground\n  if (testName === 'hmr-ssr') {\n    return\n  }\n\n  const wsEndpoint = inject('wsEndpoint')\n  if (!wsEndpoint) {\n    throw new Error('wsEndpoint not found')\n  }\n\n  browser = await chromium.connect(wsEndpoint)\n  page = await browser.newPage()\n\n  try {\n    page.on('console', (msg) => {\n      // ignore favicon request in headed browser\n      if (\n        process.env.VITE_DEBUG_SERVE &&\n        msg.text().includes('Failed to load resource:') &&\n        msg.location().url.includes('favicon.ico')\n      ) {\n        return\n      }\n      browserLogs.push(msg.text())\n    })\n    page.on('pageerror', (error) => {\n      browserErrors.push(error)\n    })\n\n    // if this is a test placed under playground/xxx/__tests__\n    // start a vite server in that directory.\n    if (testName) {\n      // when `root` dir is present, use it as vite's root\n      const testCustomRoot = path.resolve(testDir, 'root')\n      rootDir = fs.existsSync(testCustomRoot) ? testCustomRoot : testDir\n\n      // separate rootDir for variant\n      const variantName = path.basename(path.dirname(testPath))\n      if (variantName !== '__tests__') {\n        const variantTestDir = testDir + '__' + variantName\n        if (fs.existsSync(variantTestDir)) {\n          rootDir = testDir = variantTestDir\n        }\n      }\n\n      const testCustomServe = [\n        path.resolve(path.dirname(testPath), 'serve.ts'),\n        path.resolve(path.dirname(testPath), 'serve.js'),\n      ].find((i) => fs.existsSync(i))\n\n      if (testCustomServe) {\n        // test has custom server configuration.\n        const mod = await import(testCustomServe)\n        const serve = mod.serve || mod.default?.serve\n        const preServe = mod.preServe || mod.default?.preServe\n        if (preServe) {\n          await preServe()\n        }\n        if (serve) {\n          server = await serve()\n          viteServer = mod.viteServer\n        }\n      } else {\n        await startDefaultServe()\n      }\n    }\n  } catch (e) {\n    // Closing the page since an error in the setup, for example a runtime error\n    // when building the playground should skip further tests.\n    // If the page remains open, a command like `await page.click(...)` produces\n    // a timeout with an exception that hides the real error in the console.\n    await page.close()\n    await server?.close()\n    throw e\n  }\n\n  return async () => {\n    serverLogs.length = 0\n    await page?.close()\n    await server?.close()\n    await watcher?.close()\n    if (browser) {\n      await browser.close()\n    }\n  }\n})\n\nasync function loadConfig(configEnv: ConfigEnv) {\n  let config: UserConfig | null = null\n\n  // config file named by convention as the *.spec.ts folder\n  const variantName = path.basename(path.dirname(testPath))\n  if (variantName !== '__tests__') {\n    const configVariantPath = path.resolve(\n      rootDir,\n      `vite.config-${variantName}.js`,\n    )\n    if (fs.existsSync(configVariantPath)) {\n      const res = await loadConfigFromFile(configEnv, configVariantPath)\n      if (res) {\n        config = res.config\n      }\n    }\n  }\n  // config file from test root dir\n  if (!config) {\n    const res = await loadConfigFromFile(configEnv, undefined, rootDir)\n    if (res) {\n      config = res.config\n    }\n  }\n\n  const options: InlineConfig = {\n    root: rootDir,\n    logLevel: 'silent',\n    configFile: false,\n    server: {\n      watch: {\n        // During tests we edit the files too fast and sometimes chokidar\n        // misses change events, so enforce polling for consistency\n        usePolling: true,\n        interval: 100,\n      },\n    },\n    build: {\n      // esbuild do not minify ES lib output since that would remove pure annotations and break tree-shaking\n      // skip transpilation during tests to make it faster\n      target: 'esnext',\n      // tests are flaky when `emptyOutDir` is `true`\n      emptyOutDir: false,\n    },\n    customLogger: createInMemoryLogger(serverLogs),\n    plugins: [throwHtmlParseError()],\n  }\n  return mergeConfig(options, config || {})\n}\n\nexport async function startDefaultServe(): Promise<void> {\n  setupConsoleWarnCollector(serverLogs)\n\n  if (!isBuild) {\n    process.env.VITE_INLINE = 'inline-serve'\n    const config = await loadConfig({ command: 'serve', mode: 'development' })\n    viteServer = server = await (await createServer(config)).listen()\n    viteTestUrl = stripTrailingSlashIfNeeded(\n      server.resolvedUrls.local[0],\n      server.config.base,\n    )\n    await page.goto(viteTestUrl)\n  } else {\n    process.env.VITE_INLINE = 'inline-build'\n    let resolvedConfig: ResolvedConfig\n    // determine build watch\n    const resolvedPlugin: () => PluginOption = () => ({\n      name: 'vite-plugin-watcher',\n      configResolved(config) {\n        resolvedConfig = config\n      },\n    })\n    const buildConfig = mergeConfig(\n      await loadConfig({ command: 'build', mode: 'production' }),\n      {\n        plugins: [resolvedPlugin()],\n      },\n    )\n    if (buildConfig.builder) {\n      const builder = await createBuilder(buildConfig)\n      await builder.buildApp()\n    } else {\n      const rollupOutput = await build(buildConfig)\n      const isWatch = !!resolvedConfig!.build.watch\n      // in build watch,call startStaticServer after the build is complete\n      if (isWatch) {\n        watcher = rollupOutput as RolldownWatcher\n        await notifyRebuildComplete(watcher)\n      }\n      if (buildConfig.__test__) {\n        buildConfig.__test__()\n      }\n    }\n\n    const previewConfig = await loadConfig({\n      command: 'serve',\n      mode: 'development',\n      isPreview: true,\n    })\n    const _nodeEnv = process.env.NODE_ENV\n    const previewServer = await preview(previewConfig)\n    // prevent preview change NODE_ENV\n    process.env.NODE_ENV = _nodeEnv\n    viteTestUrl = stripTrailingSlashIfNeeded(\n      previewServer.resolvedUrls.local[0],\n      previewServer.config.base,\n    )\n    await page.goto(viteTestUrl)\n  }\n}\n\n/**\n * Send the rebuild complete message in build watch\n */\nexport async function notifyRebuildComplete(\n  watcher: RolldownWatcher,\n): Promise<void> {\n  let resolveFn: undefined | (() => void)\n  const callback = (event: RolldownWatcherEvent): void => {\n    if (event.code === 'END') {\n      resolveFn?.()\n    }\n  }\n  watcher.on('event', callback)\n  await new Promise<void>((resolve) => {\n    resolveFn = resolve\n  })\n\n  watcher.off('event', callback)\n}\n\nexport function createInMemoryLogger(logs: string[]): Logger {\n  const loggedErrors = new WeakSet<Error | RollupError>()\n  const warnedMessages = new Set<string>()\n\n  const logger: Logger = {\n    hasWarned: false,\n    hasErrorLogged: (err) => loggedErrors.has(err),\n    clearScreen: () => {},\n    info(msg) {\n      logs.push(msg)\n    },\n    warn(msg) {\n      logs.push(msg)\n      logger.hasWarned = true\n    },\n    warnOnce(msg) {\n      if (warnedMessages.has(msg)) return\n      logs.push(msg)\n      logger.hasWarned = true\n      warnedMessages.add(msg)\n    },\n    error(msg, opts) {\n      logs.push(msg)\n      if (opts?.error) {\n        loggedErrors.add(opts.error)\n      }\n    },\n  }\n\n  return logger\n}\n\nfunction setupConsoleWarnCollector(logs: string[]) {\n  const warn = console.warn\n  console.warn = (...args) => {\n    logs.push(args.join(' '))\n    return warn.call(console, ...args)\n  }\n}\n\nexport function slash(p: string): string {\n  return p.replace(/\\\\/g, '/')\n}\n\nfunction stripTrailingSlashIfNeeded(url: string, base: string): string {\n  if (base === '/') {\n    return url.replace(/\\/$/, '')\n  }\n  return url\n}\n\ndeclare module 'vite' {\n  export interface UserConfig {\n    /**\n     * special test only hook\n     *\n     * runs after build and before preview\n     */\n    __test__?: () => void\n  }\n}\n\ndeclare module 'vitest' {\n  export interface ProvidedContext {\n    wsEndpoint: string\n  }\n}\n"
  },
  {
    "path": "playground/wasm/__tests__/wasm.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page } from '~utils'\n\ntest('should work when inlined', async () => {\n  await page.click('.inline-wasm .run')\n  await expect\n    .poll(() => page.textContent('.inline-wasm .result'))\n    .toMatch('42')\n})\n\ntest('should work when output', async () => {\n  await page.click('.output-wasm .run')\n  await expect\n    .poll(() => page.textContent('.output-wasm .result'))\n    .toMatch('24')\n})\n\ntest('init function returns WebAssembly.Instance', async () => {\n  await page.click('.init-returns-instance .run')\n  await expect\n    .poll(() => page.textContent('.init-returns-instance .result'))\n    .toMatch('true')\n})\n\ntest('?url', async () => {\n  expect(await page.textContent('.url')).toMatch(\n    isBuild ? 'data:application/wasm' : '/light.wasm',\n  )\n})\n\ntest('should work when wasm in worker', async () => {\n  await expect.poll(() => page.textContent('.worker-wasm .result')).toMatch('3')\n})\n"
  },
  {
    "path": "playground/wasm/index.html",
    "content": "<h1>Web Assembly</h1>\n\n<div class=\"inline-wasm\">\n  <h3>When wasm is inline, result should be 42</h3>\n  <button class=\"run\">Click to run</button>\n  <span class=\"result\"></span>\n</div>\n\n<div class=\"output-wasm\">\n  <h3>When wasm is output, result should be 24</h3>\n  <button class=\"run\">Click to run</button>\n  <span class=\"result\"></span>\n</div>\n\n<div class=\"init-returns-instance\">\n  <h3>init function returns WebAssembly.Instance</h3>\n  <button class=\"run\">Click to run</button>\n  <span class=\"result\"></span>\n</div>\n\n<div>\n  <h3>Importing as URL</h3>\n  <span class=\"url\"></span>\n</div>\n\n<div class=\"worker-wasm\">\n  <h3>worker wasm</h3>\n  <span class=\"result\"></span>\n</div>\n\n<script type=\"module\">\n  import light from './light.wasm?init'\n  import heavy from './heavy.wasm?init'\n  import myWorker from './worker?worker'\n\n  const w = new myWorker()\n  w.addEventListener('message', (ev) => {\n    text('.worker-wasm .result', ev.data.result)\n  })\n\n  async function testWasm(init, resultElement) {\n    const { exported_func } = await init({\n      imports: {\n        imported_func: (res) => (resultElement.textContent = res),\n      },\n    }).then((i) => i.exports)\n    exported_func()\n  }\n\n  function text(el, text) {\n    document.querySelector(el).textContent = text\n  }\n\n  document\n    .querySelector('.inline-wasm .run')\n    .addEventListener('click', async () =>\n      testWasm(light, document.querySelector('.inline-wasm .result')),\n    )\n\n  document\n    .querySelector('.output-wasm .run')\n    .addEventListener('click', async () =>\n      testWasm(heavy, document.querySelector('.output-wasm .result')),\n    )\n\n  document\n    .querySelector('.init-returns-instance .run')\n    .addEventListener('click', async () => {\n      const res = await light({\n        imports: {\n          imported_func: (res) => (resultElement.textContent = res),\n        },\n      })\n      text(\n        '.init-returns-instance .result',\n        res instanceof WebAssembly.Instance,\n      )\n    })\n\n  import lightUrl from './light.wasm?url'\n  text('.url', lightUrl)\n</script>\n"
  },
  {
    "path": "playground/wasm/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-wasm\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\",\n    \"preview\": \"vite preview\"\n  }\n}\n"
  },
  {
    "path": "playground/wasm/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nexport default defineConfig({\n  build: {\n    // make cannot emit light.wasm\n    // and emit add.wasm\n    assetsInlineLimit: 80,\n  },\n})\n"
  },
  {
    "path": "playground/wasm/worker.js",
    "content": "import init from './add.wasm?init'\ninit().then(({ exports }) => {\n  self.postMessage({ result: exports.add(1, 2) })\n})\n"
  },
  {
    "path": "playground/worker/__tests__/es/worker-es.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { isBuild, page, testDir } from '~utils'\n\ntest('normal', async () => {\n  await expect.poll(() => page.textContent('.pong')).toMatch('pong')\n  await expect\n    .poll(() => page.textContent('.mode'))\n    .toMatch(process.env.NODE_ENV)\n  await expect\n    .poll(() => page.textContent('.bundle-with-plugin'))\n    .toMatch('worker bundle with plugin success!')\n  await expect\n    .poll(() => page.textContent('.asset-url'))\n    .toMatch(\n      isBuild\n        ? /\\/es\\/assets\\/worker_asset-vite-[\\w-]{8}\\.svg/\n        : '/es/vite.svg',\n    )\n  await expect.poll(() => page.textContent('.dep-cjs')).toMatch('[cjs ok]')\n})\n\ntest('named', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-named'))\n    .toMatch('namedWorker')\n})\n\ntest('TS output', async () => {\n  await expect.poll(() => page.textContent('.pong-ts-output')).toMatch('pong')\n})\n\ntest('inlined', async () => {\n  await expect.poll(() => page.textContent('.pong-inline')).toMatch('pong')\n})\n\ntest('named inlined', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-inline-named'))\n    .toMatch('namedInlineWorker')\n})\n\ntest('import meta url', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-inline-url'))\n    .toMatch(/^(blob|http):/)\n})\n\ntest('unicode inlined', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-inline-unicode'))\n    .toMatch('•pong•')\n})\n\ntest('shared worker', async () => {\n  await expect.poll(() => page.textContent('.tick-count')).toMatch('pong')\n})\n\ntest('named shared worker', async () => {\n  await expect.poll(() => page.textContent('.tick-count-named')).toMatch('pong')\n})\n\ntest('inline shared worker', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-shared-inline'))\n    .toMatch('pong')\n})\n\ntest('worker emitted and import.meta.url in nested worker (serve)', async () => {\n  await expect\n    .poll(() => page.textContent('.nested-worker'))\n    .toMatch('worker-nested-worker')\n  await expect\n    .poll(() => page.textContent('.nested-worker-module'))\n    .toMatch('sub-worker')\n  await expect\n    .poll(() => page.textContent('.nested-worker-constructor'))\n    .toMatch('\"type\":\"constructor\"')\n})\n\ntest('deeply nested workers', async () => {\n  await expect\n    .poll(() => page.textContent('.deeply-nested-worker'))\n    .toMatch(/Hello\\sfrom\\sroot.*\\/es\\/.+deeply-nested-worker\\.js/)\n  await expect\n    .poll(() => page.textContent('.deeply-nested-second-worker'))\n    .toMatch(/Hello\\sfrom\\ssecond.*\\/es\\/.+second-worker\\.js/)\n  await expect\n    .poll(() => page.textContent('.deeply-nested-third-worker'))\n    .toMatch(/Hello\\sfrom\\sthird.*\\/es\\/.+third-worker\\.js/)\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  // assert correct files\n  test('inlined code generation', async () => {\n    const assetsDir = path.resolve(testDir, 'dist/es/assets')\n    const files = fs.readdirSync(assetsDir)\n\n    // inline-only worker should not be emitted as a separate worker file\n    const workerFiles = files.filter((f) => f.startsWith('worker_'))\n    for (const file of workerFiles) {\n      const fileContent = fs.readFileSync(\n        path.resolve(assetsDir, file),\n        'utf-8',\n      )\n      expect(fileContent).not.toContain('my-inline-shared-worker.js')\n    }\n\n    const index = files.find((f) => f.includes('main-module'))\n    const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')\n    const worker = files.find((f) => f.includes('my-worker'))\n    const workerContent = fs.readFileSync(\n      path.resolve(assetsDir, worker),\n      'utf-8',\n    )\n\n    // worker should have all imports resolved and no exports\n    expect(workerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(workerContent).not.toMatch(/\\bexport\\b/)\n    // chunk\n    expect(content).toMatch('new Worker(`/es/assets')\n    expect(content).toMatch('new SharedWorker(`/es/assets')\n    // inlined worker\n    expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`)\n    expect(content).toMatch(`self.Blob`)\n    expect(content).toMatch(\n      /try\\{if\\(\\w+=\\w+&&\\(self\\.URL\\|\\|self\\.webkitURL\\)\\.createObjectURL\\(\\w+\\),!\\w+\\)throw``/,\n    )\n    // inlined shared worker\n    expect(content).toMatch(\n      'return new SharedWorker(`data:text/javascript;charset=utf-8,',\n    )\n  })\n\n  test('worker emitted and import.meta.url in nested worker (build)', async () => {\n    await expect\n      .poll(() => page.textContent('.nested-worker-module'))\n      .toMatch('\"type\":\"module\"')\n    await expect\n      .poll(() => page.textContent('.nested-worker-constructor'))\n      .toMatch('\"type\":\"constructor\"')\n  })\n})\n\ntest('module worker', async () => {\n  await expect\n    .poll(() => page.textContent('.worker-import-meta-url'))\n    .toMatch('A string')\n  await expect\n    .poll(() => page.textContent('.worker-import-meta-url-resolve'))\n    .toMatch('A string')\n  await expect\n    .poll(() => page.textContent('.worker-import-meta-url-without-extension'))\n    .toMatch('A string')\n  await expect\n    .poll(() => page.textContent('.shared-worker-import-meta-url'))\n    .toMatch('A string')\n})\n\ntest('classic worker', async () => {\n  await expect\n    .poll(() => page.textContent('.classic-worker'))\n    .toMatch('A classic')\n  if (!isBuild) {\n    await expect\n      .poll(() => page.textContent('.classic-worker-import'))\n      .toMatch('[success] classic-esm')\n  }\n  await expect\n    .poll(() => page.textContent('.classic-shared-worker'))\n    .toMatch('A classic')\n})\n\ntest('emit chunk', async () => {\n  await expect\n    .poll(() => page.textContent('.emit-chunk-worker'))\n    .toMatch(\n      '[\"A string\",{\"type\":\"emit-chunk-sub-worker\",\"data\":\"A string\"},{\"type\":\"module-and-worker:worker\",\"data\":\"A string\"},{\"type\":\"module-and-worker:module\",\"data\":\"module and worker\"},{\"type\":\"emit-chunk-sub-worker\",\"data\":{\"module\":\"module and worker\",\"msg1\":\"module1\",\"msg2\":\"module2\",\"msg3\":\"module3\"}}]',\n    )\n  await expect\n    .poll(() => page.textContent('.emit-chunk-dynamic-import-worker'))\n    .toMatch('\"A stringmodule1/es/\"')\n})\n\ntest('url query worker', async () => {\n  await expect\n    .poll(() => page.textContent('.simple-worker-url'))\n    .toMatch('Hello from simple worker!')\n})\n\ntest('import.meta.glob in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.importMetaGlob-worker'))\n    .toMatch('[\"')\n})\n\ntest('import.meta.glob with eager in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.importMetaGlobEager-worker'))\n    .toMatch('[\"')\n})\n\ntest.runIf(isBuild)('require json in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.worker-require-json'))\n    .toMatch('[{\"name\":\"a\"},{\"name\":\"b\"}]')\n})\n\ntest('self reference worker', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-worker'))\n    .toMatch('pong: main\\npong: nested\\n')\n})\n\ntest('self reference url worker', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-url-worker'))\n    .toMatch('pong: main\\npong: nested\\n')\n})\n"
  },
  {
    "path": "playground/worker/__tests__/iife/worker-iife.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport {\n  extractSourcemap,\n  formatSourcemapForSnapshot,\n  isBuild,\n  isServe,\n  page,\n  readManifest,\n  testDir,\n  viteTestUrl,\n} from '~utils'\n\ntest('normal', async () => {\n  await expect.poll(() => page.textContent('.pong')).toMatch('pong')\n  await expect\n    .poll(() => page.textContent('.mode'))\n    .toMatch(process.env.NODE_ENV)\n  await expect\n    .poll(() => page.textContent('.bundle-with-plugin'))\n    .toMatch('worker bundle with plugin success!')\n  await expect\n    .poll(() => page.textContent('.asset-url'))\n    .toMatch(\n      isBuild\n        ? /\\/iife\\/assets\\/worker_asset-vite-[\\w-]{8}\\.svg/\n        : '/iife/vite.svg',\n    )\n})\n\ntest('named', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-named'))\n    .toMatch('namedWorker')\n})\n\ntest('TS output', async () => {\n  await expect.poll(() => page.textContent('.pong-ts-output')).toMatch('pong')\n})\n\ntest('inlined', async () => {\n  await expect.poll(() => page.textContent('.pong-inline')).toMatch('pong')\n})\n\ntest('named inlined', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-inline-named'))\n    .toMatch('namedInlineWorker')\n})\n\ntest('shared worker', async () => {\n  await expect.poll(() => page.textContent('.tick-count')).toMatch('pong')\n})\n\ntest('named shared worker', async () => {\n  await expect.poll(() => page.textContent('.tick-count-named')).toMatch('pong')\n})\n\ntest('inline shared worker', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-shared-inline'))\n    .toMatch('pong')\n})\n\ntest.runIf(!isBuild)(\n  'worker emitted and import.meta.url in nested worker (serve)',\n  async () => {\n    await expect\n      .poll(() => page.textContent('.nested-worker'))\n      .toMatch('/worker-nested')\n    await expect\n      .poll(() => page.textContent('.nested-worker-module'))\n      .toMatch('/sub-worker')\n    await expect\n      .poll(() => page.textContent('.nested-worker-constructor'))\n      .toMatch('\"type\":\"constructor\"')\n  },\n)\n\ndescribe.runIf(isBuild)('build', () => {\n  // assert correct files\n  test('inlined code generation', async () => {\n    const assetsDir = path.resolve(testDir, 'dist/iife/assets')\n    const files = fs.readdirSync(assetsDir)\n\n    // inline-only worker should not be emitted as a separate worker file\n    const workerFiles = files.filter((f) => f.startsWith('worker_'))\n    for (const file of workerFiles) {\n      const fileContent = fs.readFileSync(\n        path.resolve(assetsDir, file),\n        'utf-8',\n      )\n      expect(fileContent).not.toContain('my-inline-shared-worker.js')\n    }\n\n    const index = files.find((f) => f.includes('main-module'))\n    const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')\n    const worker = files.find((f) => f.includes('worker_entry-my-worker'))\n    const workerContent = fs.readFileSync(\n      path.resolve(assetsDir, worker),\n      'utf-8',\n    )\n\n    // worker should have all imports resolved and no exports\n    expect(workerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(workerContent).not.toMatch(/\\bexport\\b/)\n    // chunk\n    expect(content).toMatch('new Worker(`/iife/assets')\n    expect(content).toMatch('new SharedWorker(`/iife/assets')\n    // inlined\n    expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`)\n    expect(content).toMatch(`self.Blob`)\n  })\n\n  test('worker emitted and import.meta.url in nested worker (build)', async () => {\n    await expect\n      .poll(() => page.textContent('.nested-worker-module'))\n      .toMatch('\"type\":\"module\"')\n    await expect\n      .poll(() => page.textContent('.nested-worker-constructor'))\n      .toMatch('\"type\":\"constructor\"')\n  })\n\n  test('should not emit worker manifest', async () => {\n    const manifest = readManifest('iife')\n    expect(manifest['index.html']).toBeDefined()\n  })\n})\n\ntest('module worker', async () => {\n  await expect\n    .poll(async () => page.textContent('.worker-import-meta-url'))\n    .toMatch(/A\\sstring.*\\/iife\\/.+url-worker\\.js.+url-worker\\.js/)\n  await expect\n    .poll(() => page.textContent('.worker-import-meta-url-resolve'))\n    .toMatch(/A\\sstring.*\\/iife\\/.+url-worker\\.js.+url-worker\\.js/)\n  await expect\n    .poll(() => page.textContent('.worker-import-meta-url-without-extension'))\n    .toMatch(/A\\sstring.*\\/iife\\/.+url-worker\\.js.+url-worker\\.js/)\n  await expect\n    .poll(() => page.textContent('.shared-worker-import-meta-url'))\n    .toMatch('A string')\n})\n\ntest('classic worker', async () => {\n  await expect\n    .poll(() => page.textContent('.classic-worker'))\n    .toMatch('A classic')\n  if (!isBuild) {\n    await expect\n      .poll(() => page.textContent('.classic-worker-import'))\n      .toMatch('[success] classic-esm')\n  }\n  await expect\n    .poll(() => page.textContent('.classic-shared-worker'))\n    .toMatch('A classic')\n})\n\ntest('url query worker', async () => {\n  await expect\n    .poll(() => page.textContent('.simple-worker-url'))\n    .toMatch('Hello from simple worker!')\n})\n\ntest('import.meta.glob eager in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.importMetaGlobEager-worker'))\n    .toMatch('[\"')\n})\n\ntest.runIf(isBuild)('require json in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.worker-require-json'))\n    .toMatch('[{\"name\":\"a\"},{\"name\":\"b\"}]')\n})\n\ntest('self reference worker', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-worker'))\n    .toBe('pong: main\\npong: nested\\n')\n})\n\ntest('self reference url worker', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-url-worker'))\n    .toBe('pong: main\\npong: nested\\n')\n})\n\ntest('self reference url worker in dependency', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-url-worker-dep'))\n    .toBe('pong: main\\npong: nested\\n')\n})\n\ntest.runIf(isServe)('sourcemap is correct after env is injected', async () => {\n  const response = page.waitForResponse(\n    /my-worker\\.ts\\?worker_file&type=module/,\n  )\n  await page.goto(viteTestUrl)\n  const code = (await (await response).text()).replace(\n    /^import \"\\/iife\\/@fs\\/.+?\\/client\\/env\\.mjs\"/,\n    '',\n  )\n  const map = extractSourcemap(code)\n  expect(formatSourcemapForSnapshot(map, code, true)).toMatchInlineSnapshot(`\n    SourceMap {\n      content: {\n        \"ignoreList\": [],\n        \"mappings\": \";;AAAA,SAAS,OAAO,kBAAkB;AAClC,OAAO,YAAY;AACnB,SAAS,MAAM,WAAW;AAC1B,SAAS,wBAAwB;AACjC,OAAO,aAAa;AACpB,MAAM,UAAU,OAAO,KAAK;AAE5B,KAAK,aAAa,MAAM;AACtB,KAAI,EAAE,SAAS,QAAQ;AACrB,OAAK,YAAY;GACf;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;;AAEJ,KAAI,EAAE,SAAS,gBAAgB;AAC7B,OAAK,YAAY;GACf,KAAK;GACL;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;;;AAGN,KAAK,YAAY;CACf;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,QAAQ,IAAI,eAAe\",\n        \"sources\": [\n          \"my-worker.ts?worker_file&type=module\",\n        ],\n        \"version\": 3,\n      },\n      visualization: \"https://evanw.github.io/source-map-visualization/#OTkwAAo7CmltcG9ydCB7IG1zZyBhcyBtc2dGcm9tRGVwIH0gZnJvbSAiL2lpZmUvbm9kZV9tb2R1bGVzLy52aXRlLWlpZmUvZGVwcy9Adml0ZWpzX3Rlc3QtZGVwLXRvLW9wdGltaXplLmpzP3Y9MDAwMDAwMDAiOwppbXBvcnQgX192aXRlX19janNJbXBvcnQyX192aXRlanNfdGVzdFdvcmtlckRlcENqcyBmcm9tICIvaWlmZS9ub2RlX21vZHVsZXMvLnZpdGUtaWlmZS9kZXBzL0B2aXRlanNfdGVzdC13b3JrZXItZGVwLWNqcy5qcz92PTAwMDAwMDAwIjsgY29uc3QgZGVwQ2pzID0gX192aXRlX19janNJbXBvcnQyX192aXRlanNfdGVzdFdvcmtlckRlcENqczsKaW1wb3J0IHsgbW9kZSwgbXNnIH0gZnJvbSAiL2lpZmUvbW9kdWxlcy93b3JrZXJJbXBvcnQudHMiOwppbXBvcnQgeyBidW5kbGVXaXRoUGx1Z2luIH0gZnJvbSAiL2lpZmUvbW9kdWxlcy90ZXN0LXBsdWdpbi5qcyI7CmltcG9ydCB2aXRlU3ZnIGZyb20gIi9paWZlL3ZpdGUuc3ZnP2ltcG9ydCI7CmNvbnN0IG1ldGFVcmwgPSBpbXBvcnQubWV0YS51cmw7CnNlbGYub25tZXNzYWdlID0gKGUpID0+IHsKCWlmIChlLmRhdGEgPT09ICJwaW5nIikgewoJCXNlbGYucG9zdE1lc3NhZ2UoewoJCQltc2csCgkJCW1vZGUsCgkJCWJ1bmRsZVdpdGhQbHVnaW4sCgkJCXZpdGVTdmcsCgkJCW1ldGFVcmwsCgkJCW5hbWUsCgkJCWRlcENqcwoJCX0pOwoJfQoJaWYgKGUuZGF0YSA9PT0gInBpbmctdW5pY29kZSIpIHsKCQlzZWxmLnBvc3RNZXNzYWdlKHsKCQkJbXNnOiAi4oCicG9uZ+KAoiIsCgkJCW1vZGUsCgkJCWJ1bmRsZVdpdGhQbHVnaW4sCgkJCXZpdGVTdmcsCgkJCW1ldGFVcmwsCgkJCW5hbWUsCgkJCWRlcENqcwoJCX0pOwoJfQp9OwpzZWxmLnBvc3RNZXNzYWdlKHsKCW1zZywKCW1vZGUsCglidW5kbGVXaXRoUGx1Z2luLAoJbXNnRnJvbURlcCwKCXZpdGVTdmcsCgltZXRhVXJsLAoJbmFtZSwKCWRlcENqcwp9KTsKLy8gZm9yIHNvdXJjZW1hcApjb25zb2xlLmxvZygibXktd29ya2VyLmpzIik7CjEzOTYAeyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6Ijs7QUFBQSxTQUFTLE9BQU8sa0JBQWtCO0FBQ2xDLE9BQU8sWUFBWTtBQUNuQixTQUFTLE1BQU0sV0FBVztBQUMxQixTQUFTLHdCQUF3QjtBQUNqQyxPQUFPLGFBQWE7QUFDcEIsTUFBTSxVQUFVLE9BQU8sS0FBSztBQUU1QixLQUFLLGFBQWEsTUFBTTtBQUN0QixLQUFJLEVBQUUsU0FBUyxRQUFRO0FBQ3JCLE9BQUssWUFBWTtHQUNmO0dBQ0E7R0FDQTtHQUNBO0dBQ0E7R0FDQTtHQUNBO0dBQ0QsQ0FBQzs7QUFFSixLQUFJLEVBQUUsU0FBUyxnQkFBZ0I7QUFDN0IsT0FBSyxZQUFZO0dBQ2YsS0FBSztHQUNMO0dBQ0E7R0FDQTtHQUNBO0dBQ0E7R0FDQTtHQUNELENBQUM7OztBQUdOLEtBQUssWUFBWTtDQUNmO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDQTtDQUNBO0NBQ0E7Q0FDRCxDQUFDOztBQUdGLFFBQVEsSUFBSSxlQUFlIiwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsibXktd29ya2VyLnRzP3dvcmtlcl9maWxlJnR5cGU9bW9kdWxlIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG1zZyBhcyBtc2dGcm9tRGVwIH0gZnJvbSAnQHZpdGVqcy90ZXN0LWRlcC10by1vcHRpbWl6ZSdcbmltcG9ydCBkZXBDanMgZnJvbSAnQHZpdGVqcy90ZXN0LXdvcmtlci1kZXAtY2pzJ1xuaW1wb3J0IHsgbW9kZSwgbXNnIH0gZnJvbSAnLi9tb2R1bGVzL3dvcmtlckltcG9ydC5qcydcbmltcG9ydCB7IGJ1bmRsZVdpdGhQbHVnaW4gfSBmcm9tICcuL21vZHVsZXMvdGVzdC1wbHVnaW4nXG5pbXBvcnQgdml0ZVN2ZyBmcm9tICcuL3ZpdGUuc3ZnJ1xuY29uc3QgbWV0YVVybCA9IGltcG9ydC5tZXRhLnVybFxuXG5zZWxmLm9ubWVzc2FnZSA9IChlKSA9PiB7XG4gIGlmIChlLmRhdGEgPT09ICdwaW5nJykge1xuICAgIHNlbGYucG9zdE1lc3NhZ2Uoe1xuICAgICAgbXNnLFxuICAgICAgbW9kZSxcbiAgICAgIGJ1bmRsZVdpdGhQbHVnaW4sXG4gICAgICB2aXRlU3ZnLFxuICAgICAgbWV0YVVybCxcbiAgICAgIG5hbWUsXG4gICAgICBkZXBDanMsXG4gICAgfSlcbiAgfVxuICBpZiAoZS5kYXRhID09PSAncGluZy11bmljb2RlJykge1xuICAgIHNlbGYucG9zdE1lc3NhZ2Uoe1xuICAgICAgbXNnOiAn4oCicG9uZ+KAoicsXG4gICAgICBtb2RlLFxuICAgICAgYnVuZGxlV2l0aFBsdWdpbixcbiAgICAgIHZpdGVTdmcsXG4gICAgICBtZXRhVXJsLFxuICAgICAgbmFtZSxcbiAgICAgIGRlcENqcyxcbiAgICB9KVxuICB9XG59XG5zZWxmLnBvc3RNZXNzYWdlKHtcbiAgbXNnLFxuICBtb2RlLFxuICBidW5kbGVXaXRoUGx1Z2luLFxuICBtc2dGcm9tRGVwLFxuICB2aXRlU3ZnLFxuICBtZXRhVXJsLFxuICBuYW1lLFxuICBkZXBDanMsXG59KVxuXG4vLyBmb3Igc291cmNlbWFwXG5jb25zb2xlLmxvZygnbXktd29ya2VyLmpzJylcbiJdfQ==\"\n    }\n  `)\n})\n"
  },
  {
    "path": "playground/worker/__tests__/relative-base/worker-relative-base.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { isBuild, page, testDir } from '~utils'\n\ntest('normal', async () => {\n  await expect.poll(() => page.textContent('.pong')).toMatch('pong')\n  await expect\n    .poll(() => page.textContent('.mode'))\n    .toMatch(process.env.NODE_ENV)\n  await expect\n    .poll(() => page.textContent('.bundle-with-plugin'))\n    .toMatch('worker bundle with plugin success!')\n  await expect\n    .poll(() => page.textContent('.asset-url'))\n    .toMatch(isBuild ? '/worker-assets/worker_asset-vite' : '/vite.svg')\n})\n\ntest('named', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-named'))\n    .toMatch('namedWorker')\n})\n\ntest('TS output', async () => {\n  await expect.poll(() => page.textContent('.pong-ts-output')).toMatch('pong')\n})\n\n// TODO: inline worker should inline assets\ntest.skip('inlined', async () => {\n  await expect.poll(() => page.textContent('.pong-inline')).toMatch('pong')\n})\n\ntest('shared worker', async () => {\n  await expect.poll(() => page.textContent('.tick-count')).toMatch('pong')\n})\n\ntest('named shared worker', async () => {\n  await expect.poll(() => page.textContent('.tick-count-named')).toMatch('pong')\n})\n\ntest('inline shared worker', async () => {\n  await expect\n    .poll(() => page.textContent('.pong-shared-inline'))\n    .toMatch('pong')\n})\n\ntest('worker emitted and import.meta.url in nested worker (serve)', async () => {\n  await expect\n    .poll(() => page.textContent('.nested-worker'))\n    .toMatch('worker-nested-worker')\n  await expect\n    .poll(() => page.textContent('.nested-worker-module'))\n    .toMatch('sub-worker')\n  await expect\n    .poll(() => page.textContent('.nested-worker-constructor'))\n    .toMatch('\"type\":\"constructor\"')\n})\n\ndescribe.runIf(isBuild)('build', () => {\n  // assert correct files\n  test('inlined code generation', () => {\n    const chunksDir = path.resolve(testDir, 'dist/relative-base/chunks')\n    const files = fs.readdirSync(chunksDir)\n    const index = files.find((f) => f.includes('main-module'))\n    const content = fs.readFileSync(path.resolve(chunksDir, index), 'utf-8')\n    const workerEntriesDir = path.resolve(\n      testDir,\n      'dist/relative-base/worker-entries',\n    )\n    const workerFiles = fs.readdirSync(workerEntriesDir)\n    const worker = workerFiles.find((f) => f.includes('worker_entry-my-worker'))\n    const workerContent = fs.readFileSync(\n      path.resolve(workerEntriesDir, worker),\n      'utf-8',\n    )\n\n    // worker should have all imports resolved and no exports\n    expect(workerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(workerContent).not.toMatch(/\\bexport\\b/)\n    // chunk\n    expect(content).toMatch('new Worker(``+new URL(`../worker-entries/')\n    expect(content).toMatch('new SharedWorker(``+new URL(`../worker-entries/')\n    // inlined\n    expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`)\n    expect(content).toMatch(`self.Blob`)\n  })\n\n  test('worker emitted and import.meta.url in nested worker (build)', async () => {\n    await expect\n      .poll(() => page.textContent('.nested-worker-module'))\n      .toMatch('\"type\":\"module\"')\n    await expect\n      .poll(() => page.textContent('.nested-worker-constructor'))\n      .toMatch('\"type\":\"constructor\"')\n  })\n})\n\ntest('module worker', async () => {\n  await expect\n    .poll(() => page.textContent('.shared-worker-import-meta-url'))\n    .toMatch('A string')\n})\n\ntest('classic worker', async () => {\n  await expect\n    .poll(() => page.textContent('.classic-worker'))\n    .toMatch('A classic')\n  if (!isBuild) {\n    await expect\n      .poll(() => page.textContent('.classic-worker-import'))\n      .toMatch('[success] classic-esm')\n  }\n  await expect\n    .poll(() => page.textContent('.classic-shared-worker'))\n    .toMatch('A classic')\n})\n\ntest.runIf(isBuild)('emit chunk', async () => {\n  await expect\n    .poll(() => page.textContent('.emit-chunk-worker'))\n    .toMatch(\n      '[\"A string\",{\"type\":\"emit-chunk-sub-worker\",\"data\":\"A string\"},{\"type\":\"module-and-worker:worker\",\"data\":\"A string\"},{\"type\":\"module-and-worker:module\",\"data\":\"module and worker\"},{\"type\":\"emit-chunk-sub-worker\",\"data\":{\"module\":\"module and worker\",\"msg1\":\"module1\",\"msg2\":\"module2\",\"msg3\":\"module3\"}}]',\n    )\n  await expect\n    .poll(() => page.textContent('.emit-chunk-dynamic-import-worker'))\n    .toMatch('\"A stringmodule1./\"')\n})\n\ntest('import.meta.glob in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.importMetaGlob-worker'))\n    .toMatch('[\"')\n})\n\ntest('import.meta.glob with eager in worker', async () => {\n  await expect\n    .poll(() => page.textContent('.importMetaGlobEager-worker'))\n    .toMatch('[\"')\n})\n\ntest('self reference worker', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-worker'))\n    .toBe('pong: main\\npong: nested\\n')\n})\n\ntest('self reference url worker', async () => {\n  await expect\n    .poll(() => page.textContent('.self-reference-url-worker'))\n    .toBe('pong: main\\npong: nested\\n')\n})\n"
  },
  {
    "path": "playground/worker/__tests__/relative-base-iife/worker-relative-base-iife.spec.ts",
    "content": "import { expect, test } from 'vitest'\nimport { isBuild, page } from '~utils'\n\ntest('asset url', async () => {\n  await expect\n    .poll(() => page.textContent('.asset-url'))\n    .toMatch(isBuild ? '/worker-assets/worker_asset-vite' : '/vite.svg')\n})\n"
  },
  {
    "path": "playground/worker/__tests__/sourcemap/worker-sourcemap.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { isBuild, testDir } from '~utils'\n\ndescribe.runIf(isBuild)('build', () => {\n  // assert correct files\n  test('sourcemap generation for web workers', async () => {\n    const assetsDir = path.resolve(testDir, 'dist/iife-sourcemap/assets')\n    const files = fs.readdirSync(assetsDir)\n\n    // every .js file should have a corresponding .js.map\n    for (const jsFile of files.filter((f) => f.endsWith('.js'))) {\n      expect(files, `missing sourcemap for ${jsFile}`).toContain(\n        `${jsFile}.map`,\n      )\n    }\n\n    const index = files.find((f) => f.includes('main-module'))\n    const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')\n    const indexSourcemap = getSourceMapUrl(content)\n    const worker = files.find((f) => /^my-worker-[-\\w]+\\.js$/.test(f))\n    const workerContent = fs.readFileSync(\n      path.resolve(assetsDir, worker),\n      'utf-8',\n    )\n    const workerSourcemap = getSourceMapUrl(workerContent)\n    const sharedWorker = files.find((f) =>\n      /^my-shared-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const sharedWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, sharedWorker),\n      'utf-8',\n    )\n    const sharedWorkerSourcemap = getSourceMapUrl(sharedWorkerContent)\n    const possibleTsOutputWorker = files.find((f) =>\n      /^possible-ts-output-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const possibleTsOutputWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, possibleTsOutputWorker),\n      'utf-8',\n    )\n    const possibleTsOutputWorkerSourcemap = getSourceMapUrl(\n      possibleTsOutputWorkerContent,\n    )\n    const workerNestedWorker = files.find((f) =>\n      /^worker-nested-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const workerNestedWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, workerNestedWorker),\n      'utf-8',\n    )\n    const workerNestedWorkerSourcemap = getSourceMapUrl(\n      workerNestedWorkerContent,\n    )\n    const subWorker = files.find((f) => /^sub-worker-[-\\w]+\\.js$/.test(f))\n    const subWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, subWorker),\n      'utf-8',\n    )\n    const subWorkerSourcemap = getSourceMapUrl(subWorkerContent)\n\n    expect(files).toContainEqual(\n      expect.stringMatching(/^index-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^my-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^my-shared-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^possible-ts-output-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^worker-nested-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^sub-worker-[-\\w]+\\.js\\.map$/),\n    )\n\n    // sourcemap should exist and have a data URL\n    expect(indexSourcemap).toMatch(/^main-module-[-\\w]+\\.js\\.map$/)\n    expect(workerSourcemap).toMatch(/^my-worker-[-\\w]+\\.js\\.map$/)\n    expect(sharedWorkerSourcemap).toMatch(/^my-shared-worker-[-\\w]+\\.js\\.map$/)\n    expect(possibleTsOutputWorkerSourcemap).toMatch(\n      /^possible-ts-output-worker-[-\\w]+\\.js\\.map$/,\n    )\n    expect(workerNestedWorkerSourcemap).toMatch(\n      /^worker-nested-worker-[-\\w]+\\.js\\.map$/,\n    )\n    expect(subWorkerSourcemap).toMatch(/^sub-worker-[-\\w]+\\.js\\.map$/)\n\n    // worker should have all imports resolved and no exports\n    expect(workerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(workerContent).not.toMatch(/\\bexport\\b/)\n\n    // shared worker should have all imports resolved and no exports\n    expect(sharedWorkerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(sharedWorkerContent).not.toMatch(/\\bexport\\b/)\n\n    // chunk\n    expect(content).toMatch('new Worker(`/iife-sourcemap/assets/my-worker')\n    expect(content).toMatch('new Worker(`data:text/javascript;charset=utf-8,')\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap/assets/possible-ts-output-worker',\n    )\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap/assets/worker-nested-worker',\n    )\n    expect(content).toMatch(\n      'new SharedWorker(`/iife-sourcemap/assets/my-shared-worker',\n    )\n\n    // inlined\n    expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`)\n    expect(content).toMatch(`self.Blob`)\n\n    expect(workerNestedWorkerContent).toMatch(\n      'new Worker(`/iife-sourcemap/assets/sub-worker',\n    )\n  })\n})\n\nfunction getSourceMapUrl(code: string): string {\n  const regex = /\\/\\/[#@]\\ssource(?:Mapping)?URL=\\s*(\\S+)/g\n  const matches = [...code.matchAll(regex)]\n  const results = matches.at(-1)\n\n  if (results && results.length >= 2) {\n    return results[1]\n  }\n  return null\n}\n"
  },
  {
    "path": "playground/worker/__tests__/sourcemap-hidden/worker-sourcemap-hidden.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { isBuild, testDir } from '~utils'\n\ndescribe.runIf(isBuild)('build', () => {\n  // assert correct files\n  test('sourcemap generation for web workers', async () => {\n    const assetsDir = path.resolve(testDir, 'dist/iife-sourcemap-hidden/assets')\n    const files = fs.readdirSync(assetsDir)\n\n    // every .js file should have a corresponding .js.map\n    for (const jsFile of files.filter((f) => f.endsWith('.js'))) {\n      expect(files, `missing sourcemap for ${jsFile}`).toContain(\n        `${jsFile}.map`,\n      )\n    }\n\n    const index = files.find((f) => f.includes('main-module'))\n    const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')\n    const indexSourcemap = getSourceMapUrl(content)\n    const worker = files.find((f) => /^my-worker-[-\\w]+\\.js$/.test(f))\n    const workerContent = fs.readFileSync(\n      path.resolve(assetsDir, worker),\n      'utf-8',\n    )\n    const workerSourcemap = getSourceMapUrl(workerContent)\n    const sharedWorker = files.find((f) =>\n      /^my-shared-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const sharedWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, sharedWorker),\n      'utf-8',\n    )\n    const sharedWorkerSourcemap = getSourceMapUrl(sharedWorkerContent)\n    const possibleTsOutputWorker = files.find((f) =>\n      /^possible-ts-output-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const possibleTsOutputWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, possibleTsOutputWorker),\n      'utf-8',\n    )\n    const possibleTsOutputWorkerSourcemap = getSourceMapUrl(\n      possibleTsOutputWorkerContent,\n    )\n    const workerNestedWorker = files.find((f) =>\n      /^worker-nested-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const workerNestedWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, workerNestedWorker),\n      'utf-8',\n    )\n    const workerNestedWorkerSourcemap = getSourceMapUrl(\n      workerNestedWorkerContent,\n    )\n    const subWorker = files.find((f) => /^sub-worker-[-\\w]+\\.js$/.test(f))\n    const subWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, subWorker),\n      'utf-8',\n    )\n    const subWorkerSourcemap = getSourceMapUrl(subWorkerContent)\n\n    expect(files).toContainEqual(\n      expect.stringMatching(/^index-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^my-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^my-shared-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^possible-ts-output-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^worker-nested-worker-[-\\w]+\\.js\\.map$/),\n    )\n    expect(files).toContainEqual(\n      expect.stringMatching(/^sub-worker-[-\\w]+\\.js\\.map$/),\n    )\n\n    // sourcemap should exist and have a data URL\n    expect(indexSourcemap).toBe(null)\n    expect(workerSourcemap).toBe(null)\n    expect(sharedWorkerSourcemap).toBe(null)\n    expect(possibleTsOutputWorkerSourcemap).toBe(null)\n    expect(workerNestedWorkerSourcemap).toBe(null)\n    expect(subWorkerSourcemap).toBe(null)\n\n    // worker should have all imports resolved and no exports\n    expect(workerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(workerContent).not.toMatch(/\\bexport\\b/)\n\n    // shared worker should have all imports resolved and no exports\n    expect(sharedWorkerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(sharedWorkerContent).not.toMatch(/\\bexport\\b/)\n\n    // chunk\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap-hidden/assets/my-worker',\n    )\n    expect(content).toMatch('new Worker(`data:text/javascript;charset=utf-8,')\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap-hidden/assets/possible-ts-output-worker',\n    )\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap-hidden/assets/worker-nested-worker',\n    )\n    expect(content).toMatch(\n      'new SharedWorker(`/iife-sourcemap-hidden/assets/my-shared-worker',\n    )\n\n    // inlined\n    expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`)\n    expect(content).toMatch(`self.Blob`)\n\n    expect(workerNestedWorkerContent).toMatch(\n      'new Worker(`/iife-sourcemap-hidden/assets/sub-worker',\n    )\n  })\n})\n\nfunction getSourceMapUrl(code: string): string {\n  const regex = /\\/\\/[#@]\\ssource(?:Mapping)?URL=\\s*(\\S+)/\n  const results = regex.exec(code)\n\n  if (results && results.length >= 2) {\n    return results[1]\n  }\n  return null\n}\n"
  },
  {
    "path": "playground/worker/__tests__/sourcemap-inline/worker-sourcemap-inline.spec.ts",
    "content": "import fs from 'node:fs'\nimport path from 'node:path'\nimport { describe, expect, test } from 'vitest'\nimport { isBuild, testDir } from '~utils'\n\ndescribe.runIf(isBuild)('build', () => {\n  // assert correct files\n  test('sourcemap generation for web workers', async () => {\n    const assetsDir = path.resolve(testDir, 'dist/iife-sourcemap-inline/assets')\n    const files = fs.readdirSync(assetsDir)\n    // inline sourcemaps should not produce .map files\n    expect(files.filter((f) => f.endsWith('.map'))).toStrictEqual([])\n    const index = files.find((f) => f.includes('main-module'))\n    const content = fs.readFileSync(path.resolve(assetsDir, index), 'utf-8')\n    const indexSourcemap = getSourceMapUrl(content)\n    const worker = files.find((f) => /^my-worker-[-\\w]+\\.js$/.test(f))\n    const workerContent = fs.readFileSync(\n      path.resolve(assetsDir, worker),\n      'utf-8',\n    )\n    const workerSourcemap = getSourceMapUrl(workerContent)\n    const sharedWorker = files.find((f) =>\n      /^my-shared-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const sharedWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, sharedWorker),\n      'utf-8',\n    )\n    const sharedWorkerSourcemap = getSourceMapUrl(sharedWorkerContent)\n    const possibleTsOutputWorker = files.find((f) =>\n      /^possible-ts-output-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const possibleTsOutputWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, possibleTsOutputWorker),\n      'utf-8',\n    )\n    const possibleTsOutputWorkerSourcemap = getSourceMapUrl(\n      possibleTsOutputWorkerContent,\n    )\n    const workerNestedWorker = files.find((f) =>\n      /^worker-nested-worker-[-\\w]+\\.js$/.test(f),\n    )\n    const workerNestedWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, workerNestedWorker),\n      'utf-8',\n    )\n    const workerNestedWorkerSourcemap = getSourceMapUrl(\n      workerNestedWorkerContent,\n    )\n    const subWorker = files.find((f) => /^sub-worker-[-\\w]+\\.js$/.test(f))\n    const subWorkerContent = fs.readFileSync(\n      path.resolve(assetsDir, subWorker),\n      'utf-8',\n    )\n    const subWorkerSourcemap = getSourceMapUrl(subWorkerContent)\n\n    // sourcemap should exist and have a data URL\n    expect(indexSourcemap).toMatch(/^data:/)\n    expect(workerSourcemap).toMatch(/^data:/)\n    expect(sharedWorkerSourcemap).toMatch(/^data:/)\n    expect(possibleTsOutputWorkerSourcemap).toMatch(/^data:/)\n    expect(workerNestedWorkerSourcemap).toMatch(/^data:/)\n    expect(subWorkerSourcemap).toMatch(/^data:/)\n\n    // worker should have all imports resolved and no exports\n    expect(workerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(workerContent).not.toMatch(/\\bexport\\b/)\n\n    // shared worker should have all imports resolved and no exports\n    expect(sharedWorkerContent).not.toMatch(/import\\s*[\"(]/)\n    expect(sharedWorkerContent).not.toMatch(/\\bexport\\b/)\n\n    // chunk\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap-inline/assets/my-worker',\n    )\n    expect(content).toMatch('new Worker(`data:text/javascript;charset=utf-8,')\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap-inline/assets/possible-ts-output-worker',\n    )\n    expect(content).toMatch(\n      'new Worker(`/iife-sourcemap-inline/assets/worker-nested-worker',\n    )\n    expect(content).toMatch(\n      'new SharedWorker(`/iife-sourcemap-inline/assets/my-shared-worker',\n    )\n\n    // inlined\n    expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`)\n    expect(content).toMatch(`self.Blob`)\n\n    expect(workerNestedWorkerContent).toMatch(\n      'new Worker(`/iife-sourcemap-inline/assets/sub-worker',\n    )\n  })\n})\n\nfunction getSourceMapUrl(code: string): string {\n  const regex = /\\/\\/[#@]\\ssource(?:Mapping)?URL=\\s*(\\S+)/\n  const results = regex.exec(code)\n\n  if (results && results.length >= 2) {\n    return results[1]\n  }\n  return null\n}\n"
  },
  {
    "path": "playground/worker/classic-esm.js",
    "content": "export const msg = '[success] classic-esm'\n"
  },
  {
    "path": "playground/worker/classic-shared-worker.js",
    "content": "let base = `/${self.location.pathname.split('/')[1]}`\nif (base.endsWith('.js') || base === `/worker-entries`) base = '' // for dev\n\nimportScripts(`${base}/classic.js`)\n\nself.onconnect = (event) => {\n  const port = event.ports[0]\n  port.postMessage(self.constant)\n}\n\n// for sourcemap\nconsole.log('classic-shared-worker.js')\n"
  },
  {
    "path": "playground/worker/classic-worker.js",
    "content": "(() => {})() // this is to test `importScripts` injection doesn't break the code\n\nlet base = `/${self.location.pathname.split('/')[1]}`\nif (base.endsWith('.js') || base === `/worker-entries`) base = '' // for dev\n\nimportScripts(`${base}/classic.js`)\n\nself.addEventListener('message', async (e) => {\n  switch (e.data) {\n    case 'ping': {\n      self.postMessage({\n        message: e.data,\n        result: self.constant,\n      })\n      break\n    }\n    case 'test-import': {\n      // Vite may inject imports to handle this dynamic import, make sure\n      // it still works in classic workers.\n      // NOTE: this test only works in dev.\n      const importPath = `${base}/classic-esm.js`\n      const { msg } = await import(/* @vite-ignore */ importPath)\n      self.postMessage({\n        message: e.data,\n        result: msg,\n      })\n      break\n    }\n  }\n})\n\n// for sourcemap\nconsole.log('classic-worker.js')\n"
  },
  {
    "path": "playground/worker/deeply-nested-second-worker.js",
    "content": "self.postMessage({\n  type: 'deeplyNestedSecondWorker',\n  data: [\n    'Hello from second level nested worker',\n    import.meta.env.BASE_URL,\n    self.location.url,\n    import.meta.url,\n  ].join(' '),\n})\n\nconst deeplyNestedThirdWorker = new Worker(\n  new URL('deeply-nested-third-worker.js', import.meta.url),\n  { type: 'module' },\n)\ndeeplyNestedThirdWorker.addEventListener('message', (ev) => {\n  self.postMessage(ev.data)\n})\n\nconsole.log('deeply-nested-second-worker.js')\n"
  },
  {
    "path": "playground/worker/deeply-nested-third-worker.js",
    "content": "self.postMessage({\n  type: 'deeplyNestedThirdWorker',\n  data: [\n    'Hello from third level nested worker',\n    import.meta.env.BASE_URL,\n    self.location.url,\n    import.meta.url,\n  ].join(' '),\n})\n\nconsole.log('deeply-nested-third-worker.js')\n"
  },
  {
    "path": "playground/worker/deeply-nested-worker.js",
    "content": "self.postMessage({\n  type: 'deeplyNestedWorker',\n  data: [\n    'Hello from root worker',\n    import.meta.env.BASE_URL,\n    self.location.url,\n    import.meta.url,\n  ].join(' '),\n})\n\nconst deeplyNestedSecondWorker = new Worker(\n  new URL('deeply-nested-second-worker.js', import.meta.url),\n  { type: 'module' },\n)\ndeeplyNestedSecondWorker.addEventListener('message', (ev) => {\n  self.postMessage(ev.data)\n})\n\nconsole.log('deeply-nested-worker.js')\n"
  },
  {
    "path": "playground/worker/dep-cjs/index.cjs",
    "content": "exports.test = '[cjs ok]'\n"
  },
  {
    "path": "playground/worker/dep-cjs/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-worker-dep-cjs\",\n  \"type\": \"commonjs\",\n  \"exports\": \"./index.cjs\"\n}\n"
  },
  {
    "path": "playground/worker/dep-cjs-with-json/data.json",
    "content": "[{ \"name\": \"a\" }, { \"name\": \"b\" }]\n"
  },
  {
    "path": "playground/worker/dep-cjs-with-json/importer.cjs",
    "content": "module.exports.content = require('./data.json')\n"
  },
  {
    "path": "playground/worker/dep-self-reference-url-worker/index.js",
    "content": "export function startWorker(handler) {\n  const worker = new Worker(new URL('./worker.js', import.meta.url), {\n    type: 'module',\n  })\n  worker.postMessage('main')\n  worker.addEventListener('message', (e) => {\n    handler(e)\n  })\n}\n"
  },
  {
    "path": "playground/worker/dep-self-reference-url-worker/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-self-reference-url-worker\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/worker/dep-self-reference-url-worker/worker.js",
    "content": "// copy of playground/worker/self-reference-url-worker.js\nself.addEventListener('message', (e) => {\n  if (e.data === 'main') {\n    const selfWorker = new Worker(new URL('./worker.js', import.meta.url), {\n      type: 'module',\n    })\n    selfWorker.postMessage('nested')\n    selfWorker.addEventListener('message', (e) => {\n      self.postMessage(e.data)\n    })\n  }\n\n  self.postMessage(`pong: ${e.data}`)\n})\n"
  },
  {
    "path": "playground/worker/dep-to-optimize/index.js",
    "content": "export const msg = 'dep-to-optimize'\n"
  },
  {
    "path": "playground/worker/dep-to-optimize/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-dep-to-optimize\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"type\": \"module\",\n  \"main\": \"index.js\"\n}\n"
  },
  {
    "path": "playground/worker/emit-chunk-dynamic-import-worker.js",
    "content": "import module1Url from './modules/module1.js?url'\n\nimport('./modules/module0').then((module) => {\n  import(/* @vite-ignore */ module1Url).then((module1) => {\n    self.postMessage(module.default + module1.msg1 + import.meta.env.BASE_URL)\n  })\n})\n\n// for sourcemap\nconsole.log('emit-chunk-dynamic-import-worker.js')\n"
  },
  {
    "path": "playground/worker/emit-chunk-nested-worker.js",
    "content": "import SubWorker from './emit-chunk-sub-worker?worker'\nconst subWorker = new SubWorker()\n\nsubWorker.onmessage = (event) => {\n  self.postMessage({\n    type: 'emit-chunk-sub-worker',\n    data: event.data,\n  })\n}\n\nconst moduleWorker = new Worker(\n  new URL('./module-and-worker.js', import.meta.url),\n  { type: 'module' },\n)\n\nmoduleWorker.onmessage = (event) => {\n  self.postMessage({\n    type: 'module-and-worker:worker',\n    data: event.data,\n  })\n}\n\nimport('./module-and-worker').then((res) => {\n  self.postMessage({\n    type: 'module-and-worker:module',\n    data: res.module,\n  })\n})\n\n// for sourcemap\nconsole.log('emit-chunk-nested-worker.js')\n"
  },
  {
    "path": "playground/worker/emit-chunk-sub-worker.js",
    "content": "Promise.all([\n  import('./module-and-worker'),\n  import('./modules/module2'),\n  import('./modules/module3'),\n]).then((data) => {\n  const _data = { ...data[0], ...data[1], ...data[2] }\n  self.postMessage(_data)\n})\n\n// for sourcemap\nconsole.log('emit-chunk-sub-worker.js')\n"
  },
  {
    "path": "playground/worker/importMetaGlob.worker.js",
    "content": "const modules = import.meta.glob('./modules/*js')\n\nself.onmessage = function (e) {\n  self.postMessage(Object.keys(modules))\n}\n\n// for sourcemap\nconsole.log('importMetaGlob.worker.js')\n"
  },
  {
    "path": "playground/worker/importMetaGlobEager.worker.js",
    "content": "const modules = import.meta.glob('./modules/*js', { eager: true })\n\nself.onmessage = function (e) {\n  self.postMessage(Object.keys(modules))\n}\n\n// for sourcemap\nconsole.log('importMetaGlobEager.worker.js')\n"
  },
  {
    "path": "playground/worker/index.html",
    "content": "<h2 class=\"format-iife\">format iife:</h2>\n<div>Expected values: <span class=\"mode-true\"></span></div>\n\n<p>worker template error match:</p>\n<code>\n  const worker = new Worker(new URL('./worker.js', import.meta.url))\n</code>\n\n<p>\n  import myWorker from '../my-worker?worker'\n  <span class=\"classname\">.pong</span>\n  <span class=\"classname\">.mode</span>\n  <span class=\"classname\">.bundle-with-plugin</span>\n  <span class=\"classname\">.asset-url</span>\n</p>\n<div>\n  <div>Response from worker: <span class=\"pong\"></span></div>\n  <div>mode: <span class=\"mode\"></span></div>\n  <div>bundle-with-plugin: <span class=\"bundle-with-plugin\"></span></div>\n  <div>asset-url: <span class=\"asset-url\"></span></div>\n  <div>dep-cjs: <span class=\"dep-cjs\"></span></div>\n</div>\n\n<p>\n  import myWorker from '../my-worker?worker'\n  <span>new myWorker({ name: \"named-worker\" })</span>\n  <span class=\"classname\">.pong-named</span>\n</p>\n<div>\n  <div>Response from worker: <span class=\"pong-named\"></span></div>\n</div>\n\n<p>\n  import InlineWorker from '../my-worker?worker&inline'\n  <span class=\"classname\">.pong-inline</span>\n</p>\n<code class=\"pong-inline\"></code>\n\n<p>\n  import InlineWorker from '../my-worker?worker&inline'\n  <span>new InlineWorker({ name: \"named-inline-worker\" })</span>\n  <span class=\"classname\">.pong-inline-named</span>\n</p>\n<code class=\"pong-inline-named\"></code>\n\n<p>\n  import InlineWorker from '../my-worker?worker&inline'\n  <span>new InlineWorker()</span>\n  <span>import.meta.url</span>\n  <span class=\"classname\">.pong-inline-url</span>\n</p>\n<code class=\"pong-inline-url\"></code>\n\n<p>\n  import InlineWorker from '../my-worker?worker&inline'\n  <span class=\"classname\">.pong-inline-unicode</span>\n</p>\n<code class=\"pong-inline-unicode\"></code>\n\n<p>\n  import TSOutputWorker from '../possible-ts-output-worker?worker'\n  <span class=\"classname\">.pong-ts-output</span>\n</p>\n<code class=\"pong-ts-output\"></code>\n\n<p>\n  import mySharedWorker from '../my-shared-worker?sharedworker&name=shared'\n  <span class=\"classname\">.tick-count</span>\n</p>\n<code class=\"tick-count\"></code>\n\n<p>\n  import mySharedWorker from '../my-shared-worker?sharedworker&name=shared'\n  <span>new mySharedWorker({ name: \"namedSharedWorker\" })</span>\n  <span class=\"classname\">.tick-count-named</span>\n</p>\n<code class=\"tick-count-named\"></code>\n\n<p>\n  import InlineSharedWorker from '../my-shared-worker?sharedworker&inline'\n  <span class=\"classname\">.pong-shared-inline</span>\n</p>\n<code class=\"pong-shared-inline\"></code>\n\n<p>\n  new Worker(new URL('./url-worker.js', import.meta.url), { type: 'module' })\n  <span class=\"classname\">.worker-import-meta-url</span>\n</p>\n<code class=\"worker-import-meta-url\"></code>\n\n<p>\n  new Worker(new URL('@/url-worker', import.meta.url), { type: 'module' })\n  <span class=\"classname\">.worker-import-meta-url-resolve</span>\n</p>\n<code class=\"worker-import-meta-url-resolve\"></code>\n\n<p>\n  new Worker(new URL('./url-worker', import.meta.url), { type: 'module' })\n  <span class=\"classname\">.worker-import-meta-url-without-extension</span>\n</p>\n<code class=\"worker-import-meta-url-without-extension\"></code>\n\n<p>\n  new SharedWorker(new URL('./url-shared-worker.js', import.meta.url), { type:\n  'module' })\n  <span class=\"classname\">.shared-worker-import-meta-url</span>\n</p>\n<code class=\"shared-worker-import-meta-url\"></code>\n\n<p>\n  import NestedWorker from './worker-nested-worker?worker' - import.meta.url\n  <span class=\"classname\">.nested-worker</span>\n</p>\n<code class=\"nested-worker\"></code>\n\n<p>\n  import NestedWorker from './worker-nested-worker?worker' - nested module\n  worker\n  <span class=\"classname\">.nested-worker-module</span>\n</p>\n<code class=\"nested-worker-module\"></code>\n\n<p>\n  import NestedWorker from './worker-nested-worker?worker' - nested worker\n  constructor\n  <span class=\"classname\">.nested-worker-constructor</span>\n</p>\n<code class=\"nested-worker-constructor\"></code>\n\n<p>\n  new Worker(new URL('./classic-worker.js', import.meta.url))\n  <span class=\"classname\">.classic-worker</span>\n</p>\n<code class=\"classic-worker\"></code>\n<code class=\"classic-worker-import\"></code>\n\n<p>\n  new SharedWorker(new URL('./classic-shared-worker.js', import.meta.url), {\n  type: 'classic' })\n  <span class=\"classname\">.classic-shared-worker</span>\n</p>\n<code class=\"classic-shared-worker\"></code>\n\n<p>\n  new Worker(new URL('../simple-worker.js', import.meta.url).href)\n  <span class=\"classname\">.simple-worker-url</span>\n</p>\n<code class=\"simple-worker-url\"></code>\n\n<p>\n  use import.meta.glob with eager in iife worker\n  <span class=\"classname\">.importMetaGlobEager-worker</span>\n</p>\n<code class=\"importMetaGlobEager-worker\"></code>\n\n<p>\n  self reference worker\n  <span class=\"classname\">.self-reference-worker</span>\n</p>\n<code class=\"self-reference-worker\"></code>\n\n<p>\n  new Worker(new URL('../self-reference-url-worker.js', import.meta.url))\n  <span class=\"classname\">.self-reference-url-worker</span>\n</p>\n<code class=\"self-reference-url-worker\"></code>\n\n<p>\n  <span class=\"classname\">.self-reference-url-worker-dep</span>\n</p>\n<code class=\"self-reference-url-worker-dep\"></code>\n\n<p>\n  new Worker(new URL('../deeply-nested-worker.js', import.meta.url), { type:\n  'module' })\n  <span class=\"classname\">.deeply-nested-worker</span>\n</p>\n<code class=\"deeply-nested-worker\"></code>\n\n<p>\n  new Worker(new URL('deeply-nested-second-worker.js', import.meta.url), { type:\n  'module' })\n  <span class=\"classname\">.deeply-nested-second-worker</span>\n</p>\n<code class=\"deeply-nested-second-worker\"></code>\n\n<p>\n  new Worker(new URL('deeply-nested-third-worker.js', import.meta.url), { type:\n  'module' })\n  <span class=\"classname\">.deeply-nested-third-worker</span>\n</p>\n<code class=\"deeply-nested-third-worker\"></code>\n\n<p>\n  require('./some.json') in worker\n  <span class=\"classname\">.worker-require-json</span>\n</p>\n<code class=\"worker-require-json\"></code>\n\n<hr />\n\n<h2 class=\"format-es\"></h2>\n\n<p>\n  use import.meta.glob in es worker\n  <span class=\"classname\">.importMetaGlob-worker</span>\n</p>\n<code class=\"importMetaGlob-worker\"></code>\n\n<p>\n  worker emit chunk <br />\n  module and worker:worker in worker file <br />\n  module and worker:module in worker file <br />\n  <span class=\"classname\">.emit-chunk-worker</span>\n</p>\n<code class=\"emit-chunk-worker\"></code>\n\n<p>\n  worker dynamic import to emit chunk\n  <span class=\"classname\">.emit-chunk-dynamic-import-worker</span>\n</p>\n<code class=\"emit-chunk-dynamic-import-worker\"></code>\n\n<p>\n  module and worker:worker in simple file\n  <span class=\"classname\">.module-and-worker-worker</span>\n</p>\n<code class=\"module-and-worker-worker\"></code>\n\n<style>\n  p {\n    background: rgba(0, 0, 0, 0.1);\n  }\n  .classname {\n    color: green;\n  }\n</style>\n<script type=\"module\" src=\"./worker/main.js\"></script>\n"
  },
  {
    "path": "playground/worker/module-and-worker.js",
    "content": "import constant from './modules/module0'\n\nself.postMessage(constant)\n\nexport const module = 'module and worker'\n\n// for sourcemap\nconsole.log('module-and-worker.js')\n"
  },
  {
    "path": "playground/worker/modules/module0.js",
    "content": "export default 'A string'\n"
  },
  {
    "path": "playground/worker/modules/module1.js",
    "content": "export const msg1 = 'module1'\n"
  },
  {
    "path": "playground/worker/modules/module2.js",
    "content": "export * from './module0'\nexport * from './module1'\nexport const msg2 = 'module2'\n"
  },
  {
    "path": "playground/worker/modules/module3.js",
    "content": "export * from './module0'\nexport const msg3 = 'module3'\n"
  },
  {
    "path": "playground/worker/modules/test-plugin.js",
    "content": "export const bundleWithPlugin = 'worker bundle with plugin fail.   '\n"
  },
  {
    "path": "playground/worker/modules/workerImport.ts",
    "content": "export const msg = 'pong'\nexport const mode = process.env.NODE_ENV\n"
  },
  {
    "path": "playground/worker/my-inline-shared-worker.ts",
    "content": "let inlineSharedWorkerCount = 0\n\n// @ts-expect-error onconnect exists in worker\nself.onconnect = (event) => {\n  inlineSharedWorkerCount++\n  const port = event.ports[0]\n  if (inlineSharedWorkerCount >= 2) {\n    port.postMessage('pong')\n  }\n}\n\n// for sourcemap\nconsole.log('my-inline-shared-worker.js')\n"
  },
  {
    "path": "playground/worker/my-shared-worker.ts",
    "content": "let sharedWorkerCount = 0\n\n// @ts-expect-error onconnect exists in worker\nself.onconnect = (event) => {\n  sharedWorkerCount++\n  const port = event.ports[0]\n  if (sharedWorkerCount >= 2) {\n    port.postMessage('pong')\n  }\n}\n\n// for sourcemap\nconsole.log('my-shared-worker.js')\n"
  },
  {
    "path": "playground/worker/my-worker.ts",
    "content": "import { msg as msgFromDep } from '@vitejs/test-dep-to-optimize'\nimport depCjs from '@vitejs/test-worker-dep-cjs'\nimport { mode, msg } from './modules/workerImport.js'\nimport { bundleWithPlugin } from './modules/test-plugin'\nimport viteSvg from './vite.svg'\nconst metaUrl = import.meta.url\n\nself.onmessage = (e) => {\n  if (e.data === 'ping') {\n    self.postMessage({\n      msg,\n      mode,\n      bundleWithPlugin,\n      viteSvg,\n      metaUrl,\n      name,\n      depCjs,\n    })\n  }\n  if (e.data === 'ping-unicode') {\n    self.postMessage({\n      msg: '•pong•',\n      mode,\n      bundleWithPlugin,\n      viteSvg,\n      metaUrl,\n      name,\n      depCjs,\n    })\n  }\n}\nself.postMessage({\n  msg,\n  mode,\n  bundleWithPlugin,\n  msgFromDep,\n  viteSvg,\n  metaUrl,\n  name,\n  depCjs,\n})\n\n// for sourcemap\nconsole.log('my-worker.js')\n"
  },
  {
    "path": "playground/worker/package.json",
    "content": "{\n  \"name\": \"@vitejs/test-worker\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite --config ./vite.config-iife.js\",\n    \"build\": \"vite --config ./vite.config-iife.js build\",\n    \"preview\": \"vite --config ./vite.config-iife.js preview\",\n    \"dev:es\": \"vite --config ./vite.config-es.js dev\",\n    \"build:es\": \"vite --config ./vite.config-es.js build\",\n    \"preview:es\": \"vite --config ./vite.config-es.js preview\",\n    \"dev:sourcemap\": \"WORKER_MODE=sourcemap vite --config ./vite.config-sourcemap.js dev\",\n    \"build:sourcemap\": \"WORKER_MODE=sourcemap vite --config ./vite.config-sourcemap.js build\",\n    \"preview:sourcemap\": \"WORKER_MODE=sourcemap vite --config ./vite.config-sourcemap.js preview\",\n    \"dev:sourcemap-hidden\": \"WORKER_MODE=hidden vite --config ./vite.config-sourcemap.js dev\",\n    \"build:sourcemap-hidden\": \"WORKER_MODE=hidden vite --config ./vite.config-sourcemap.js build\",\n    \"preview:sourcemap-hidden\": \"WORKER_MODE=hidden vite --config ./vite.config-sourcemap.js preview\",\n    \"dev:sourcemap-inline\": \"WORKER_MODE=inline vite --config ./vite.config-sourcemap.js dev\",\n    \"build:sourcemap-inline\": \"WORKER_MODE=inline vite --config ./vite.config-sourcemap.js build\",\n    \"preview:sourcemap-inline\": \"WORKER_MODE=inline vite --config ./vite.config-sourcemap.js preview\",\n    \"dev:relative-base\": \"WORKER_MODE=inline vite --config ./vite.config-relative-base.js dev\",\n    \"build:relative-base\": \"WORKER_MODE=inline vite --config ./vite.config-relative-base.js build\",\n    \"preview:relative-base\": \"WORKER_MODE=inline vite --config ./vite.config-relative-base.js preview\",\n    \"dev:relative-base-iife\": \"WORKER_MODE=inline vite --config ./vite.config-relative-base-iife.js dev\",\n    \"build:relative-base-iife\": \"WORKER_MODE=inline vite --config ./vite.config-relative-base-iife.js build\",\n    \"preview:relative-base-iife\": \"WORKER_MODE=inline vite --config ./vite.config-relative-base-iife.js preview\",\n    \"debug\": \"node --inspect-brk ../../packages/vite/bin/vite\"\n  },\n  \"dependencies\": {\n    \"@vitejs/test-dep-self-reference-url-worker\": \"file:./dep-self-reference-url-worker\",\n    \"@vitejs/test-dep-to-optimize\": \"file:./dep-to-optimize\",\n    \"@vitejs/test-worker-dep-cjs\": \"file:./dep-cjs\"\n  }\n}\n"
  },
  {
    "path": "playground/worker/possible-ts-output-worker.mjs",
    "content": "import { mode, msg } from './modules/workerImport'\n\nself.onmessage = (e) => {\n  self.postMessage({ msg, mode })\n}\n\nself.postMessage({ msg, mode })\n\n// for sourcemap\nconsole.log('possible-ts-output-worker.mjs')\n"
  },
  {
    "path": "playground/worker/public/classic.js",
    "content": "self.constant = 'A classic'\n"
  },
  {
    "path": "playground/worker/self-reference-url-worker.js",
    "content": "self.addEventListener('message', (e) => {\n  if (e.data === 'main') {\n    const selfWorker = new Worker(\n      new URL('./self-reference-url-worker.js', import.meta.url),\n      {\n        type: 'module',\n      },\n    )\n    selfWorker.postMessage('nested')\n    selfWorker.addEventListener('message', (e) => {\n      self.postMessage(e.data)\n    })\n  }\n\n  self.postMessage(`pong: ${e.data}`)\n})\n"
  },
  {
    "path": "playground/worker/self-reference-worker.js",
    "content": "import SelfWorker from './self-reference-worker?worker'\n\nself.addEventListener('message', (e) => {\n  if (e.data === 'main') {\n    const selfWorker = new SelfWorker()\n    selfWorker.postMessage('nested')\n    selfWorker.addEventListener('message', (e) => {\n      self.postMessage(e.data)\n    })\n  }\n\n  self.postMessage(`pong: ${e.data}`)\n})\n"
  },
  {
    "path": "playground/worker/simple-worker.js",
    "content": "self.postMessage('Hello from simple worker!')\n"
  },
  {
    "path": "playground/worker/sub-worker.js",
    "content": "self.onmessage = (event) => {\n  if (event.data === 'ping') {\n    self.postMessage(`pong ${self.location.href}`)\n  }\n}\n\n// for sourcemap\nconsole.log('sub-worker.js')\n"
  },
  {
    "path": "playground/worker/url-shared-worker.js",
    "content": "import constant from './modules/module0.js'\n\nself.onconnect = (event) => {\n  const port = event.ports[0]\n  port.postMessage(constant)\n}\n\n// for sourcemap\nconsole.log('url-shared-worker.js')\n"
  },
  {
    "path": "playground/worker/url-worker.js",
    "content": "self.postMessage(\n  [\n    'A string',\n    import.meta.env.BASE_URL,\n    self.location.url,\n    import.meta && import.meta.url,\n    import.meta.url,\n  ].join(' '),\n)\n\n// for sourcemap\nconsole.log('url-worker.js')\n"
  },
  {
    "path": "playground/worker/vite.config-es.js",
    "content": "import { defineConfig } from 'vite'\nimport workerPluginTestPlugin from './worker-plugin-test-plugin'\n\nexport default defineConfig({\n  base: '/es/',\n  resolve: {\n    alias: {\n      '@': import.meta.dirname,\n    },\n  },\n  worker: {\n    format: 'es',\n    plugins: () => [workerPluginTestPlugin()],\n    rollupOptions: {\n      output: {\n        assetFileNames: 'assets/worker_asset-[name]-[hash].[ext]',\n        chunkFileNames: 'assets/worker_chunk-[name]-[hash].js',\n        entryFileNames: 'assets/worker_entry-[name].js',\n      },\n    },\n  },\n  build: {\n    outDir: 'dist/es',\n    assetsInlineLimit: (filePath) =>\n      filePath.endsWith('.svg') ? false : undefined,\n    rollupOptions: {\n      output: {\n        assetFileNames: 'assets/[name]-[hash].[ext]',\n        chunkFileNames: 'assets/[name]-[hash].js',\n        entryFileNames: 'assets/[name].js',\n      },\n    },\n  },\n  plugins: [\n    workerPluginTestPlugin(),\n    {\n      name: 'resolve-format-es',\n\n      transform(code, id) {\n        if (id.includes('main.js')) {\n          return code.replace(\n            `/* flag: will replace in vite config import(\"./format-es.js\") */`,\n            `import(\"./main-format-es\")`,\n          )\n        }\n      },\n    },\n  ],\n  cacheDir: 'node_modules/.vite-es',\n})\n"
  },
  {
    "path": "playground/worker/vite.config-iife.js",
    "content": "import { defineConfig } from 'vite'\nimport workerPluginTestPlugin from './worker-plugin-test-plugin'\n\nexport default defineConfig({\n  base: '/iife/',\n  resolve: {\n    alias: {\n      '@': import.meta.dirname,\n    },\n  },\n  worker: {\n    format: 'iife',\n    plugins: () => [workerPluginTestPlugin()],\n    rollupOptions: {\n      output: {\n        assetFileNames: 'assets/worker_asset-[name]-[hash].[ext]',\n        chunkFileNames: 'assets/worker_chunk-[name]-[hash].js',\n        // should be overwritten to worker_entry-[name] by the config-test plugin\n        entryFileNames: 'assets/worker_-[name].js',\n      },\n    },\n  },\n  build: {\n    outDir: 'dist/iife',\n    assetsInlineLimit: (filePath) =>\n      filePath.endsWith('.svg') ? false : undefined,\n    manifest: true,\n    rollupOptions: {\n      output: {\n        assetFileNames: 'assets/[name]-[hash].[ext]',\n        chunkFileNames: 'assets/[name]-[hash].js',\n        entryFileNames: 'assets/[name].js',\n      },\n    },\n  },\n  plugins: [\n    workerPluginTestPlugin(),\n    {\n      name: 'config-test',\n      config() {\n        return {\n          worker: {\n            rollupOptions: {\n              output: {\n                entryFileNames: 'assets/worker_entry-[name].js',\n              },\n            },\n          },\n        }\n      },\n    },\n  ],\n  cacheDir: 'node_modules/.vite-iife',\n  optimizeDeps: {\n    exclude: ['@vitejs/test-dep-self-reference-url-worker'],\n  },\n})\n"
  },
  {
    "path": "playground/worker/vite.config-relative-base-iife.js",
    "content": "import { defineConfig } from 'vite'\nimport workerPluginTestPlugin from './worker-plugin-test-plugin'\n\nexport default defineConfig(({ isPreview }) => ({\n  base: !isPreview ? './' : '/relative-base-iife/',\n  resolve: {\n    alias: {\n      '@': import.meta.dirname,\n    },\n  },\n  worker: {\n    format: 'iife',\n    plugins: () => [workerPluginTestPlugin()],\n    rollupOptions: {\n      output: {\n        assetFileNames: 'worker-assets/worker_asset-[name]-[hash].[ext]',\n        chunkFileNames: 'worker-chunks/worker_chunk-[name]-[hash].js',\n        entryFileNames: 'worker-entries/worker_entry-[name]-[hash].js',\n      },\n    },\n  },\n  build: {\n    outDir: 'dist/relative-base-iife',\n    assetsInlineLimit: (filePath) =>\n      filePath.endsWith('.svg') ? false : undefined,\n    rollupOptions: {\n      output: {\n        assetFileNames: 'other-assets/[name]-[hash].[ext]',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        entryFileNames: 'entries/[name]-[hash].js',\n      },\n    },\n  },\n  plugins: [workerPluginTestPlugin()],\n  cacheDir: 'node_modules/.vite-relative-base-iife',\n}))\n"
  },
  {
    "path": "playground/worker/vite.config-relative-base.js",
    "content": "import { defineConfig } from 'vite'\nimport workerPluginTestPlugin from './worker-plugin-test-plugin'\n\nexport default defineConfig(({ isPreview }) => ({\n  base: !isPreview ? './' : '/relative-base/',\n  resolve: {\n    alias: {\n      '@': import.meta.dirname,\n    },\n  },\n  worker: {\n    format: 'es',\n    plugins: () => [workerPluginTestPlugin()],\n    rollupOptions: {\n      output: {\n        assetFileNames: 'worker-assets/worker_asset-[name]-[hash].[ext]',\n        chunkFileNames: 'worker-chunks/worker_chunk-[name]-[hash].js',\n        entryFileNames: 'worker-entries/worker_entry-[name]-[hash].js',\n      },\n    },\n  },\n  build: {\n    outDir: 'dist/relative-base',\n    assetsInlineLimit: (filePath) =>\n      filePath.endsWith('.svg') ? false : undefined,\n    rollupOptions: {\n      output: {\n        assetFileNames: 'other-assets/[name]-[hash].[ext]',\n        chunkFileNames: 'chunks/[name]-[hash].js',\n        entryFileNames: 'entries/[name]-[hash].js',\n      },\n    },\n  },\n  plugins: [\n    workerPluginTestPlugin(),\n    {\n      name: 'resolve-format-es',\n      transform(code, id) {\n        if (id.includes('main.js')) {\n          return code.replace(\n            `/* flag: will replace in vite config import(\"./format-es.js\") */`,\n            `import(\"./main-format-es\")`,\n          )\n        }\n      },\n    },\n  ],\n  cacheDir: 'node_modules/.vite-relative-base',\n}))\n"
  },
  {
    "path": "playground/worker/vite.config-sourcemap-hidden.js",
    "content": "import sourcemap from './worker-sourcemap-config.js'\nexport default sourcemap('hidden')\n"
  },
  {
    "path": "playground/worker/vite.config-sourcemap-inline.js",
    "content": "import sourcemap from './worker-sourcemap-config.js'\nexport default sourcemap('inline')\n"
  },
  {
    "path": "playground/worker/vite.config-sourcemap.js",
    "content": "import sourcemap from './worker-sourcemap-config.js'\nexport default sourcemap(true)\n"
  },
  {
    "path": "playground/worker/worker/main-classic.js",
    "content": "// prettier-ignore\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nlet classicWorker = new Worker(\n  new URL('../classic-worker.js', import.meta.url) /* , */,\n  // test comment\n)\n\n// just test for case: ') ... ,' mean no worker options params\nclassicWorker = new Worker(new URL('../classic-worker.js', import.meta.url))\n\nclassicWorker.addEventListener('message', ({ data }) => {\n  switch (data.message) {\n    case 'ping': {\n      text('.classic-worker', data.result)\n      break\n    }\n    case 'test-import': {\n      text('.classic-worker-import', data.result)\n      break\n    }\n  }\n})\nclassicWorker.postMessage('ping')\nclassicWorker.postMessage('test-import')\n\n// prettier-ignore\n// test trailing comma\nconst classicSharedWorker = new SharedWorker(\n  new URL('../classic-shared-worker.js', import.meta.url),\n  {\n    type: 'classic'\n  }, // test comment\n)\nclassicSharedWorker.port.addEventListener('message', (ev) => {\n  text('.classic-shared-worker', JSON.stringify(ev.data))\n})\nclassicSharedWorker.port.start()\n"
  },
  {
    "path": "playground/worker/worker/main-deeply-nested.js",
    "content": "const worker = new Worker(\n  new URL('../deeply-nested-worker.js', import.meta.url),\n  { type: 'module' },\n)\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nworker.addEventListener('message', (ev) => {\n  if (ev.data.type === 'deeplyNestedSecondWorker') {\n    text('.deeply-nested-second-worker', JSON.stringify(ev.data.data))\n  } else if (ev.data.type === 'deeplyNestedThirdWorker') {\n    text('.deeply-nested-third-worker', JSON.stringify(ev.data.data))\n  } else {\n    text('.deeply-nested-worker', JSON.stringify(ev.data.data))\n  }\n})\n"
  },
  {
    "path": "playground/worker/worker/main-format-es.js",
    "content": "// run when format es\nimport NestedWorker from '../emit-chunk-nested-worker?worker'\nimport ImportMetaGlobWorker from '../importMetaGlob.worker?worker'\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\ntext('.format-es', 'format es:')\n\nconst nestedWorker = new NestedWorker()\nconst dataList = []\nnestedWorker.addEventListener('message', (ev) => {\n  dataList.push(ev.data)\n  text(\n    '.emit-chunk-worker',\n    JSON.stringify(\n      dataList.sort(\n        (a, b) => JSON.stringify(a).length - JSON.stringify(b).length,\n      ),\n    ),\n  )\n})\n\nconst dynamicImportWorker = new Worker(\n  new URL('../emit-chunk-dynamic-import-worker.js', import.meta.url),\n  {\n    type: 'module',\n  },\n)\ndynamicImportWorker.addEventListener('message', (ev) => {\n  text('.emit-chunk-dynamic-import-worker', JSON.stringify(ev.data))\n})\n\nconst moduleWorker = new Worker(\n  new URL('../module-and-worker.js', import.meta.url),\n  { type: 'module' },\n)\n\nmoduleWorker.addEventListener('message', (ev) => {\n  text('.module-and-worker-worker', JSON.stringify(ev.data))\n})\n\nconst importMetaGlobWorker = new ImportMetaGlobWorker()\n\nimportMetaGlobWorker.postMessage('1')\n\nimportMetaGlobWorker.addEventListener('message', (e) => {\n  text('.importMetaGlob-worker', JSON.stringify(e.data))\n})\n"
  },
  {
    "path": "playground/worker/worker/main-module.js",
    "content": "import * as depSelfReferenceUrlWorker from '@vitejs/test-dep-self-reference-url-worker'\nimport myWorker from '../my-worker.ts?worker'\nimport InlineWorker from '../my-worker.ts?worker&inline'\nimport InlineSharedWorker from '../my-inline-shared-worker?sharedworker&inline'\nimport mySharedWorker from '../my-shared-worker?sharedworker&name=shared'\nimport TSOutputWorker from '../possible-ts-output-worker?worker'\nimport NestedWorker from '../worker-nested-worker?worker'\nimport { mode } from '../modules/workerImport'\nimport SelfReferenceWorker from '../self-reference-worker?worker'\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\ndocument.querySelector('.mode-true').textContent = mode\n\nconst worker = new myWorker()\nworker.postMessage('ping')\nworker.addEventListener('message', (e) => {\n  text('.pong', e.data.msg)\n  text('.mode', e.data.mode)\n  text('.bundle-with-plugin', e.data.bundleWithPlugin)\n  text('.asset-url', e.data.viteSvg)\n  text('.dep-cjs', e.data.depCjs.test)\n})\n\nconst namedWorker = new myWorker({ name: 'namedWorker' })\nnamedWorker.postMessage('ping')\nnamedWorker.addEventListener('message', (e) => {\n  text('.pong-named', e.data.name)\n})\n\nconst inlineWorker = new InlineWorker()\ninlineWorker.postMessage('ping')\ninlineWorker.addEventListener('message', (e) => {\n  text('.pong-inline', e.data.msg)\n})\n\nconst namedInlineWorker = new InlineWorker({ name: 'namedInlineWorker' })\nnamedInlineWorker.postMessage('ping')\nnamedInlineWorker.addEventListener('message', (e) => {\n  text('.pong-inline-named', e.data.name)\n})\n\nconst inlineWorkerUrl = new InlineWorker()\ninlineWorkerUrl.postMessage('ping')\ninlineWorkerUrl.addEventListener('message', (e) => {\n  text('.pong-inline-url', e.data.metaUrl)\n})\n\nconst unicodeInlineWorker = new InlineWorker()\nunicodeInlineWorker.postMessage('ping-unicode')\nunicodeInlineWorker.addEventListener('message', (e) => {\n  text('.pong-inline-unicode', e.data.msg)\n})\n\nconst startSharedWorker = () => {\n  const sharedWorker = new mySharedWorker()\n  sharedWorker.port.addEventListener('message', (event) => {\n    text('.tick-count', event.data)\n  })\n  sharedWorker.port.start()\n}\nstartSharedWorker()\nstartSharedWorker()\n\nconst startNamedSharedWorker = () => {\n  const sharedWorker = new mySharedWorker({ name: 'namedSharedWorker' })\n  sharedWorker.port.addEventListener('message', (event) => {\n    text('.tick-count-named', event.data)\n  })\n  sharedWorker.port.start()\n}\nstartNamedSharedWorker()\nstartNamedSharedWorker()\n\nconst startInlineSharedWorker = () => {\n  const inlineSharedWorker = new InlineSharedWorker()\n  inlineSharedWorker.port.addEventListener('message', (event) => {\n    text('.pong-shared-inline', event.data)\n  })\n  inlineSharedWorker.port.start()\n}\n\nstartInlineSharedWorker()\nstartInlineSharedWorker()\n\nconst tsOutputWorker = new TSOutputWorker()\ntsOutputWorker.postMessage('ping')\ntsOutputWorker.addEventListener('message', (e) => {\n  text('.pong-ts-output', e.data.msg)\n})\n\nconst nestedWorker = new NestedWorker()\nnestedWorker.addEventListener('message', (ev) => {\n  if (typeof ev.data === 'string') {\n    text('.nested-worker', JSON.stringify(ev.data))\n  } else if (typeof ev.data === 'object') {\n    const data = ev.data\n    if (data.type === 'module') {\n      text('.nested-worker-module', JSON.stringify(ev.data))\n    } else if (data.type === 'constructor') {\n      text('.nested-worker-constructor', JSON.stringify(ev.data))\n    } else if (data.type === 'importMetaGlobEager') {\n      text('.importMetaGlobEager-worker', JSON.stringify(ev.data))\n    }\n  }\n})\nnestedWorker.postMessage('ping')\n\nconst workerOptions = { type: 'module' }\n// url import worker\nconst w = new Worker(\n  new URL('../url-worker.js', import.meta.url),\n  /* @vite-ignore */ workerOptions,\n)\nw.addEventListener('message', (ev) =>\n  text('.worker-import-meta-url', JSON.stringify(ev.data)),\n)\n\n// url import worker with alias path\nconst wResolve = new Worker(\n  new URL('@/url-worker.js', import.meta.url),\n  /* @vite-ignore */ workerOptions,\n)\nwResolve.addEventListener('message', (ev) =>\n  text('.worker-import-meta-url-resolve', JSON.stringify(ev.data)),\n)\n\n// url import worker without extension\nconst wWithoutExt = new Worker(\n  new URL('../url-worker', import.meta.url),\n  /* @vite-ignore */ workerOptions,\n)\nwWithoutExt.addEventListener('message', (ev) =>\n  text('.worker-import-meta-url-without-extension', JSON.stringify(ev.data)),\n)\n\nconst genWorkerName = () => 'module'\nconst w2 = new SharedWorker(\n  new URL('../url-shared-worker.js', import.meta.url),\n  {\n    name: genWorkerName(),\n    type: 'module',\n  },\n)\nw2.port.addEventListener('message', (ev) => {\n  text('.shared-worker-import-meta-url', JSON.stringify(ev.data))\n})\nw2.port.start()\n\nconst workers = import.meta.glob('../importMetaGlobEager.*.js', {\n  query: '?worker',\n  eager: true,\n})\nconst importMetaGlobEagerWorker = new workers[\n  '../importMetaGlobEager.worker.js'\n].default()\nimportMetaGlobEagerWorker.postMessage('1')\nimportMetaGlobEagerWorker.addEventListener('message', (e) => {\n  text('.importMetaGlobEager-worker', JSON.stringify(e.data))\n})\n\nconst selfReferenceWorker = new SelfReferenceWorker()\nselfReferenceWorker.postMessage('main')\nselfReferenceWorker.addEventListener('message', (e) => {\n  document.querySelector('.self-reference-worker').textContent += `${e.data}\\n`\n})\n\nconst selfReferenceUrlWorker = new Worker(\n  new URL('../self-reference-url-worker.js', import.meta.url),\n  {\n    type: 'module',\n  },\n)\nselfReferenceUrlWorker.postMessage('main')\nselfReferenceUrlWorker.addEventListener('message', (e) => {\n  document.querySelector('.self-reference-url-worker').textContent +=\n    `${e.data}\\n`\n})\n\n// only run on build\nif (!import.meta.hot) {\n  const cjsInteropWorker = new Worker(\n    new URL('../worker-require-json.js', import.meta.url),\n    { type: 'module' },\n  )\n  cjsInteropWorker.addEventListener('message', (e) => {\n    if (e.data.ok) {\n      text('.worker-require-json', e.data.content)\n    } else {\n      text('.worker-require-json', e.data.error)\n    }\n  })\n} else {\n  text('.worker-require-json', 'skipped in dev')\n}\n\ndepSelfReferenceUrlWorker.startWorker((e) => {\n  document.querySelector('.self-reference-url-worker-dep').textContent +=\n    `${e.data}\\n`\n})\n"
  },
  {
    "path": "playground/worker/worker/main-url.js",
    "content": "import workerUrl from '../simple-worker?worker&url'\n\nfunction text(el, text) {\n  document.querySelector(el).textContent = text\n}\n\nconst worker = new Worker(workerUrl, { type: 'module' })\n\nworker.addEventListener('message', (ev) => {\n  text('.simple-worker-url', JSON.stringify(ev.data))\n})\n"
  },
  {
    "path": "playground/worker/worker/main.js",
    "content": "/* flag: will replace in vite config import(\"./format-es.js\") */\nimport('./main-module')\nimport('./main-classic')\nimport('./main-url')\nimport('./main-deeply-nested')\n"
  },
  {
    "path": "playground/worker/worker-nested-worker.js",
    "content": "import ImportMetaGlobEagerWorker from './importMetaGlobEager.worker?worker'\nimport SubWorker from './sub-worker?worker'\n\nconst subWorker = new SubWorker()\n\nself.onmessage = (event) => {\n  if (event.data === 'ping') {\n    subWorker.postMessage('ping')\n  }\n}\n\nself.postMessage(self.location.href)\n\nsubWorker.onmessage = (ev) => {\n  self.postMessage({\n    type: 'module',\n    data: ev.data,\n  })\n}\n\nconst classicWorker = new Worker(new URL('./url-worker.js', import.meta.url), {\n  type: 'module',\n})\nclassicWorker.addEventListener('message', (ev) => {\n  self.postMessage({\n    type: 'constructor',\n    data: ev.data,\n  })\n})\n\nconst importMetaGlobEagerWorker = new ImportMetaGlobEagerWorker()\n\nimportMetaGlobEagerWorker.postMessage('1')\n\nimportMetaGlobEagerWorker.addEventListener('message', (ev) => {\n  self.postMessage({\n    type: 'importMetaGlobEager',\n    data: ev.data,\n  })\n})\n\n// for sourcemap\nconsole.log('worker-nested-worker.js')\n"
  },
  {
    "path": "playground/worker/worker-plugin-test-plugin.js",
    "content": "export default () => ({\n  name: 'plugin-for-worker',\n  transform(code, id) {\n    if (id.includes('worker/modules/test-plugin.js')) {\n      return {\n        // keep length for sourcemap\n        code: code.replace('plugin fail.   ', 'plugin success!'),\n        map: null,\n      }\n    }\n  },\n})\n"
  },
  {
    "path": "playground/worker/worker-require-json.js",
    "content": "import('./dep-cjs-with-json/importer.cjs')\n  .then((mod) => {\n    self.postMessage({ ok: true, content: JSON.stringify(mod.content) })\n  })\n  .catch((err) => {\n    self.postMessage({ ok: false, error: String(err) })\n  })\n"
  },
  {
    "path": "playground/worker/worker-sourcemap-config.js",
    "content": "import { defineConfig } from 'vite'\nimport workerPluginTestPlugin from './worker-plugin-test-plugin'\n\n/** @param {boolean | 'inline' | 'hidden' | 'sourcemap'} sourcemap */\nexport default (sourcemap) => {\n  sourcemap =\n    /** @type {'inline' | 'hidden' | 'sourcemap'} */ (\n      process.env.WORKER_MODE\n    ) || sourcemap\n\n  if (sourcemap === 'sourcemap') {\n    sourcemap = true\n  }\n\n  const typeName =\n    typeof sourcemap === 'boolean' ? 'sourcemap' : 'sourcemap-' + sourcemap\n\n  return defineConfig({\n    base: `/iife-${typeName}/`,\n    resolve: {\n      alias: {\n        '@': import.meta.dirname,\n      },\n    },\n    worker: {\n      format: 'iife',\n      plugins: () => [workerPluginTestPlugin()],\n      rollupOptions: {\n        output: {\n          assetFileNames: 'assets/[name]-worker_asset[hash].[ext]',\n          chunkFileNames: 'assets/[name]-worker_chunk[hash].js',\n          entryFileNames: 'assets/[name]-worker_entry[hash].js',\n        },\n      },\n    },\n    build: {\n      outDir: `dist/iife-${typeName}/`,\n      assetsInlineLimit: (filePath) =>\n        filePath.endsWith('.svg') ? false : undefined,\n      sourcemap: sourcemap,\n      rollupOptions: {\n        output: {\n          assetFileNames: 'assets/[name]-[hash].[ext]',\n          chunkFileNames: 'assets/[name]-[hash].js',\n          entryFileNames: 'assets/[name]-[hash].js',\n        },\n      },\n    },\n    plugins: [workerPluginTestPlugin()],\n    cacheDir: `node_modules/.vite-sourcemap-${typeName}`,\n  })\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/*'\n  - 'playground/**'\n  - 'packages/**/__tests__/**'\n  - docs\n\nhoistPattern:\n  - postcss # package/vite\n  - pug # playground/tailwind: @vue/compiler-sfc\n  - eslint-import-resolver-* # eslint-plugin-import-x\nshellEmulator: true\nautoInstallPeers: false\ndedupeInjectedDeps: false\noverrides:\n  rolldown: $rolldown\n  vite: 'workspace:*'\n  debug: 'npm:obug@^1.0.2'\npatchedDependencies:\n  \"sirv@3.0.2\": \"patches/sirv@3.0.2.patch\"\n  \"chokidar@3.6.0\": \"patches/chokidar@3.6.0.patch\"\n  \"dotenv-expand@12.0.3\": \"patches/dotenv-expand@12.0.3.patch\"\npeerDependencyRules:\n  allowedVersions:\n    vite: \"*\"\npackageExtensions:\n  sass-embedded:\n    peerDependencies:\n      source-map-js: \"*\"\n    peerDependenciesMeta:\n      source-map-js:\n        optional: true\n  '@rollup/plugin-dynamic-import-vars':\n    dependencies:\n      '@types/estree': ^1.0.0\nignoredBuiltDependencies:\n  - core-js\nonlyBuiltDependencies:\n  - \"@parcel/watcher\"\n  - \"@tailwindcss/oxide\"\n  - \"esbuild\"\n  - \"playwright-chromium\"\n  - \"sharp\"\n  - \"simple-git-hooks\"\n  - \"unrs-resolver\"\n  - \"workerd\"\n\ntrustPolicy: no-downgrade\ntrustPolicyExclude:\n  - chokidar@4.0.3 # https://github.com/paulmillr/chokidar/issues/1440\n  - semver@5.7.2 || 6.3.1\n  - tailwindcss@3.4.18\n  - undici-types@6.21.0 # https://github.com/nodejs/undici/issues/4666\n"
  },
  {
    "path": "scripts/docs-check.sh",
    "content": "echo \"prev commit: $CACHED_COMMIT_REF\"\necho \"current commit: $COMMIT_REF\"\nif [ \"$CACHED_COMMIT_REF\" = \"$COMMIT_REF\" ]; then\n  # builds runs without cache\n  exit 1\nfi\ngit diff --quiet $CACHED_COMMIT_REF $COMMIT_REF docs package.json pnpm-lock.yaml netlify.toml packages/vite/package.json scripts/docs-check.sh\nstatus=$?\necho \"diff exit code: $status\"\nexit $status\n"
  },
  {
    "path": "scripts/mergeChangelog.ts",
    "content": "/**\n * Merges prerelease (alpha/beta/rc) changelog entries into a single stable\n * release section within a package's CHANGELOG.md.\n *\n * Usage:\n *   pnpm merge-changelog <package> <version>\n *\n * Example:\n *   pnpm merge-changelog vite 8.0.0\n *\n * This will find the `## [8.0.0]` header in packages/vite/CHANGELOG.md,\n * collect all entries from its prerelease versions (e.g. 8.0.0-beta.1,\n * 8.0.0-rc.0), deduplicate and reorder them by category, append a\n * \"Beta Changelogs\" section with links to each prerelease's tagged\n * changelog, and write the merged result back to the file.\n */\nimport { readFile, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nconst pkg = process.argv[2]\nconst version = process.argv[3]\n\nif (!pkg || !version) {\n  console.error('Usage: pnpm merge-changelog <package> <version>')\n  process.exit(1)\n}\n\nconst CATEGORY_ORDER = [\n  '### ⚠ BREAKING CHANGES',\n  '### Features',\n  '### Bug Fixes',\n  '### Performance Improvements',\n  '### Documentation',\n  '### Miscellaneous Chores',\n  '### Code Refactoring',\n  '### Tests',\n]\n\nfunction escapeRegex(str: string): string {\n  return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nconst versionHeaderRe = /^## (?:<small>)?\\[/\n\nfunction findReleaseHeaderIndex(lines: string[], version: string): number {\n  const re = new RegExp(`^## (?:<small>)?\\\\[${escapeRegex(version)}\\\\]`)\n  const idx = lines.findIndex((l) => re.test(l))\n  if (idx === -1) {\n    console.error(`Could not find header for version ${version}`)\n    process.exit(1)\n  }\n  return idx\n}\n\nfunction findEndBoundary(\n  lines: string[],\n  startIdx: number,\n  version: string,\n): number {\n  const prereleaseRe = new RegExp(\n    `^## (?:<small>)?\\\\[${escapeRegex(version)}-(beta|alpha|rc)\\\\.\\\\d+\\\\]`,\n  )\n  for (let i = startIdx + 1; i < lines.length; i++) {\n    if (versionHeaderRe.test(lines[i]) && !prereleaseRe.test(lines[i])) {\n      return i\n    }\n  }\n  return lines.length\n}\n\nfunction parseCategories(releaseLines: string[]): Map<string, string[]> {\n  const categories = new Map<string, string[]>()\n  let currentCategory: string | null = null\n\n  for (let i = 1; i < releaseLines.length; i++) {\n    const line = releaseLines[i]\n    if (versionHeaderRe.test(line)) {\n      currentCategory = null\n      continue\n    }\n    if (line.startsWith('### ')) {\n      currentCategory = line.trim()\n      if (!categories.has(currentCategory)) {\n        categories.set(currentCategory, [])\n      }\n      continue\n    }\n\n    if (currentCategory && line.trim() !== '') {\n      categories.get(currentCategory)!.push(line)\n    }\n  }\n\n  return categories\n}\n\nfunction findPreviousStableVersion(lines: string[], startIdx: number): string {\n  for (let i = startIdx; i < lines.length; i++) {\n    const match = lines[i].match(/^## (?:<small>)?\\[([^\\]]+)\\]/)\n    if (match) {\n      const v = match[1]\n      if (!/alpha|beta|rc/.test(v)) {\n        return v\n      }\n    }\n  }\n  return ''\n}\n\nfunction updateHeaderCompareLink(\n  headerLine: string,\n  prevStable: string,\n  pkg: string,\n  version: string,\n): string {\n  if (!prevStable) return headerLine\n  const tagPrefix = pkg === 'vite' ? 'v' : `${pkg}@`\n  return headerLine.replace(\n    /compare\\/[^)]+/,\n    `compare/${tagPrefix}${prevStable}...${tagPrefix}${version}`,\n  )\n}\n\nfunction collectPrereleaseHeaders(\n  releaseLines: string[],\n  pkg: string,\n): string[] {\n  const lines: string[] = []\n  for (const line of releaseLines) {\n    const match = line.match(\n      /^## (?:<small>)?\\[([^\\]]+)\\]\\(([^)]+)\\)(?: \\((\\d{4}-\\d{2}-\\d{2})\\))?/,\n    )\n    if (!match) continue\n    const [, ver, compareUrl, date] = match\n    if (!/alpha|beta|rc/.test(ver)) continue\n\n    const tagPrefix = pkg === 'vite' ? 'v' : `${pkg}@`\n    const tag = `${tagPrefix}${ver}`\n    const header = date\n      ? `#### [${ver}](${compareUrl}) (${date})`\n      : `#### [${ver}](${compareUrl})`\n    lines.push(\n      header,\n      '',\n      `See [${ver} changelog](https://github.com/vitejs/vite/blob/${tag}/packages/${pkg}/CHANGELOG.md)`,\n      '',\n    )\n  }\n  return lines\n}\n\nfunction buildOutputLines(\n  headerLine: string,\n  categories: Map<string, string[]>,\n  prereleaseLines: string[],\n): string[] {\n  const hasUnknownCategories = [...categories.keys()].filter(\n    (c) => !CATEGORY_ORDER.includes(c),\n  )\n  if (hasUnknownCategories.length > 0) {\n    throw new Error(\n      `Unknown categories found: ${hasUnknownCategories.join(', ')}`,\n    )\n  }\n\n  const outputLines: string[] = [headerLine, '']\n  for (const category of CATEGORY_ORDER) {\n    const items = categories.get(category)\n    if (items && items.length > 0) {\n      outputLines.push(category, '')\n      outputLines.push(...items)\n      outputLines.push('')\n    }\n  }\n\n  if (prereleaseLines.length > 0) {\n    outputLines.push('### Beta Changelogs', '', ...prereleaseLines)\n  }\n\n  return outputLines\n}\n\nconst filePath = path.resolve(\n  // eslint-disable-next-line n/no-unsupported-features/node-builtins\n  import.meta.dirname,\n  `../packages/${pkg}/CHANGELOG.md`,\n)\nconst content = await readFile(filePath, 'utf-8')\nconst lines = content.split('\\n')\n\nconst releaseHeaderIdx = findReleaseHeaderIndex(lines, version)\nconst endIdx = findEndBoundary(lines, releaseHeaderIdx, version)\nconst releaseLines = lines.slice(releaseHeaderIdx, endIdx)\n\nconst categories = parseCategories(releaseLines)\nconst prereleaseLines = collectPrereleaseHeaders(releaseLines, pkg)\nconst prevStable = findPreviousStableVersion(lines, endIdx)\nconst headerLine = updateHeaderCompareLink(\n  releaseLines[0],\n  prevStable,\n  pkg,\n  version,\n)\nconst outputLines = buildOutputLines(headerLine, categories, prereleaseLines)\n\nconst result = [\n  ...lines.slice(0, releaseHeaderIdx),\n  ...outputLines,\n  ...lines.slice(endIdx),\n].join('\\n')\n\nawait writeFile(filePath, result, 'utf-8')\nconsole.log(`Merged prerelease changelog sections for ${version} in ${pkg}`)\n"
  },
  {
    "path": "scripts/publishCI.ts",
    "content": "import { publish } from '@vitejs/release-scripts'\n\npublish({ defaultPackage: 'vite', packageManager: 'pnpm' })\n"
  },
  {
    "path": "scripts/release.ts",
    "content": "import { generateChangelog, release } from '@vitejs/release-scripts'\nimport colors from 'picocolors'\nimport { logRecentCommits, updateTemplateVersions } from './releaseUtils'\n\nrelease({\n  repo: 'vite',\n  packages: ['vite', 'create-vite', 'plugin-legacy'],\n  toTag: (pkg, version) =>\n    pkg === 'vite' ? `v${version}` : `${pkg}@${version}`,\n  logChangelog: (pkg) => logRecentCommits(pkg),\n  generateChangelog: async (pkgName) => {\n    if (pkgName === 'create-vite') await updateTemplateVersions()\n\n    console.log(colors.cyan('\\nGenerating changelog...'))\n\n    await generateChangelog({\n      getPkgDir: () => `packages/${pkgName}`,\n      tagPrefix: pkgName === 'vite' ? undefined : `${pkgName}@`,\n    })\n  },\n})\n"
  },
  {
    "path": "scripts/releaseUtils.ts",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport colors from 'picocolors'\nimport type { Options as ExecaOptions, ResultPromise } from 'execa'\nimport { execa } from 'execa'\n\nfunction run<EO extends ExecaOptions>(\n  bin: string,\n  args: string[],\n  opts?: EO,\n): ResultPromise<\n  EO & (keyof EO extends 'stdio' ? object : { stdio: 'inherit' })\n> {\n  return execa(bin, args, { stdio: 'inherit', ...opts }) as any\n}\n\nexport async function getLatestTag(pkgName: string): Promise<string> {\n  const pkgJson = JSON.parse(\n    await fs.readFile(`packages/${pkgName}/package.json`, 'utf-8'),\n  )\n  const version = pkgJson.version\n  return pkgName === 'vite' ? `v${version}` : `${pkgName}@${version}`\n}\n\nexport async function logRecentCommits(pkgName: string): Promise<void> {\n  const tag = await getLatestTag(pkgName)\n  if (!tag) return\n  const sha = await run('git', ['rev-list', '-n', '1', tag], {\n    stdio: 'pipe',\n  }).then((res) => res.stdout.trim())\n  console.log(\n    colors.bold(\n      `\\n${colors.blue(`i`)} Commits of ${colors.green(\n        pkgName,\n      )} since ${colors.green(tag)} ${colors.gray(`(${sha.slice(0, 5)})`)}`,\n    ),\n  )\n  await run(\n    'git',\n    [\n      '--no-pager',\n      'log',\n      `${sha}..HEAD`,\n      '--oneline',\n      '--',\n      `packages/${pkgName}`,\n    ],\n    { stdio: 'inherit' },\n  )\n  console.log()\n}\n\nexport async function updateTemplateVersions(): Promise<void> {\n  const vitePkgJson = JSON.parse(\n    await fs.readFile('packages/vite/package.json', 'utf-8'),\n  )\n  const viteVersion = vitePkgJson.version\n  if (/beta|alpha|rc/.test(viteVersion)) return\n\n  const dir = 'packages/create-vite'\n  const templates = (await fs.readdir(dir)).filter((dir) =>\n    dir.startsWith('template-'),\n  )\n  for (const template of templates) {\n    const pkgPath = path.join(dir, template, `package.json`)\n    const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf-8'))\n    pkg.devDependencies.vite = `^` + viteVersion\n    await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\\n')\n  }\n}\n"
  },
  {
    "path": "scripts/tsconfig.json",
    "content": "{\n  \"$schema\": \"https://json.schemastore.org/tsconfig\",\n  \"include\": [\".\"],\n  \"compilerOptions\": {\n    \"module\": \"Preserve\",\n    \"target\": \"ES2023\",\n    \"moduleResolution\": \"bundler\",\n    \"types\": [\"node\"],\n    \"noEmit\": true,\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"erasableSyntaxOnly\": true,\n    \"skipLibCheck\": true,\n    \"noUnusedLocals\": true\n  }\n}\n"
  },
  {
    "path": "vitest.config.e2e.ts",
    "content": "import { resolve } from 'node:path'\nimport { defaultExclude, defineConfig } from 'vitest/config'\n\nconst isBuild = !!process.env.VITE_TEST_BUILD\n\nconst timeout = process.env.PWDEBUG ? Infinity : process.env.CI ? 50000 : 30000\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      // eslint-disable-next-line n/no-unsupported-features/node-builtins\n      '~utils': resolve(import.meta.dirname, './playground/test-utils'),\n    },\n  },\n  test: {\n    include: ['./playground/**/*.spec.[tj]s'],\n    exclude: [\n      ...(isBuild\n        ? [\n            './playground/object-hooks/**/*.spec.[tj]s', // object hook sequential\n          ]\n        : []),\n      ...defaultExclude,\n    ],\n    setupFiles: ['./playground/vitestSetup.ts'],\n    globalSetup: ['./playground/vitestGlobalSetup.ts'],\n    testTimeout: timeout,\n    hookTimeout: timeout,\n    reporters: 'dot',\n    deps: {\n      // Prevent Vitest from running the workspace packages in Vite's SSR runtime\n      moduleDirectories: ['node_modules', 'packages'],\n    },\n    expect: {\n      poll: {\n        timeout: 50 * (process.env.CI ? 200 : 50),\n      },\n    },\n    env: {\n      NODE_ENV: process.env.VITE_TEST_BUILD ? 'production' : 'development',\n    },\n  },\n  oxc: {\n    target: 'node20',\n  },\n  publicDir: false,\n})\n"
  },
  {
    "path": "vitest.config.ts",
    "content": "import path from 'node:path'\nimport url from 'node:url'\nimport { defineConfig } from 'vitest/config'\n\nconst _dirname = path.dirname(url.fileURLToPath(import.meta.url))\n\nexport default defineConfig({\n  test: {\n    include: ['**/__tests__/**/*.spec.[tj]s'],\n    exclude: [\n      '**/node_modules/**',\n      '**/dist/**',\n      './playground/**/*.*',\n      './playground-temp/**/*.*',\n    ],\n    deps: {\n      // we specify 'packages' so Vitest doesn't inline the files\n      moduleDirectories: ['node_modules', 'packages'],\n    },\n    testTimeout: 20000,\n    isolate: false,\n  },\n  oxc: {\n    target: 'node20',\n  },\n  publicDir: false,\n  resolve: {\n    alias: {\n      'vite/module-runner': path.resolve(\n        _dirname,\n        './packages/vite/src/module-runner/index.ts',\n      ),\n    },\n  },\n})\n"
  }
]